upload-labs靶场通关详解:第21关 数组绕过

一、分析源代码

php 复制代码
// 初始化上传状态和消息变量
$is_upload = false;
$msg = null;

// 检查是否有文件上传
if(!empty($_FILES['upload_file'])){
    // 允许上传的MIME类型数组
    $allow_type = array('image/jpeg','image/png','image/gif');
    
    // 验证上传文件的MIME类型是否允许
    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 = "请选择要上传的文件!";
}

这里首先做了一个MIME类型检测,然后将保存的文件名分割成数组,进行白名单验证。

explode()函数将文件名拆分成数组,假设上传文件是xx.php.jpg,被拆分为:

php 复制代码
Array
(
     [0] => xx
     [1] => php
     [2] => jpg
)

end()函数用来获取最后一个元素的值,进行后缀名检查。这里获取是jpg,通过白名单验证,进入下一步。

重新组合文件名,reset()函数返回第一个元素的值,"."用来拼接,count()函数是统计元素个数,file\[count(file) - 1]是获取最后一个元素。举例,这里文件名被拆分为包含三个元素的数组,所以count(file)为3,也就是file[2],索引从0开始,$file[2]就是第三位的"jpg"。重新组合的文件名就成为"xx.jpg"。

接下来再构建路径并转移上传。

二、解题思路

缺陷存在于数组拆分重组这一步,因为数组中的元素是可以构造的。

php 复制代码
Array
(
     [0] => xx.php
     [1] => (空)
     [2] => jpg
)

将第二个元素构造为空,end()函数获取第三个元素的值jpg,通过白名单验证。进入重新组合文件名:

file_name = reset(file) . '.' . file\[count(file) - 1];

这一步是关键所在,reset()函数获取第一个元素的值xx.php,而count()函数计算数组中只有2个元素,所以file\[count(file) - 1]索引的位置是$file[1],也就是第二个元素的值。最后拼接,变成了"xx.php.(空)",由于windows系统的特性会删除文件名末尾的句点(.),最终文件被服务器保存为xx.php。

三、解题步骤

1.上传木马,利用bp抓包,先修改一下MIME类型,改成image/png。

2.构造数组。

3.提示文件上传成功,被保存为php文件。

相关推荐
安全漏洞防治中心4 小时前
Roadmap:一年实现安全漏洞防治自动化
运维·web安全·网络安全·自动化·漏洞管理·漏洞处置sop·漏洞紧急修复建议
Bruce_Liuxiaowei5 小时前
使用批处理脚本安全清理Windows系统垃圾
网络·windows·安全·网络安全
lingggggaaaa6 小时前
小迪安全v2023学习笔记(七十讲)—— Python安全&SSTI模板注入&项目工具
笔记·python·学习·安全·web安全·网络安全·ssti
Johny_Zhao18 小时前
Linux防止rm误操作防护方案
linux·网络·人工智能·网络安全·信息安全·云计算·yum源·系统运维
卓码软件测评1 天前
软件测试:如何利用Burp Suite进行高效WEB安全测试
网络·安全·web安全·可用性测试·安全性测试
黑客影儿2 天前
Go特有的安全漏洞及渗透测试利用方法(通俗易懂)
开发语言·后端·安全·web安全·网络安全·golang·系统安全
MicroTech20252 天前
微算法科技(NASDAQ: MLGO)引入高级区块链DSR算法:重塑区块链网络安全新范式
网络安全·区块链
m0_738120722 天前
CTFshow系列——命令执行web38-40
前端·windows·安全·web安全
网络安全大学堂3 天前
【黑客技术零基础入门】PHP环境搭建、安装Apache、安装与配置MySQL(非常详细)零基础入门到精通,收藏这一篇就够
安全·web安全·计算机·网络安全·黑客·信息安全·程序员
卓码软件测评3 天前
【网站测试:CORS配置错误引发的安全风险及测试】
功能测试·安全·web安全·压力测试·可用性测试·安全性测试