PHP代码审计:文件上传(构造数组绕过)

uplaod-labs 21:
源码:

$is_upload = false;
$msg = null;
if(!empty($_FILES['upload_file'])){
    //检查MIME
    $allow_type = array('image/jpeg','image/png','image/gif');
    if(!in_array($_FILES['upload_file']['type'],$allow_type)){
        $msg = "禁止上传该类型文件!";
    }else{
        //检查文件名
        $file = empty($_POST['save_name']) ? $_FILES['upload_file']['name'] : $_POST['save_name'];
        if (!is_array($file)) {
            $file = explode('.', strtolower($file));
        }

        $ext = end($file);
        $allow_suffix = array('jpg','png','gif');
        if (!in_array($ext, $allow_suffix)) {
            $msg = "禁止上传该后缀文件!";
        }else{
            $file_name = reset($file) . '.' . $file[count($file) - 1];
            $temp_file = $_FILES['upload_file']['tmp_name'];
            $img_path = UPLOAD_PATH . '/' .$file_name;
            if (move_uploaded_file($temp_file, $img_path)) {
                $msg = "文件上传成功!";
                $is_upload = true;
            } else {
                $msg = "文件上传失败!";
            }
        }
    }
}else{
    $msg = "请选择要上传的文件!";
}

代码分析:
本关为该系列靶场最后一关,当中使用了很多陌生的函数,让我们来一一认识它们。

	在代码第56行设置了 Content-Type 白名单,检测请求头中 Content-Type 是否为 $allow_type 中的
三种类型。如果 Content-Type 为白名单中的类型的话,会在代码第1011行判断传入的文件是否为
POST传入,如果POST没有传入文件名则使用 $_FILES 中获取到的文件名并且如果$file不是 $_FILE 传
入的话则使用 explode() 将内容以 . 进行分割并以数组的形式进行返回以便后续调用。
在代码第15行使用 end() 函数将获取$file数组进中最后一个数组元素,也就是获取后缀名,然后在代码
第17行与白名单中后缀进行比较,如果在白名单中则在代码第20行将 reset() 函数获取的文件名与
count() 函数获取的文件后缀进行拼接组成新的文件名,然后在23行进行移动。

explode()

定义和用法:
explode() 函数使用一个字符串分割另一个字符串,并返回由字符串组成的数组。
语法:
explode(separator,string,limit)
separator 必需。规定在哪里分割字符串。
string 必需。要分割的字符串。
limit 可选。规定所返回的数组元素的数目。
可能的值:
大于 0 - 返回包含最多 limit 个元素的数组
小于 0 - 返回包含除了最后的 -limit 个元素以外的所有元素的数组
0 - 会被当做 1, 返回包含一个元素的数组
返回值:返回字符串数组。

end()

定义和用法:
end() 函数将内部指针指向数组中的最后一个元素,并输出。
语法:
end(array)
array 必需。规定要使用的数组。
返回值:
如果成功则返回数组中最后一个元素的值,如果数组为空则返回 FALSE

reset()
该函数与上述 end() 类似,类似函数还有 current() 、 next() 、 prev() 、 each() 。

定义和用法:
reset() 函数将内部指针指向数组中的第一个元素,并输出。
语法:
reset(array)
返回值:
如果成功则返回数组中第一个元素的值,如果数组为空则返回 FALSE

count()

定义和用法:
count() 函数返回数组中元素的数目。
语法:
count(array,mode);
array 必需。规定要计数的数组。
mode 可选。规定函数的模式。可能的值:
0 - 默认。不计算多维数组中的所有元素。
1 - 递归地计算数组中元素的数目(计算多维数组中的所有元素)
返回值:
返回数组中元素的数目。

绕过方法:
这里可以构造 save_name[0] = upload-20.php ,save_name[2] = png ,这样数组的长度为2,
save_name[1] = null ,所以最终 file_name=upload-20.php.
在这里插入图片描述在这里插入图片描述

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值