刷题[De1CTF 2019]SSRF Me
前置知识
本题框架是flask框架,正好python面向对象和flask框架没怎么学,借着这个好好学一下
这里我直接听mooc上北京大学陈斌老师的内容,因为讲的比较清楚,直接把他的ppt拿过来,看看就懂了


解题思路

直接给源码,得知是python,flask框架。审就完事了
代码审计
#! /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',port=80)
代码量不是很长,大概意思是创建了一个Task类,定义了若干个函数,利用时再剖析,三个路由
geneSign路由:
其调用了getSign函数,返回了经md5处理的值De1ta路由:
通过get方法传入param的值,在cookie中传入action和sign的值,将param通过waf函数。再用传入的参数构造一个Task类,执行Exec函数。
首先看waf函数,禁了gopher协议和file协议,这么打ssrf打不了了。
再看exec函数,大概就是先判断成功登陆,登陆成功后,读经过scan扫描的param,那么思路就出来了,如果我们传入param的值为flag.txt,并且令action里面有scan和read这两个参数,即可读取内容/路由:
根目录路由,指定了访问根目录时,会读整个源码,并定义了一些基础函数
大概思路明确了。
保证checkSign函数返回真
保证 getSign(self.action, self.param) == self.sign
即经过hashlib.md5(secert_key + param + action).hexdigest()处理
需要知道这三个字符串连接后的md5值,但是纵观源码并没有哪里有secert_key
方法一 字符串拼接
我们又发现很有意思的一点,确认action的值时,使用的是in,并非是等于号,也就是说只要read在action里即可。
因为使用的是连接符号加号(+),那么传入这两个值时
md5(secert_key + 'flag.txt' + 'readscan')
md5(secert_key + 'flag.txtread' + 'scan')
其实是相同的字符串md5(secert_keyflag.txtreadscan),经md5处理当然也相同
我们先令/geneSign?param=flag.txtread。在此页面下我们可以获得md5(secert_key + 'flag.txtread' + 'scan') 的值
再访问/De1ta路由,在其中传入cookie值和get请求即可获得对应的flag

方法二 哈希长度扩展攻击
git clone https://github.com/bwall/HashPump.git
$ apt-get install g++ libssl-dev
$ cd HashPump
$ make
$ make install
首先在kali机下安装,这里我的kali机没换国内源。。。先换国内源,然后如果有问题的话aptitude降级安装
一步一步敲命令,完成后
使用方法:
使用方法:
Input Signature 为md5(salt+message)的值
Input Data 为message内容
Input Key Length 为salt+message长度
Input Data to Add 为自定义添加

