0x00:
源码
#! /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) ################ #16位1scan的md5=fdb77515270210ce2b7b2c4961fe0186 ############### @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从路由开始看
/geneSign:功能是指定action=scan 然后get接收一个param参数 进行getSign md5加密处理
这里secert_key为16位随机数,基本看到这里基本有个思路hash长度扩展攻击
这里思路就是同时需要action存在scan和read
因为这里的if "scan" in self.action: 而不是==所以可以以此来进行绕过
(这里在Task 类的Exec函数 scan模块这里存在一个print操作,但为什么不能直接打印出flag呢
因为存在json.dumps,处理字典为str,所以页面就会以json返回,print函数执行了 但不会在页面显示,在服务器控制台进行打印
所以需要scan把flag写入result.txt文件,然后read再去读取
所以三种做法
依据https://xz.aliyun.com/t/5927
这里记录一下第三种
urllib.urlopen(param) 去包含的文件
且urllib.urlopen(param) 进行读取的时候,如果param不存在协议的时候,默认使用file协议
urllib.urlopen(param) 这里param可以使用file或者local_file进行读取,不过file被过滤了,local_file:///app/flag.txtread
且urllib.urlopen(param) 文
件路径不支持./file这种写法。file,/file,../file都是支持的
如果使用 urllib2.urlopen(param) 去包含文件就必须加上 file
,否则会报 ValueError: unknown url type: /path/to/file
的错误
原文:https://www.cnblogs.com/Tkitn/p/13661173.html