首页 > 其他分享 >SSRF类型的CTF题目[De1CTF 2019]SSRF Me1

SSRF类型的CTF题目[De1CTF 2019]SSRF Me1

时间:2024-09-26 20:20:04浏览次数:14  
标签:return SSRF scan De1CTF self param CTF result action

启动BUUCTF靶场,先查看一下提示:

显示出flag的文件路径是/flag.txt

发现是一段python代码,整理一下:

#! /usr/bin/env python
#encoding=utf-8
from flask import Flask
from flask import request
import socket
import hashlib
import urllib
import sys
import os
import json
reload(sys)
sys.setdefaultencoding('latin1')

app = Flask(__name__)

secert_key = os.urandom(16)


class Task:
    def __init__(self, action, param, sign, ip):
        self.action = action
        self.param = param
        self.sign = sign
        self.sandbox = md5(ip)
        if(not os.path.exists(self.sandbox)):          #SandBox For Remote_Addr
            os.mkdir(self.sandbox)

    def Exec(self):
        result = {}
        result['code'] = 500
        if (self.checkSign()):
            if "scan" in self.action:
                tmpfile = open("./%s/result.txt" % self.sandbox, 'w')
                resp = scan(self.param)
                if (resp == "Connection Timeout"):
                    result['data'] = resp
                else:
                    print resp
                    tmpfile.write(resp)
                    tmpfile.close()
                result['code'] = 200
            if "read" in self.action:
                f = open("./%s/result.txt" % self.sandbox, 'r')
                result['code'] = 200
                result['data'] = f.read()
            if result['code'] == 500:
                result['data'] = "Action Error"
        else:
            result['code'] = 500
            result['msg'] = "Sign Error"
        return result

    def checkSign(self):
        if (getSign(self.action, self.param) == self.sign):
            return True
        else:
            return False


#generate Sign For Action Scan.
@app.route("/geneSign", methods=['GET', 'POST'])
def geneSign():
    param = urllib.unquote(request.args.get("param", ""))
    action = "scan"
    return getSign(action, param)


@app.route('/De1ta',methods=['GET','POST'])
def challenge():
    action = urllib.unquote(request.cookies.get("action"))
    param = urllib.unquote(request.args.get("param", ""))
    sign = urllib.unquote(request.cookies.get("sign"))
    ip = request.remote_addr
    if(waf(param)):
        return "No Hacker!!!!"
    task = Task(action, param, sign, ip)
    return json.dumps(task.Exec())
@app.route('/')
def index():
    return open("code.txt","r").read()


def scan(param):
    socket.setdefaulttimeout(1)
    try:
        return urllib.urlopen(param).read()[:50]
    except:
        return "Connection Timeout"



def getSign(action, param):
    return hashlib.md5(secert_key + param + action).hexdigest()


def md5(content):
    return hashlib.md5(content).hexdigest()


def waf(param):
    check=param.strip().lower()
    if check.startswith("gopher") or check.startswith("file"):
        return True
    else:
        return False


if __name__ == '__main__':
    app.debug = False
    app.run(host='0.0.0.0')

这段代码实现了一个简单的 Flask web 应用程序,主要功能是处理特定的网络请求并执行一些操作。下面逐步分析代码的主要部分:

导入库:

Flask 用于创建 web 应用,request 用于处理 HTTP 请求。

socket, hashlib, urllib, sys, os, json 是用于网络、加密、URL 处理、系统操作和 JSON 数据操作的库。


Flask 应用程序:

创建一个 Flask 应用实例 app。


密钥生成:

secert_key = os.urandom(16) 生成一个随机的 16 字节的密钥,用于后续的签名生成。


任务类 Task:

__init__ 方法:初始化一个任务,接收 action、param、sign 和 ip。并使用 MD5 对 IP 地址进行哈希,作为沙盒文件夹的名称。检查沙盒文件夹是否存在,如果不存在则创建。


Exec 方法:根据 action 执行相应的操作。

如果 checkSign() 返回真,继续执行;

