目录
本文通过《upload-labs靶场通关笔记系列》来进行upload-labs靶场的渗透实战,本文讲解upload-labs靶场第11关文件空格绕过渗透实战。
一、双写绕过
双写绕过的核心思想是通过构造特殊的文件名,使得安全过滤机制在删除或替换危险扩展名后,仍然保留一个有效的危险扩展名。
- 文件名过滤机制:许多文件上传功能会对文件名进行检查,以确保只允许上传特定类型的文件,比如只允许上传
.jpg
、.png
等图片文件,而禁止上传.php等可执行文件。这种检查通常是通过简单的字符串匹配来实现的。 - 双写绕过方法:攻击者发现,如果将文件名中的关键字符或扩展名进行双写,就可能绕过这种简单的字符串匹配检查。例如,将php文件重命名为.pphphp,服务器端的检查函数在第一次扫描时,可能会将其识别为非php文件,因为它不完全匹配php这个字符串。然而,在服务器实际保存文件或后续处理过程中,可能由于某些环节的处理逻辑问题,会将双写的部分保留下来,最终导致文件以php的形式被保存到服务器上,从而使攻击者能够成功上传恶意的可执行文件。
假设过滤机制为过滤后缀“php”,那么可以通过如下方法进行渗透
-
原始文件名:test11.php(这个后缀会被过滤掉)
-
将文件名改为:test11.pphphp(即在php的第一个p后面插入php)
-
过滤机制删除php后:test11.php(即将中间红色的php过滤掉了)
-
结果保留了危险的.php扩展名,成功绕或服务器的检查。
二、源码分析
打开靶场第11关,选择查看源码对其进行代码审计,这段代码依旧是黑名单过滤,具体如下所示。
详细注释的源码如下所示,有一点值得注意那就黑名单的过滤方法不一样,本次使用str_ireplace($deny_ext,"", $file_name)函数处理的方法过滤,使用str_ireplace简单替换禁止的扩展名为空字符串。而第3关到底9关的黑名单过滤方法为!in_array($file_ext, $deny_ext)进行黑名单过滤,判断文件后缀名是否在黑名单中。第9关处理逻辑具体如下所示。
<?php
$is_upload = false; // 上传状态标识,初始为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 . '文件夹不存在,请手工创建!'; // 目录不存在提示
}
}
?>
这段代码存在双写绕过安全问题,主要是因为:
-
黑名单过滤机制:使用str_ireplace简单粗暴直接替换禁止的扩展名为空字符串
-
缺乏完整性检查:替换后没有验证文件名是否仍然包含危险扩展名
-
未规范化文件名:没有对文件名进行规范化处理后再检查
假设攻击者上传名为test11.php的文件,具体绕过方法如下所示。
-
原始脚本文件名:test11.php
-
将脚本名改为:test11.pphphp
-
过滤过程:str_ireplace
()
会查找并删除所有php
字符串:test11.php -
最终保存的文件名:test11.php(成功绕过了过滤)
三、渗透实战
1、构建脚本
构建脚本test11.php,目标是获取服务器的php信息,具体内容如下所示。
<?php
phpinfo();
?>
2、打开靶场
打开靶场第0关,浏览选择该脚本,但不点击上传。
3、bp开启拦截
4、点击上传
5、bp抓包
bp捕获到上传报文,下图红框的部分即为需要修改的文件名,需要将".php"后缀改为".pphphp",修改之前文件名为”test11.php“,如下所示
6、后缀名改为pphphp
test11.php改为“test11.pphphp”,修改后效果如下所示。
7、发包并获取脚本地址
将bp的inception设置为off,此时修改后的报文发送成功。
回到靶场的Pass11关卡,图片已经上传成功,在图片处右键复制图片地址。
右键图片获取图片地址,如下所示获取到图片URL。
http://127.0.0.1/upload-labs/upload/test11.php
8、访问脚本
如下所示访问上传脚本获取到服务器的php信息,证明文件上传成功。