之前已经总结了一部分文件上传漏洞,现在继续总结剩余的另一部分。
漏洞环境依旧用的upload-labs。
%00截断
类型:PHP %00截断
原理:因为00
代表结束符,所以会把00后面的所有字符删除
条件:PHP版本小于5.3.4,PHP的magic_quotes_gpc为OFF状态
常见的截断上传
0x00,%00,/00 截断的核心在于chr(0)这个字符,这个函数表示返回以数值表达式值为编码的字符。char(0)表示的ascll字符是null,当程序输出包含chr(0)变量时,chr(0)后面的数据会被截断,后面的数据直接忽略,导致漏洞产生。
查看源码
$is_upload = false;
$msg = null;
if(isset($_POST['submit'])){
$ext_arr = array('jpg','png','gif');
$file_ext = substr($_FILES['upload_file']['name'],strrpos($_FILES['upload_file']['name'],".")+1);
if(in_array($file_ext,$ext_arr)){
$temp_file = $_FILES['upload_file']['tmp_name'];
$img_path = $_GET['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext;
if(move_uploaded_file($temp_file,$img_path)){
$is_upload = true;
} else {
$msg = '上传出错!';
}
} else{
$msg = "只允许上传.jpg|.png|.gif类型文件!";
}
}
是白名单判断,但$img_path直接拼接,所以可以利用%00截断绕过,上传webshell。
因为我的ubantu虚拟机PHP版本大于5.3.4,所以直接在windows进行测试。
因为之前没用过,所以先配置一下:
1、Firefox+Burpsuite抓包配置
2、设置PHP版本
3、magic_quotes_gpc调为OFF:magic_quotes_gpc函数的关闭方法
配置结束,开始上传webshell.jpg,抓包,添加webshell.php%00
Forward发包,上传成功
测试连接,连接成功
查看源码,还是白名单判断,还是利用00截断。但save_path是通过post传进来的,post不会像get对%00进行自动解码,所以需要在二进制中进行修改。
空格的十六进制是20 ,将0x20 改成0x00 也就是00
点击Go,上传成功
测试连接,连接成功
function getReailFileType($filename){
$file = fopen($filename, "rb");
$bin = fread($file, 2); //只读2字节
fclose($file);
$strInfo = @unpack("C2chars", $bin);
$typeCode = intval($strInfo['chars1'].$strInfo['chars2']);
$fileType = '';
switch($typeCode){
case 255216:
$fileType = 'jpg';
break;
case 13780:
$fileType = 'png';
break;
case 7173:
$fileType = 'gif';
break;
default:
$fileType = 'unknown';
}
return $fileType;
}
$is_upload = false;
$msg = null;
if(isset($_POST['submit'])){
$temp_file = $_FILES['upload_file']['tmp_name'];
$file_type = getReailFileType($temp_file);
if($file_type == 'unknown'){
$msg = "文件未知,上传失败!";
}else{
$img_path = UPLOAD_PATH."/".rand(10, 99).date("YmdHis").".".$file_type;
if(move_uploaded_file($temp_file,$img_path)){
$is_upload = true;
} else {
$msg = "上传出错!";
}
}
}
分析代码,通过读文件的前2个字节判断文件类型,因此直接上传图片马即可,
方法一:copy normal.jpg /b + shell.php /a webshell.jpg
方法二:exiftool -Comment='"; system($_GET['cmd']); ?>' 1.jpg
我采用方法一先制作个图片马webshell.jpg(为了方便以后关卡一般直尝试jpg图片马)
上传webshell.jpg
,不用抓包改包,上传成功
测试连接,连接失败,发现文件名被替换。
重新输入图片马的文件名,测试连接,连接成功
利用的话,还需要结合文件包含漏洞。。。
依旧是上传图片马,查看源码
function isImage($filename){
$types = '.jpeg|.png|.gif';
if(file_exists($filename)){
$info = getimagesize($filename);
$ext = image_type_to_extension($info[2]);
if(stripos($types,$ext)>=0){
return $ext;
}else{
return false;
}
}else{
return false;
}
}
这里用的是getimagesize
获取文件类型,还是直接可以利用图片马就可以绕过。
还用Pass-13制作的那个图片马,上传成功,查看文件名
测试连接,连接成功
当然查看有关信息发现可以图片头绕过,具体操作如下:
将PHP木马文件,改成*.php;.jpg
抓包,给文件头部加上:GIF89a 图片头标识
查看源码
function isImage($filename){
//需要开启php_exif模块
$image_type = exif_imagetype($filename);
switch ($image_type) {
case IMAGETYPE_GIF:
return "gif";
break;
case IMAGETYPE_JPEG:
return "jpg";
break;
case IMAGETYPE_PNG:
return "png";
break;
default:
return false;
break;
}
}
利用php_exif模块判断文件类型,还是直接利用图片马就可以绕过。
上传图片马,在windows上上传有问题。所以打开ubantu漏洞环境上传,上传成功
查看文件名
测试连接,连接成功
依旧是上传图片马,上传、查看文件名
测试连接、连接成功
不过查看源码发现,综合判断了后缀名、content-type,以及利用imagecreatefromgif判断是否为gif图片,最后再做了一次二次渲染,绕过方法(不想尝试,这里借用大佬的一张图):
竞争条件攻击存在的原因:
一些网站上传逻辑是先允许上传任意文件,然后检查上传文件是否包含WebShell脚本,如果包含则删除该文件。文件上传成功后和删除文件之间存在短的时间差。攻击者可以利用这个时间差完成竞争条件的上传漏洞攻击。
攻击过程:
攻击者先上传一个webshell脚本shell.php
,shell.php
的内容是生成一个新的webshell脚本webshell.php
shell.php代码如下:
fputs(fopen('../webshell.php','w'),'a']);?>');
?>
shell.php
上传成功后,客户端立即访问shell.php,则会在当前目录下自动生成webshell.php
,这时攻击者就利用时间差完成webshell的上传。
查看源码
$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 = '上传出错!';
}
}
这里先将文件上传到服务器,然后通过rename修改名称,再通过unlink删除文件,因此可以通过条件竞争的方式在unlink之前,访问webshell。
首先在burp中不断发送上传webshell的数据包,然后不断在浏览器中访问,发现通过竞争可以访问到。
(不会不断发送上传webshell的数据包,没有复现成功)
upload-labs17
本关需要上传图片马,查看代码发现:
对文件后缀名做了白名单判断,然后会一步一步检查文件大小、文件是否存在等等,将文件上传后,对文件重新命名,同样存在条件竞争的漏洞。可以不断利用burp发送上传图片马的数据包,由于条件竞争,程序会出现来不及rename的问题,从而上传成功
依旧用webshell.jpg
图片马测试,发送上传图片马的数据包
考察CVE-2015-2348 move_uploaded_file() 00截断,上传webshell,同时自定义保存名称,直接保存为php是不行的
查看源码,发现move_uploaded_file()函数中的img_path是由post参数save_name控制的,因此可以在save_name利用00截断绕过。上传的文件名用0x00绕过。改成*.php【二进制00】.1.jpg,上传文件名改成要自己定义。
也可以上传webshell.php/.
绕过
下面用的windows的漏洞环境。两个文件名中间留一个空格
将0x20改为0x00
Forword发包,上传成功。
测试连接,连接成功
好了,总结完毕,总算了解完文件上传漏洞的各种绕过姿势,收获很大。
继续努力,小白进阶ing。