upload-labs靶场通关详解:第11关
一、分析源代码
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {if (file_exists(UPLOAD_PATH)) {$deny_ext = array("php","php5","php4","php3","php2","html","htm","phtml","pht","jsp","jspa","jspx","jsw","jsv","jspf","jtml","asp","aspx","asa","asax","ascx","ashx","asmx","cer","swf","htaccess","ini");$file_name = trim($_FILES['upload_file']['name']);$file_name = str_ireplace($deny_ext,"", $file_name);$temp_file = $_FILES['upload_file']['tmp_name'];$img_path = UPLOAD_PATH.'/'.$file_name; if (move_uploaded_file($temp_file, $img_path)) {$is_upload = true;} else {$msg = '上传出错!';}} else {$msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';}
}
这一关仍然是黑名单过滤,但是它的代码和前几关都不一样, 它这里有一行核心代码,就是
$file_name = str_ireplace($deny_ext,"", $file_name);
str_ireplace是 PHP 内置函数,用于执行不区分大小写的字符串替换。
语法:str_ireplace(要查找的数组, 替换值, 输入字符串)
这行代码的执行逻辑就是:
1.遍历$deny_ext数组中的每个扩展名;
2.在$file_name中查找匹配项(不区分大小写);
3.将所有匹配的扩展名替换为空字符串(即删除)。
典型处理示例
原始文件名 | 处理后文件名 | 说明 |
---|---|---|
shell.php | shell. | 直接移除.php 扩展名 |
shell.php.jpg | shell.jpg | 仅移除第一个扩展名 |
shell.php5 | shell. | 移除 PHP 旧版本扩展名 |
SHELL.PHP | shell. | 大小写不敏感替换 |
.htaccess | . | 移除服务器配置文件 |
exploit.jsp.asax | exploit. | 同时移除多个危险扩展名 |
二、解题思路
现在我们知道它可以删除黑名单中的扩展名,那么这关的代码是否存在逻辑漏洞呢?联想第10关结合绕过的方式,是否可以再尝试多次绕过呢?如果我上传文件的后缀名为pphphp,代码从第一位字母p开始读取,读到2-4位的时候发现这三位字母是php,于是将它替换成空白字符(删除),这看起来没什么问题,代码执行下一步,构建路径上传文件。但是,这里的pphphp在php被删除后,后缀只剩下了php,然后被上传,从而构成了文件绕过,这就是双写绕过。
三、解题步骤
1.上传666.php并抓包,修改后缀为pphphp。
2.放行后显示文件上传成功,被保存为666.php。
3.解析测试。