[De1CTF 2019]SSRF Me

步骤
代码分析
用ai格式化代码
#!/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模块
sys.setdefaultencoding('latin1') //将默认编码设置为latin1
app = Flask(__name__)
secert_key = os.urandom(16) //设置key为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: //这里用的in,scan在action中
tmpfile = open("./%s/result.txt" % self.sandbox, 'w') //打开result.txt,以可写的权限
resp = scan(self.param)
if (resp == "Connection Timeout"):
result['data'] = resp
else:
print resp
tmpfile.write(resp) //将scan读取的前50个字符写入result.txt中
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", "")) //从get参数中获取param值并url解码
action = "scan"
return getSign(action, param)
@app.route('/De1ta', methods=['GET', 'POST'])
def challenge():
action = urllib.unquote(request.cookies.get("action")) //获取cookies中的action值并url解码
param = urllib.unquote(request.args.get("param", "")) //获取get参数中的param值并url解码
sign = urllib.unquote(request.cookies.get("sign")) //获取cookies中的sign值并url解码
ip = request.remote_addr //获取请求端的IP地址
if (waf(param)):
return "No Hacker!!!!"
task = Task(action, param, sign, ip)
return json.dumps(task.Exec()) //以json的形式返回到客户端
@app.route('/')
def index():
return open("code.txt", "r").read()
def scan(param):
socket.setdefaulttimeout(1) //设置默认超时为1s
try:
return urllib.urlopen(param).read()[:50] //发起HTTP请求并读取响应内容的前50个字符
except:
return "Connection Timeout"
def getSign(action, param):
return hashlib.md5(secert_key + param + action).hexdigest() //生成md5hash值
def md5(content):
return hashlib.md5(content).hexdigest()
def waf(param):
check = param.strip().lower() //转小写
if check.startswith("gopher") or check.startswith("file"): //是否开头是gopher或者是file
return True
else:
return False
if __name__ == '__main__':
app.debug = False
app.run(host='0.0.0.0', port=80)
漏洞代码分析:
Task内:
if "scan" in self.action:
if "read" in self.action:
这里用的判断是 in ,只要里面包含字符串就返回真,所以如果是 scanread 两个if都返回真。
if (self.checkSign())
这里判断sign值是否相等,而sign通过cookie传入。需要md5(secert_key + param + action).hexdigest() == self.sign,param和acton可以自己传入控制,而secert_key在服务端,所以可以通过geneSign路由获取sing值。
在Task类内,result.txt的位置也可以知道,为md5(ip)/result.txt。
方法一:字符串拼接
得到flag的大概流程:
首先通过/geneSign,得到sign值来绕过self.checkSign(),之后在传入的action中需要同时包含read和scan,在"scan" in self.action中将flag.txt写入result.txt(题目提示)中,然后在"read" in self.action中奖result.txt中的内容读取出来。
1.绕过checkSign
访问/gensSign,action已经默认设置为scan,param是要读取的文件+read。
所以拼接为:secret_key+'flag.txtreadscan'。
/geneSign?param=flag.txt&action=readscan

2.读取flag.txt
访问/De1ta,action为cookies传入,值为readscan,param为get参数,值为flag.txt,sign为上面得到的,cookies传入。

方法二:哈希长度拓展攻击
如果你知道一个消息(message)和密钥(key)的组合的哈希值,即使不知道密钥的具体值,只要知道密钥的长度,你就能在这个消息后面添加额外的信息,并计算出新的哈希值。
首先通过/geneSign得到md5(secret_key + flag.txtscan)的md5值。

然后使用hashpump计算出添加read后的新hash值。
秘钥长度:secret_key(16)+flag.txt(8) = 24

sign值就为1fee4e944f01a5da4ae1cf86514ad435,action为scan\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x00\x00\x00\x00\x00\x00read,这里需要将\x替换为%。

方法三:local_file
这里使用 urllib.urlopen(param) 去包含文件,所以可以直接加上文件路径 flag.txt,但是file被过滤了,无法使用,但是可以使用local_file去代替。
但是如果使用 urllib2.urlopen(param) 去包含文件就必须加上 file,否则会报错。
过程和字符串拼接差不多。
1.获取sign

2.读取flag.txt

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)