博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
BUUCTF [De1CTF 2019]SSRF Me
阅读量:2066 次
发布时间:2019-04-29

本文共 4197 字,大约阅读时间需要 13 分钟。

  • 审计一下源码,稍微加了一些注释
#! /usr/bin/env python#encoding=utf-8from flask import Flaskfrom flask import requestimport socketimport hashlibimport urllibimport sysimport osimport jsonreload(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()):#调用checkSign函数来判段 if "scan" in self.action: #action中要有scan tmpfile = open("./%s/result.txt" % self.sandbox, 'w') resp = scan(self.param) # 自定义的scan()函数读取文件 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): # checkSign用于上面的校验 if (getSign(self.action, self.param) == self.sign): return True else: return False#generate Sign For Action Scan.@app.route("/geneSign", methods=['GET', 'POST'])# /geneSign路由 def geneSign(): param = urllib.unquote(request.args.get("param", "")) # request.args.get()用于获取url上的参数 这里获取param action = "scan" return getSign(action, param)@app.route('/De1ta',methods=['GET','POST']) # 这里执行了Exec(),应该是最后的注入点# /De1ta路由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()) # json.dump将python对象转为python对象@app.route('/')def index(): return open("code.txt","r").read() # 我们点入题目后的页面 返回的就是源代码def scan(param): socket.setdefaulttimeout(1) # 经过1秒后,如果还未下载成功,自动跳入下一次操作, try: return urllib.urlopen(param).read()[:50] except: return "Connection Timeout"def getSign(action, param): return hashlib.md5(secert_key + param + action).hexdigest() # action和param的md5加密def md5(content): return hashlib.md5(content).hexdigest() # 文件内容的md5加密def waf(param): check=param.strip().lower() if check.startswith("gopher") or check.startswith("file"): # gopher协议和file协议的waf 提醒我去复习gopher协议了 return True else: return Falseif __name__ == '__main__': app.debug = False app.run(host='0.0.0.0')
  • 审计完代码 简单的总结一下
  • Flask框架下 有三个路由
  • /geneSign:用于测试页面返回的是md5加密后的secert_key + param + action
  • /De1ta:题目的核心部分
action = urllib.unquote(request.cookies.get("action"))param = urllib.unquote(request.args.get("param", ""))sign = urllib.unquote(request.cookies.get("sign"))ip = request.remote_addrtask = Task(action, param, sign, ip)return json.dumps(task.Exec())
  • 获取一系列的数据,param过滤了gopher和file,生成Task对象,调用Exec()命令执行函数去读取文件
  • /:返回源代码,没什么用 题目给了下载的地方
  • 在执行Exec()函数的第一步有一个if(self.checkSign())
def checkSign(self): # checkSign用于上面的校验    if (getSign(self.action, self.param) == self.sign):        return True    else:        eturn Falsedef getSign(action, param):    return hashlib.md5(secert_key + param + action).hexdigest()
  • 所以我们传入的sign要和getSign()生成的sign一致
  • 所以我们访问/geneSign路由get上传?param=flag.txtread
  • adf80ee5dfe9c60c8575ebd2c8baacf1页面返回
  • 这个就是当action=readscan param=flag.txt时 页面返回的md5加密后的值
  • 因为action在生成的时候已经固定为scan了 所以只需要param=readscan
def geneSign():    param = urllib.unquote(request.args.get("param", ""))    # request.args.get()用于获取url上的参数 这里获取param    action = "scan"    return getSign(action, param)

转载地址:http://eywmf.baihongyu.com/

你可能感兴趣的文章
绑定CPU逻辑核心的利器——taskset
查看>>
Linux下perf性能测试火焰图只显示函数地址不显示函数名的问题
查看>>
c结构体、c++结构体和c++类的区别以及错误纠正
查看>>
Linux下查看根目录各文件内存占用情况
查看>>
A星算法详解(个人认为最详细,最通俗易懂的一个版本)
查看>>
利用栈实现DFS
查看>>
逆序对的数量(递归+归并思想)
查看>>
数的范围(二分查找上下界)
查看>>
算法导论阅读顺序
查看>>
Windows程序设计:直线绘制
查看>>
linux之CentOS下文件解压方式
查看>>
Django字段的创建并连接MYSQL
查看>>
div标签布局的使用
查看>>
HTML中表格的使用
查看>>
(模板 重要)Tarjan算法解决LCA问题(PAT 1151 LCA in a Binary Tree)
查看>>
(PAT 1154) Vertex Coloring (图的广度优先遍历)
查看>>
(PAT 1115) Counting Nodes in a BST (二叉查找树-统计指定层元素个数)
查看>>
(PAT 1143) Lowest Common Ancestor (二叉查找树的LCA)
查看>>
(PAT 1061) Dating (字符串处理)
查看>>
(PAT 1118) Birds in Forest (并查集)
查看>>