当前位置: 首页 > news >正文

upload-labs通关笔记-第10关 文件上传之点多重过滤(空格点绕过)

目录

一、源码分析

1、delot函数

2、strrchr函数

3、trim函数

4、代码审计 

5、渗透思路

 二、渗透实战

1、构建脚本test10.php

2、打开靶场

3、bp开启拦截

4、点击上传

5、bp拦截

6、文件名尾部增加“. .”

7、发包并获取脚本地址

8、访问脚本


本文通过《upload-labs靶场通关笔记系列》来进行upload-labs靶场的渗透实战,本文讲解upload-labs靶场第10关文件上传通关代码审计实现“点空格点”绕过的渗透实战。

一、源码分析

打开upload-labs靶场第10关,选择查看源码对其进行代码审计,这段代码依旧是黑名单过滤,具体如下所示。

1、delot函数

本关卡需要通过代码审计完成渗透,如上关卡的delot函数是自定义函数,函数主要功能是删除文件名末尾的点(.),从字符串尾部开始,从后向前删除点(.)字符 ,直到末尾的字符不是点为止。具体源码如下所示。

<?php
function deldot($s){for($i = strlen($s)-1;$i>0;$i--){$c = substr($s,$i,1);if($i == strlen($s)-1 and $c != '.'){return $s;}if($c != '.'){return substr($s,0,$i+1);}}
}
?>

2、strrchr函数

strrchr 是 PHP 中的字符串处理函数,其主要功能是查找字符串中某个字符(或子字符串)最后一次出现的位置,并返回从该位置开始到字符串末尾的所有字符。

strrchr ( string $haystack , mixed $needle ) : string|false
  • 参数说明
    • $haystack:这是要进行搜索的目标字符串。
    • $needle:这是要查找的字符或子字符串。如果 $needle 是一个长度大于 1 的字符串,实际上只会使用该字符串的第一个字符进行查找。
  • 返回值
    • 若 $needle 存在于 $haystack 中,函数会返回从 $needle 最后一次出现的位置开始到 $haystack 末尾的子字符串。
    • 若 $needle 不存在于 $haystack 中,函数会返回 false。

在文件上传靶场中,通常使用file_ext = strrchr($file_name, '.')函数用于获取上传文件的扩展名

$file_ext = strrchr($file_name, '.');

这里 $file_name 是上传文件的文件名,通过 strrchr 函数查找 点(.) 最后一次出现的位置,然后返回从该位置开始到文件名末尾的子字符串,也就是文件的扩展名。例如,若 $file_name 为 example.jpg,那么 $file_ext 就会是 .jpg。

3、trim函数

trim 是 PHP 里一个十分实用的字符串处理函数,其主要功能为去除字符串首尾处的空白字符或者其他指定字符。trim函数的基本语法如下所示。

trim ( string $str [, string $character_mask = " \t\n\r\0\x0B" ] ) : string
  • 参数说明
    • $str:这是需要处理的目标字符串。
    • $character_mask:这是一个可选参数,用于指定要去除的字符。若不提供该参数,默认会去除空格()、制表符(\t)、换行符(\n)、回车符(\r)、空字节(\0)以及垂直制表符(\x0B)。
  • 返回值:返回去除了指定字符后的新字符串

 在之前的文件上传代码里,trim 函数被调用了两次:

$file_name = trim($_FILES['upload_file']['name']);
$file_ext = trim($file_ext);
  • 第一次使用 trim 函数是为了去除上传文件原始文件名首尾的空白字符,避免因文件名前后存在空格而引发问题。
  • 第二次使用 trim 函数是对处理后的文件扩展名进行处理,去除其首尾的空白字符,确保扩展名的准确性。这样做能防止因空白字符的存在而导致文件类型的过滤出现误判。

4、代码审计 

详细注释的源码如下所示。第10关处理逻辑具体如下所示。

<?php
// 初始化变量,用于判断文件是否上传成功,初始值为 false
$is_upload = false;
// 初始化变量,用于存储上传过程中的提示信息,初始值为 null
$msg = null;// 检查是否通过 POST 方式提交了名为 submit 的表单数据
if (isset($_POST['submit'])) {// 检查上传目录是否存在if (file_exists(UPLOAD_PATH)) {// 定义一个数组,包含不允许上传的文件扩展名$deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess",".ini");// 获取上传文件的原始文件名,并去除首尾空格$file_name = trim($_FILES['upload_file']['name']);// 调用 deldot 函数删除文件名末尾的点$file_name = deldot($file_name);// 获取文件的扩展名,从文件名中最后一个点开始截取$file_ext = strrchr($file_name, '.');// 将文件扩展名转换为小写$file_ext = strtolower($file_ext);// 去除文件扩展名中可能存在的字符串 "::$DATA"$file_ext = str_ireplace('::$DATA', '', $file_ext);// 去除文件扩展名首尾的空格$file_ext = trim($file_ext);// 检查文件扩展名是否不在禁止上传的扩展名列表中if (!in_array($file_ext, $deny_ext)) {// 获取上传文件在服务器临时存储的路径$temp_file = $_FILES['upload_file']['tmp_name'];// 拼接上传文件在目标目录中的完整路径$img_path = UPLOAD_PATH.'/'.$file_name;// 尝试将临时文件移动到目标目录if (move_uploaded_file($temp_file, $img_path)) {// 如果移动成功,将 $is_upload 标记为 true$is_upload = true;} else {// 如果移动失败,设置提示信息为上传出错$msg = '上传出错!';}} else {// 如果文件扩展名在禁止列表中,设置提示信息为不允许上传该类型文件$msg = '此文件类型不允许上传!';}} else {// 如果上传目录不存在,设置提示信息为文件夹不存在,需要手工创建$msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';}
}
?>

