一、条件竞争
1.1、原理
当我们上传webshell1到服务器中时,如果后端验证的方式是:
先接收文件,再在当前文件夹中检查文件的合法性;
那么就会产生问题,如果我们在后端验证文件后缀合法性之前在网页访问到我们的webshell1,使其生成新的webshell2到上级目录中的文件夹中或上级目录中;
那即使这时我们最开始的webshell1被删除,也没关系了,直接访问webshell2即可。
1.2、方式&示例
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 = '上传出错!';
}
}
webshell1:
<?php
file_put_contents('../webshell2.php','<?php phpinfo(); ?>');
bp抓包:
暴力破解+请求:
设置两个线程,一个是上传webshell1,另一个请求127.0.0.1/upload-labs-master/webshell2,两个线程同时爆破。
二、多文件上传
2.1、原理
可以让我们上传多个文件,但只检测第一个上传的文件的合法性。
2.2、方式
只需要第一份上传合法文件,第二份上传马即可。
将第二个文件表单的action
设置为绝对路径http://xxx.com/<file>
以确定文件上传的路径,方便利用。
三、二次渲染绕过
3.1、原理
网站允许上传php
等文件,但是会检查文件内容,对检测出来的恶意内容进行渲染,从而使得文件无害化。
但是当某个木马图片文件被上传时经过渲染后,将渲染后的文件再上传
时就不会查出恶意文件。
3.2、方式
先将一个木马文件上传
后渲染,再将经过渲染后的文件下载
下来,把木马内容添加到经过渲染的图片文件
,此时再上传去渲染就不会查出木马内容。
使用16进制编辑器
找到两次文件的异同,在相同的地方
(即被判定无害)加入恶意代码(一句话木马等),再次上传就可以成功了。
四、windows符号特性绕过
4.1、原理
在php+windows+[iis]环境下,下面符号会被视作相同:
双引号(") <==> 点号(.)
大于符号(>) <==> 问号(?)
小于符号(<) <==> 星号(*)
我们就可以上传 shell.<<< (等同于shell.***)这样的文件并在其中写木马覆盖服务器中的php文件并访问执行。
不过有问题:
1)上传目录不可控
2)服务器目录中一般不会存在php文件
解决办法:
用冒号(:)截断
我们可以先上传webshell.php:jpg、webshell.php:gif这样的文件,后端接收后因为windows的特性会将冒号(:)后面的字符忽略,到web服务器的目录中的就是webshell.php了;但是被处理后的文件内容会被清除,但这时服务器目录中就已经存在php文件了,就可以搭配webshell.<<<使用了。
4.2、方式
准备两个文件:webshell.php webshell.<<<
上传webshell.php时抓包,将文件后缀改为webshell.php:gif,放包
此时web目录中存在webshell.php,但文件内容为空
在webshell.<<<中编写恶意代码,上传webshell.<<<
因为webshell.<<< <==> webshell.***,匹配到目录中的webshell.php并覆盖内容
访问127.0.0.1/uploads/webshell.php,执行命令
五、嵌套绕过(phpcms v9)
5.1、原理
后端检测函数:
$ext = strtolower(substr(strrchr($name,'.'),1));
function check_dir($dir)
{
$handle = opendir($dir);
while (($f = readdir ($handle))!== false){
if (lin_array($f, array('.','..'))){
$ext = strtolower(substr(strrchr($f,'.'),1));
if (!in_array($ext, array('jpg', gif',png'))){
unlink($dir . $f);
}
}
}
}
虽然是白名单过滤检测后缀,不过没有采用递归删除
5.2、方式
准备两个文件:webshell.php aaa.gif
创建文件夹:web
将webshell.php放到文件夹中
将web和aaa.gif打包压缩web.zip
上传web.zip
最后访问127.0.0.1/uploads/web/webshell.php