(因为代码中告诉了secert_key为16位,这里的sat看成16位的secert_key+8位的flag.txt即24位)
算出最后的值同样放在cookie中即可(\x记得换成%,即url形式)
CVE-2019-9948
Python 2.x到2.7.16中的urllib支持local_file
local_file允许远程攻击者绕过保护机制
这里是使用的 urllib.urlopen(param) 去包含的文件,所以可以直接加上文件路径 flag.txt 或 ./flag.txt 去访问,也可以使用类似的 file:///app/flag.txt 去访问,但是 file 关键字在黑名单里,可以使用 local_file 代替
如果使用 urllib2.urlopen(param) 去包含文件就必须加上 file ,否则会报 ValueError: unknown url type: /path/to/file 的错误
总结思路
- 踏实的代码审计功底
- MD5扩展攻击
- 搜索cve,拿poc打
知识点
- python代码审计
- md5扩展攻击
刷题[De1CTF 2019]SSRF Me的更多相关文章
- 刷题记录:[De1CTF 2019]SSRF Me
目录 刷题记录:[De1CTF 2019]SSRF Me 一.涉及知识点 1.MD5长度扩展攻击 2.Python 2.x - 2.7.16 urllib.fopen支持local_file导致LFI ...
- [De1CTF 2019]SSRF Me
原帖地址 : https://xz.aliyun.com/t/5927 De1CTF 2019 的一个题目总结 题目描述 直接查看页面源代码可以看到正确格式的代码 #! /usr/bin/env py ...
- [De1CTF 2019]SSRF Me-MD5长度扩展攻击&CVE-2019-9948
0x00 打开题目查看源代码,开始审计 这里贴上网上师傅的博客笔记: https://xz.aliyun.com/t/6050 #! /usr/bin/env python #encoding=utf ...
- BUUCTF | [De1CTF 2019]SSRF Me
解法一字符串拼接: 1.得到签名sign http://8fa4531c-1164-49b7-a700-70e77e6aacb7.node3.buuoj.cn/geneSign?param=flag. ...
- 刷题[GWCTF 2019]mypassword
解题思路 打开网站,登陆框.注册一个用户后再登陆 看样子是注入了,在feedback.php中发现注释 <!-- if(is_array($feedback)){ echo "< ...
- 刷题[GWCTF 2019]你的名字
解题思路 打开发现需要输入名字,猜测会有sql注入漏洞,测试一下发现单引号被过滤了,再fuzs下看看过滤了哪些 长度为1518和1519的都有过滤,测试一下,感觉不是sql注入了.那还有什么呢,考虑了 ...
- 刷题[RCTF 2019]Nextphp
前置知识 一些关于php7.4版本需知: 1.FFI扩展:ffi.cdef 其中还有这样一段话 如果ffi.cdef没有第二个参数,会在全局查找,第一个参数所声明的符号.意思就是其在不传入第二个参数时 ...
- 刷题[SUCTF 2019]CheckIn
解题思路 打开网页发现只是简单做了一个上传界面,朴实无华 上传一个php文件,发现非法后缀. 上传一个.htaccess文件,发现,爆出很重要的信息 exif_imagetype函数通过检测文件头来检 ...
- 刷题[RoarCTF 2019]Easy Java
前置知识 WEB-INF/web.xml泄露 java web工程目录结构 Servlet访问URL映射配置 由于客户端是通过URL地址访问Web服务器中的资源,所以Servlet程序若想被外界访问, ...
随机推荐
- github 加速方法
登录网址:https://github.com.ipaddress.com/codeload.github.com#ipinfo 更改hosts:
- Inherent Adversarial Robustness of Deep Spiking Neural Networks: Effects of Discrete Input Encoding and Non-Linear Activations
郑重声明:原文参见标题,如有侵权,请联系作者,将会撤销发布! arXiv:2003.10399v2 [cs.CV] 23 Jul 2020 ECCV 2020 1 https://github.com ...
- A Case for Lease-Based, Utilitarian Resource Management on Mobile Devices
郑重声明:原文参见标题,如有侵权,请联系作者,将会撤销发布! 以下是对本文关键部分的摘抄翻译,详情请参见原文. Abstract 移动应用程序已经成为我们日常生活中不可或缺的一部分,但许多应用程序的设 ...
- 6. 二十不惑,ObjectMapper使用也不再迷惑
一滴水,用显微镜看,也是一个大世界.本文已被 https://www.yourbatman.cn 收录,里面一并有Spring技术栈.MyBatis.JVM.中间件等小而美的专栏供以免费学习.关注公众 ...
- 牛客网PAT练习场-数素数
题解:就是一道素数筛选法 题目地址:https://www.nowcoder.com/questionTerminal/e0fb49acb75f47e8b6fa2077d9071799 /** * C ...
- 自动部署Asp.Net Core到Docker
原文链接:个人博客:自动部署Asp.Net Core至Docker 本文简介 最近在开发一个管理系统,代码框架是用的前后台分离的方式 后台使用的是Asp.Net Core平台,开发所有业务,向前台提供 ...
- docker部署数据库
搜索数据库镜像images docker search mysql 搜索结果如下图所示: 选择合适自己的mysql版本 因为mysql新版本出来了,很多特性没有学习,所以笔者安装了mysql:5.6 ...
- idea创建web项目,不能自动导入tomcat包,导致调用request的方法时,无法正常调用
问题现象 分析原因 reques不能正常调用它的各种方法是因为没有导入tomcat包,所以不能正常调用request对象中的各种方法. 解决办法 ================== ======== ...
- C++ Templates (2.2 使用Stack类模板 Use of Class Template Stack )
返回完整目录 目录 2.2 使用Stack类模板 Use of Class Template Stack 2.2 使用Stack类模板 Use of Class Template Stack 在C++ ...
- ASP.NET Core 3.x控制IHostedService启动顺序浅探
想写好中间件,这是基础. 一.前言 今天这个内容,基于于ASP.NET Core 3.x. 从3.x开始,ASP.NET Core使用了通用主机模式.它将WebHostBuilder放到了通用的I ...