如果 action 包含 "scan",则尝试通过 scan(param) 函数获取参数的响应,并将响应写入 result.txt 文件;

如果 action 包含 "read",则读取 result.txt 内容。

如果未匹配到有效操作或签名不正确,返回相应错误信息。


签名生成接口:

geneSign 路由:接收参数并返回该参数的签名,签名使用 getSign 方法生成。


挑战接口:

challenge 路由:获取请求中的 action、param 和 sign,并获取请求的 IP 地址。

调用 waf(param) 检查参数是否合法,如果不合法则返回 "No Hacker!!!!"。

创建 Task 实例并执行。


首页路由:

index 路由:返回名为 "code.txt" 的文件内容。


网络请求处理:

scan(param) 函数尝试访问给定的 URL,并返回前 50 个字符,超时则返回 "Connection Timeout"。


签名生成函数 getSign:

使用 hashlib.md5 对密钥、参数和动作进行哈希处理,生成签名。


MD5 哈希函数:

md5(content) 函数对给定内容进行 MD5 哈希处理。


WAF(Web 应用防火墙)检查:

waf(param) 检查参数是否以 "gopher" 或 "file" 开头,若是则返回真,表示参数不合法。


运行应用:

在主程序中运行 Flask 应用,监听所有 IP 地址。

总体来看,这段代码是一个简单的 web 服务,允许执行网络请求并对输入参数进行一些安全性检查,同时实现了基本的请求签名机制。


发现代码中中有两处地方可以传参(/geneSign和 /De1ta)


先看一下调用函数Task的函数(/De1ta的函数):

可以传入可控的action,param,sign三个函数


先经过waf判断:

param中不能有'gopher'和'file',然后最后return json.dumps(task.Exec())


而task.Exec()最后return result,所以我们判断,最后应该要将return的值等于flag,即return flag


看一下Exec()的构成

可以看到跟checkSign()函数有关


溯源checkSign():

可以看到跟getSign()函数有关


溯源getSign():

即让(secert_key + param + action)的md5值等于sign

但secert_key的值不知道,所以要用到第一个路由(/geneSign)


再来看(/geneSign)的函数:

action="scan"的值已经给定,我们只能控制param的值。

最后return getSign(action,param)

得到secert_key + param + action的md5值。(即secert_key + param + 'scan')


了解到关键词'scan'立马想到Exec()函数有关:

第一个if要求传入的action中含有scan,然后调用scan函数从文件中查找param这个文件,将文件名给resp,然后通过tmpfile函数写入result.txt中,且令它连通。即(code=200);

第二个if要求传入的action中含有read,然后从result.txt中查找连通的文件作为f,并让result['data']=f.read得到它的内容。最后return result输出内容。

所以此处的action必须为含read和scan。


而/geneSign路由中规定的action必须为scan。但可以控制param

而/De1ta路由中两个值都可以控制。

且两者最后的secert_key + param + action相等。我们已知flag在flag.txt中,而且最终要通过/De1ta中的param来得到,所以/De1ta中的param=flag.txt


所以,在(/geneSign路由)中param=flag.txt,读取action,此时action='scan'

构造payload:

/geneSign?param=flag.txtread

得到一个值,是md5值,再来看看先前的回顾:


再来看(/De1ta路由)

令param=flag.txt,action='readscan'

这样,最后secert_key + param + action==sign的值


用burp抓包,修改cookie内容:(/De1ta?param=flag.txt)

Cookie:action=readscan;sign=adf22554dca69e25f96ce25d67b84444

(注意:做到现在,脑子糊涂了,不知道怎么解释了,就硬撑着做下去了)

得到flag:

flag{0bb9d18a-aed4-456d-9fa6-de37c90a7a54}

成功了,但身心疲惫

标签:return,SSRF,scan,De1CTF,self,param,CTF,result,action
From: https://blog.csdn.net/weixin_73049307/article/details/142577194

