解法一字符串拼接:

1.得到签名sign

http://8fa4531c-1164-49b7-a700-70e77e6aacb7.node3.buuoj.cn/geneSign?param=flag.txtread

2.添加Cookie发送请求得到flag

Cookie: action=readscan;sign=cf8d4365c9b27a29b29e025a7ed25fa6

原理:

1.分析源码

#! /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)

2.传入一个param,/geneSign路由会返回的一个sign

3.通过cookie得到一个sign,到时候回传到exec()中去跟getSign()产生的sign校验,所以这里直接传一个getSign()产生的sign。通过cookie传入一个action参数,看后面的Exec()可以知道action="readscan"。根据提示param=flag.txt,所以这个sign应该是md5('xxxflag.txtreadscan'),但是action在geneSign()写死了为"action"。

  • 不妨假设 secert_key 是 xxx ,那么在开始访问 /geneSign?param=flag.txt 的时候,返回的 md5 就是 md5('xxx' + 'flag.txt' + 'scan') ,在 python 里面上述表达式就相当于 md5(xxxflag.txtscan) ,这就很有意思了。

  • 直接构造访问 /geneSign?param=flag.txtread ,拿到的 md5 就是 md5('xxx' + 'flag.txtread' + 'scan') ,等价于 md5('xxxflag.txtreadscan') ,这就达到了目标。


解法二文件包含:

1.得到sign

2.得到flag

原理:

Python 2.x - 2.7.16 urllib.fopen支持local_file导致LFI(CVE-2019-9948):https://bugs.python.org/issue35907

这里是使用的 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 的错误

当不存在协议的时候,默认使用file协议读取

可以使用local_file:绕过,例如 local_file:flag.txt路径就是相对脚本的路径  local_file://就必须使用绝对路径(协议一般都是这样)
PS:local-file:///proc/self/cwd/flag.txt也可以读取,因为/proc/self/cwd/代表的是当前路径


解法三:哈希拓展攻击

我们可以在不知道salt的具体内容的情况下,计算出任意的md5(salt+message+padding+append)值

对于本题来说就是 md5(secert_key + 'flag.txt' + 'scan') 的值延拓成 md5(secert_key + 'flag.txt' + 'readscan') 的值

由于我本机的hashpump老是安装失败就不复现了Orz  Hash Length Extension Attack


参考:

https://blog.csdn.net/weixin_44255856/article/details/98946266

https://xz.aliyun.com/t/5927

https://www.cnblogs.com/20175211lyz/p/11440316.html

https://joychou.org/web/hash-length-extension-attack.html

BUUCTF | [De1CTF 2019]SSRF Me的更多相关文章

  1. 刷题记录:[De1CTF 2019]SSRF Me

    目录 刷题记录:[De1CTF 2019]SSRF Me 一.涉及知识点 1.MD5长度扩展攻击 2.Python 2.x - 2.7.16 urllib.fopen支持local_file导致LFI ...

  2. [De1CTF 2019]SSRF Me

    原帖地址 : https://xz.aliyun.com/t/5927 De1CTF 2019 的一个题目总结 题目描述 直接查看页面源代码可以看到正确格式的代码 #! /usr/bin/env py ...

  3. 刷题[De1CTF 2019]SSRF Me

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

  4. [De1CTF 2019]SSRF Me-MD5长度扩展攻击&CVE-2019-9948

    0x00 打开题目查看源代码,开始审计 这里贴上网上师傅的博客笔记: https://xz.aliyun.com/t/6050 #! /usr/bin/env python #encoding=utf ...

  5. 刷题记录:[De1CTF 2019]Giftbox && Comment

    目录 刷题记录:[De1CTF 2019]Giftbox && Comment 一.知识点 1.sql注入 && totp 2.RCE 3.源码泄露 4.敏感文件读取 ...

  6. [De1CTF 2019]Giftbox 分析&&TPOP学习

    [De1CTF 2019]Giftbox 刚进来我以为是直接给了shell,恐怖如斯. 随便扔了个命令,之后就没然后了,hhh,截包发现可能存在sql注入. 然后我就不会了... what i lea ...

  7. BUUCTF | [RoarCTF 2019]Easy Calc

    看一下页面源码,发现了提示: calc.php?num=encodeURIComponent($("#content").val()) $("#content" ...

  8. [BUUCTF]REVERSE——[2019红帽杯]easyRE

    [2019红帽杯]easyRE 附件 步骤: ida载入,没有main函数,就先检索了程序里的字符串 发现了base64加密的特征字符串,双击you found me跟进,找到了调用它的函数,函数很长 ...

  9. BUUCTF | [SUCTF 2019]CheckIn

    感觉这题师傅们已经写得很详细了,我就做一个思路梳理吧,顺道学一波.user.ini 步骤: 1.上传一个“.user.ini”文件 2.上传自己的马“a.jpg” 3.菜刀连接 "http: ...

随机推荐

  1. JavaScript 变量,语句

    定义变量的方式: var   变量可以没有初始值,变量可以修改,变量可以覆盖,存在变量提升. // 变量提升机制 console.log(name)// undefined var name = &q ...

  2. 【ABAP系列】SAP 生产订单完工确认(CO11N) BAPI : BAPI_PRODORDCONF_CREATE_TT

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[ABAP系列]SAP 生产订单完工确认(CO1 ...

  3. linux下安装python27 nginx 和uwsgi

    注意: python27 默认没有安装 pip 和setuptools所以要提前安装.(务必先提前安装python27 哈 ) wget --no-check-certificate https:// ...

  4. JavaSE编码试题强化练习2

    1.编写递归算法程序:一列数的规则如下: 0.1.1.2.3.5.8.13.21.34...... 求数列的第40位数是多少. public class TestRecursion { public ...

  5. SpringBoot使用RestTemplate

    SpringBoot使用RestTempate SpringBoot使用RestTemplate摘要认证 SpringBoot使用RestTemplate基础认证 设置pom引用 <?xml v ...

  6. [Python3 填坑] 012 字典的遍历在 Python2 与 Python3 中区别

    目录 1. print( 坑的信息 ) 2. 开始填坑 2.1 Python2 中字典的遍历 2.2 Python3 中字典的遍历 2.3 结论 1. print( 坑的信息 ) 挖坑时间:2019/ ...

  7. [Python3] 020 借函数,谈一谈变量的作用域

    目录 1. 概述 2. 分类 3. 变量的作用范围 少废话,上例子 4. 将局部变量提升为全局变量 少废话,上例子 5. 内建函数 globals() 与 locals() 少废话,上例子 6. 邪恶 ...

  8. Java数据结构介绍(线性结构和非线性结构)

    数据结构包括:线性结构和非线性结构. 线性结构 数据元素之间存在一对一的线性关系 包括顺序存储结构和链式存储结构.顺序存储的线性表称为顺序表,顺序表中的存储元素是连续的 链式存储的线性表称为链表,链表 ...

  9. Spark-Core RDD概述

    一.什么是RDD 1.RDD(Resilient Distributed DataSet)弹性分布式数据集 2.是Spark中最基本的数据抽象 3.在代码中是一个抽象类,它代表一个弹性的.不可变的.可 ...

  10. Vue2+VueRouter2+webpack 构建项目实战(四)接通api,先渲染个列表

    Vue2+VueRouter2+webpack 构建项目实战(四)接通api,先渲染个列表:  Vue2+VueRouter2+Webpack+Axios 构建项目实战2017重制版(一)基础知识概述