[De1CTF 2019]SSRF Me

[De1CTF 2019]SSRF Me

Investigation, code audit hash extended length

Source follows

The key point add a little comment

#! /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):#python得构造方法
        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):#定义的命令执行函数,此处调用了scan这个自定义的函数
        result = {}
        result['code'] = 500
        if (self.checkSign()):
            if "scan" in self.action:#action要写scan
                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:#action要加read
                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):#!!!这个应该是本题关键点,此处注意顺序先是param后是action
    return hashlib.md5(secert_key + param + action).hexdigest()


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


def waf(param):#这个waf比较没用好像
    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')

First explain part of the function:

Row function Explanation
Line 20 init(self, action, param, ...) Constructors self represents the object, the other is a property of an object
71 request.args.get(param) The method of extraction get passed, corresponding to the parameter param name Found
70 request.cookies.get("action") Cookie information is extracted, called an action to obtain corresponding values
92 hashlib.md5().hexdigest() hashlib.md5 () # md5 obtain a target encryption algorithm , hexdigest () is obtained hexadecimal string encryption roar
70,71,72 urllib.unquote() The url codec
87 urllib.urlopen() Network File parameter can be read url
77 json.dumps Python objects encoded as JSON string

General process:

image-20200401193522563

Exec critical code

After reading the code can understand the whole

1. We need to cross check checkSign, getSign(self.action, self.param) == self.sign,

When secert_key + param + sign and the same hexadecimal contents hash to the action by checking.

In 2.action have read and scan,

3.param flag can be read by a flag.txt scan function.

image-20200401191940039

CheckSign difficulty is checking function, which is getSign check.

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

Since we do not value secert_key, so originally I did not have a way.

But / geneSign route, exposed getSign function,

We can go to get the correct sign value according to the routing getSign.

image-20200401192348317

Get sign with geneSign route

Value of the action is mandatory scan, it can not fill fill.

sign: 911db68eab96df16a18bc3521fb10d3d

get parameter passing:

​ param=flag.txt

cookie:

​ action=action

​ sign=911db68eab96df16a18bc3521fb10d3d

image-20200401193217290

Guess you like

Origin www.cnblogs.com/h3zh1/p/12615062.html
Recommended