相关文章

  • nssctf(web
    web1.浏览器也能套娃查看wp,是ssrf漏洞介绍:SSRF漏洞产生的原因是服务端提供了能够从其他服务器应用获取数据的功能,比如从指定的URL地址获取网页内容,加载指定地址的图片、数据、下载等等。SSRF的利用:进行内网资源的访问:url?url=http://内网的资源url利用伪协议:file:///这种......
  • CTFSHOW pwn03 WrriteUp
    本文来自一个初学CTF的小白,如有任何问题请大佬们指教!题目来源CTFShowpwn-pwn03(ret2libc)https://ctf.show/challenges思路1.下载题目放到checksec先查一下2.IDA打开题目Shift+F12查看字符串发现没有system和/bin/sh,但是有libc文件。3.用gdb的cyclic查询一下溢出所......
  • CTF入门教程(非常详细)从零基础入门到竞赛,看这一篇就够了!
        一、CTF简介CTF(CaptureTheFlag)中文一般译作夺旗赛,在网络安全领域中指的是网络安全技术人员之间进行技术竞技的一种比赛形式。CTF起源于1996年DEFCON全球黑客大会,以代替之前黑客们通过互相发起真实攻击进行技术比拼的方式。发展至今,已经成为全球范围网络安全圈流行......
  • CTF入门教程(非常详细)从零基础入门到竞赛,看这一篇就够了!
        一、CTF简介CTF(CaptureTheFlag)中文一般译作夺旗赛,在网络安全领域中指的是网络安全技术人员之间进行技术竞技的一种比赛形式。CTF起源于1996年DEFCON全球黑客大会,以代替之前黑客们通过互相发起真实攻击进行技术比拼的方式。发展至今,已经成为全球范围网络安全圈流行......
  • byteCTF 2024 ezobj(复现)
    byteCTF2024ezobj(复现)ezobj(复现)开题:<?phpini_set("display_errors","On");include_once("config.php");if(isset($_GET['so'])&&isset($_GET['key'])){if(is_numeric($_GET['so'])......
  • [SKSEC::CTF新生web专题训练赛] week1 writeup
    1.扫雷游戏(js)随便点格子,当点到第二个时,会判定踩雷失败,浏览器给出gameover的提示并刷新网页。F12从来源中找到saolei.js,找到gameover所在的函数if分支。if(block.isMine){block.innerHTML='......
  • [MRCTF2020]Ezpop
    [MRCTF2020]EzpopWelcometoindex.php<?php//flagisinflag.php//WTFISTHIS?//LearnFromhttps://ctf.ieki.xyz/library/php.html#%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E9%AD%94%E6%9C%AF%E6%96%B9%E6%B3%95//AndCrackIt!classModifier{protected......
  • 【CTF Web】BUUCTF SQLi-LABS Page-1(Basic Challenges) Less-3 Writeup(SQL注入+GET请
    sqli-labs1点击启动靶机。SQLi-LABSPage-1(BasicChallenges)解法发送GET请求,id作为参数。http://b38e0f15-7e65-40e6-abf2-fc99e50b38e4.node5.buuoj.cn/Less-3/?id=1返回了用户名和密码。?id=1'发生报错。闭合括号:?id=1');--+正常输出。判断......
  • 【CTF Web】BUUCTF SQLi-LABS Page-1(Basic Challenges) Less-4 Writeup(SQL注入+GET请
    sqli-labs1点击启动靶机。SQLi-LABSPage-1(BasicChallenges)解法发送GET请求,id作为参数。http://b38e0f15-7e65-40e6-abf2-fc99e50b38e4.node5.buuoj.cn/Less-4/?id=1返回了用户名和密码。?id=1'正常输出。?id=1"发生报错。构造闭合:?id=1");--......
  • [vulnhub] LAMPSecurity: CTF4
    https://www.vulnhub.com/entry/lampsecurity-ctf4,83/端口扫描主机发现探测存活主机,138是靶机nmap-sP192.168.75.0/24//StartingNmap7.93(https://nmap.org)at2024-09-2314:13CSTNmapscanreportfor192.168.75.1H......