这段代码首先定义了一个数组 $deny_ext,包含了一系列不允许上传的文件扩展名 ,然后获取并处理上传的文件名以及扩展名,具体逻辑如下所示。

  • 从 $_FILES['upload_file']['name'] 获取上传文件的原始文件名,并去除首尾空格。
  • 调用 deldot 函数删除文件名末尾的点。
  • 使用 strrchr 函数获取文件的扩展名。
  • 将扩展名转换为小写,以避免大小写绕过。
  • 去除扩展名中可能存在的字符串 ::$DATA。
  • 再次去除扩展名首尾的空格。

5、渗透思路

假设我们要上传的文件名为test10.php,我们在文件名的后缀尾部添加[点+空格+点],那么要上传的文件名被修改为[test10.php.空格.],上传到服务器之后会保留文件名test.php,整个处理流程如下所示。

  • 第一步:deldot的函数先去除了一个最末尾的点,但是由于deldot()函数从后向前检测,当检测到末尾的第一个点时会继续它的检测,但是遇到空格会停下来,因此可以得到$file_name值为test10.php.空格,即“test10.php. ”
filename:“test10.php. ”
  • 第二步:$file_ext = strrchr($file_name, ‘.’);这个函数的功能是获取字符点最后出现的位置后面的所有字符,因此在判断完以上语句后,可以得到$ file_ext值为点空格,即“. ”
ext:". "
  • 第三步:$file_ext = trim($file_ext); //首尾去空,原$file_ext中的空格全都删掉,变为了点,这样文件扩展名为“.”,这样可以绕过黑名单的检测。而此时文件名为"test10.php",这类文件传入window服务器,会被默认删掉.所以可以成功上传php后缀的文件。
​filename:"test10.php. "
ext:"."

 二、渗透实战

1、构建脚本test10.php

<?php
phpinfo();
?>

2、打开靶场

 打开靶场第10关,浏览选择该脚本,但不点击上传。

3、bp开启拦截

4、点击上传

5、bp拦截

bp捕获到上传报文,下图红框的部分即为需要修改的文件名,需要将".php"后缀改为".php. ",修改之前文件名为”test10.php “,如下所示

6、文件名尾部增加“. .”

test11.php改为“test11.php. .”,修改后效果如下所示。

7、发包并获取脚本地址

将bp的inception设置为off,此时修改后的报文发送成功。

回到靶场的Pass11关卡,图片已经上传成功,在图片处右键复制图片地址。

右键图片获取图片地址,如下所示获取到图片URL。 

http://127.0.0.1/upload-labs/upload/test10.php.

8、访问脚本

 如下所示访问上传脚本获取到服务器的php信息,证明文件上传成功。

http://www.xdnf.cn/news/495973.html

相关文章:

  • 开源RTOS(实时操作系统):nuttx 编译
  • JDBC实现模糊、动态与分页查询的详解
  • C++ deque双端队列、deque对象创建、deque赋值操作
  • 「Mac畅玩AIGC与多模态41」开发篇36 - 用 ArkTS 构建聚合搜索前端页面
  • Java 方法向 Redis 里操作字符串有什么需要注意的?​
  • OpenWebUI新突破,MCPO框架解锁MCP工具新玩法
  • Java 多态学习笔记(详细版)
  • 一场关于BOM物料清单的深度对话
  • 阿里通义万相 Wan2.1-VACE:开启视频创作新境界
  • 重排序模型解读:gte-multilingual-reranker-base 首个GTE系列重排模型诞生
  • 【计算机视觉】论文精读《基于改进YOLOv3的火灾检测与识别》
  • 区块链可投会议CCF C--IPCCC 2025 截止6.7 附录用率
  • 2024 山东省ccpc省赛
  • 数据库——SQL约束窗口函数介绍
  • windows触摸板快捷指南
  • 一二维前缀和与差分
  • C++学习-入门到精通-【7】类的深入剖析
  • 【Redis】redis用作缓存和分布式锁
  • 湖北理元理律师事务所:科学债务管理模型构建实录
  • 无法加载文件 E:\Program Files\nodejs\npm.ps1,因为在此系统上禁止运行脚本
  • 支持同步观看的媒体服务器GhostHub
  • 【Linux笔记】——线程互斥与互斥锁的封装
  • 使用 Python 连接 Oracle 23ai 数据库完整指南
  • 小黑独自咖啡厅享受思考心流:82. 删除排序链表中的重复元素 II
  • DAY28-类的定义和方法
  • 计算机视觉与深度学习 | LSTM应用于数据插值
  • 下集:一条打包到底的静态部署之路
  • JMeter 教程:编写 POST 请求脚本访问百度
  • SQL Server 与 Oracle 常用函数对照表
  • 二进制与十进制互转的方法