文件上传漏洞-学习笔记
参考资料:
【WEB】文件上传 | 狼组安全团队公开知识库
[Web安全]文件上传漏洞及绕过基础详解+实操_截断绕过-CSDN博客
一、什么是文件上传漏洞?
文件上传漏洞是指 Web 应用程序在处理用户上传文件的功能时,没有对上传的文件进行严格、充分的验证和过滤,导致攻击者可以上传恶意文件(如 Webshell、病毒、恶意脚本等)到服务器上。一旦上传成功,攻击者可能通过访问该文件,获得服务器的控制权、执行任意命令、窃取数据、篡改网页等。
二、文件上传的过程
- 客户端: 用户在浏览器选择要上传的文件。
- 客户端验证(可选): 浏览器端可能通过 JavaScript 对文件类型、大小进行初步检查。
- 服务器接收: 文件数据通过 HTTP POST 请求发送到服务器。
- 服务器端处理:
- Web 应用程序接收文件数据。
- 验证与过滤(关键步骤): 程序对文件进行检查(如后缀名、MIME 类型、文件头、内容扫描等)。
- 临时存储: 文件通常先被存放在服务器的临时目录中。
- 移动文件: 如果验证通过,文件被从临时目录移动到指定的、可通过 Web 访问或程序引用的最终路径。
- 返回结果: 服务器向客户端返回上传结果(成功或失败信息)。
三、文件上传返回值(PHP 示例)
PHP 在处理文件上传时,$_FILES['userfile']['error'] 会包含一个错误代码,常见的有:
UPLOAD_ERR_OK(0): 上传成功。UPLOAD_ERR_INI_SIZE(1): 上传的文件大小超过了php.ini中upload_max_filesize指令限制的值。UPLOAD_ERR_FORM_SIZE(2): 上传文件的大小超过了 HTML 表单中MAX_FILE_SIZE选项指定的值。UPLOAD_ERR_PARTIAL(3): 文件只有部分被上传。UPLOAD_ERR_NO_FILE(4): 没有文件被上传。UPLOAD_ERR_NO_TMP_DIR(6): 找不到临时文件夹。UPLOAD_ERR_CANT_WRITE(7): 文件写入失败。UPLOAD_ERR_EXTENSION(8): PHP 扩展程序停止了文件上传。
四、什么是 Webshell?
Webshell 本质上是一个运行在 Web 服务器上的服务端脚本文件(如 PHP、ASP、JSP、ASPX 等编写),它充当了一个可以通过 Web 浏览器访问的远程管理后门。攻击者上传 Webshell 成功后,可以通过访问这个 Webshell 文件,执行系统命令、管理文件、操作数据库、查看服务器信息等,从而达到控制网站或服务器的目的。
五、Webshell 的分类
| 分类 | 体量 | 特点 |
|---|---|---|
| 大马 | 体积大 | 功能全面,通常包含文件管理、数据库管理、命令执行、端口扫描等多种功能。常进行代码加密或混淆以躲避检测。 |
| 小马 | 体积小 | 功能单一,通常只包含核心功能,如文件上传或命令执行,用于后续上传大马或执行简单命令。 |
| 一句话木马 | 极短 | 代码通常只有一行,隐蔽性强。需要配合客户端工具(如中国蚁剑、菜刀、Behinder)使用。易于变形和插入正常文件中,难以检测。 |
六、文件上传的攻击方法/步骤
- 信息收集: 寻找目标网站上存在文件上传功能的地方(如用户头像、附件上传、编辑器图片上传、资料导入等)。
- 初步测试: 尝试直接上传一个简单的 Webshell 文件(如
shell.php),看是否能成功,并尝试访问。 - 识别防护机制: 如果直接上传失败,分析错误提示、前端代码、服务器响应,判断服务器可能采用了哪种防护措施(前端 JS 检查、MIME 类型检查、后缀名黑/白名单、文件内容检查等)。
- 尝试绕过: 针对识别出的防护机制,使用相应的绕过技术(详见下一节)。
- 上传成功与验证: 绕过成功后,上传 Webshell。
- 获取访问路径: 确定上传后的文件在服务器上的确切 URL 路径。这可能需要猜测、读取响应信息或利用其他漏洞。
- 连接 Webshell: 使用 Webshell 管理工具(如蚁剑、菜刀)连接上传的 Webshell URL,验证是否能成功执行命令或管理文件。
- 后渗透(可选): 利用 Webshell 进行提权、信息收集、持久化等操作。
七、上传绕过技术
1. 绕过前端 JS 检测
- 原理: 只在浏览器端使用 JavaScript 检查文件后缀名,数据包未发送到服务器前进行拦截。
- 绕过方法:
- 禁用浏览器 JS: 在浏览器设置中临时禁用 JavaScript 功能。
- 修改前端代码: 使用浏览器开发者工具(F12)找到负责检查的 JS 代码,将其删除或修改判断逻辑。
- 抓包改包: 先将文件后缀改为允许的类型(如
.jpg)骗过 JS 检查,然后使用 Burp Suite 等代理工具抓取 HTTP 请求包,在发送给服务器前,将数据包中的文件名或后缀名改回恶意文件的后缀(如.php)。
2. 绕过 Content-Type 检测
- 原理: 服务器端检查 HTTP 请求头中的
Content-Type字段,判断文件类型是否在允许的列表中(如image/jpeg,image/png)。 - 绕过方法: 使用 Burp Suite 抓包,修改请求包中的
Content-Type字段为服务器允许的值(如image/jpeg),即使实际上传的是.php文件。
3. 黑名单绕过
- 原理: 服务器端维护一个不允许上传的文件后缀名列表(黑名单),如
.php,.asp,.jsp。 - 绕过方法:
- 寻找替代后缀名: 尝试使用未被列入黑名单但仍能被服务器解析为脚本的后缀名,如
php3,php4,php5,phtml,pht(Apache),asa,cer,cdx(IIS),jspx(JSP) 等。 - 大小写绕过: 如果服务器检查时未将后缀名统一转换为小写(或大写),可以尝试
pHp,PhP,PHP等。 - 特殊文件名绕过 (Windows):
- 末尾加点
.: Windows 会自动去除文件名末尾的点,上传shell.php.可能会被保存为shell.php。 - 末尾加空格
: Windows 会自动去除文件名末尾的空格,上传shell.php(抓包修改,文件名后加空格) 可能会被保存为shell.php。 - NTFS 交换数据流 (
::$DATA): 在文件名后附加::$DATA,如shell.php::$DATA,在某些 Windows 环境下,文件内容会写入shell.php本身。
- 末尾加点
- 双写绕过: 如果服务器过滤机制是简单地替换或删除黑名单中的子串(如将
php替换为空),可以尝试双写,如shell.pphphp,过滤后可能剩下shell.php。 . .绕过 (特定场景): 如果服务器过滤逻辑是先去点再去空格(或类似顺序),shell.php. .可能会绕过过滤。 (如 upload-labs 第十关)- 利用系统特性 (Windows): 文件名
shell.php:.jpg在特定环境下可能生成shell.php文件。Windows 下"等价于.,>等价于?,<等价于*,可能用于绕过正则。
- 寻找替代后缀名: 尝试使用未被列入黑名单但仍能被服务器解析为脚本的后缀名,如
4. 使用 .htaccess 绕过 (Apache)
- 原理:
.htaccess是 Apache 服务器的分布式配置文件。如果服务器允许上传并解析.htaccess文件,并且开启了AllowOverride选项,攻击者可以上传自定义的.htaccess文件来改变服务器行为。 - 绕过方法:
- 创建一个名为
.htaccess的文件。 - 在文件中写入指令,让 Apache 将特定后缀(甚至是所有文件)当作 PHP 执行。例如:
SetHandler application/x-httpd-php(将当前目录下所有文件当作 PHP 解析)AddType application/x-httpd-php .jpg(将.jpg文件当作 PHP 解析)
- 上传这个
.htaccess文件到目标目录。 - 上传一个包含 Webshell 代码的文件,其后缀名符合
.htaccess文件中设置的规则(如shell.jpg)。 - 访问这个
shell.jpg文件,它将被 Apache 当作 PHP 执行。
- 创建一个名为
5. 白名单绕过
- 原理: 服务器只允许上传指定后缀名的文件(白名单),如
jpg,png,gif。这通常比黑名单更安全,但仍有绕过可能。 - 绕过方法:
- %00 截断 (路径/文件名截断):
- 条件: PHP 版本 < 5.3.4 且
magic_quotes_gpc配置为 Off。 - 原理:
%00(URL 编码的 NULL 字节) 在 C 语言系的函数中通常表示字符串结束。如果上传路径或文件名参数可控,可以在路径中注入%00。 - GET 型截断: 如
save_path=../upload/shell.php%00,后面即使拼接了.jpg,最终保存路径可能只取到shell.php。 - POST 型截断: POST 请求中的
%00不会被自动解码,需要在 Burp Suite 中找到包含路径的参数,修改为../upload/shell.php%00,然后对%00进行 URL Decode (Hex 视图下修改为00) 再发送。 - 目的: 使服务器在拼接最终保存路径时,在
%00处截断,丢弃后面用于满足白名单验证的后缀(如.jpg),从而以期望的恶意后缀(如.php)保存文件。
- 条件: PHP 版本 < 5.3.4 且
- %00 截断 (路径/文件名截断):
6. 解析漏洞绕过
- 原理: 利用 Web 服务器(Apache, Nginx, IIS)自身或其与脚本解释器(如 PHP)配合时的解析缺陷。
- 常见漏洞:
- Apache 解析漏洞:
- 从右向左解析后缀,不认识的后缀向前跳过。
shell.php.xxx会被解析为shell.php。 .htaccess配置错误。AddHandler或AddType配置了非标准后缀(如php5,phtml)。
- 从右向左解析后缀,不认识的后缀向前跳过。
- Nginx 解析漏洞:
cgi.fix_pathinfo=1(PHP 配置) + Nginx 配置不当:访问shell.jpg/xxx.php或shell.jpg%00.php时,shell.jpg可能被当作 PHP 执行。- Nginx < 0.8.41 空字节代码执行漏洞。
- IIS 解析漏洞:
- 目录解析: 目录名以
.asp,.asa结尾时,该目录下的所有文件(无论后缀)都可能被当作 ASP 执行。 - 文件解析: 文件名
shell.asp;.jpg可能被当作shell.asp执行。 - IIS 7/7.5 + PHP (FastCGI): 类似 Nginx 的
cgi.fix_pathinfo问题,访问shell.jpg/.php可能导致shell.jpg被当作 PHP 执行。
- 目录解析: 目录名以
- Apache 解析漏洞:
7. 文件内容检测绕过
- 原理: 服务器不仅检查后缀名,还检查文件内容,如文件头(Magic Number)、调用
getimagesize()函数检查图片信息、扫描文件内容是否包含恶意代码特征(如<?php)。 - 绕过方法:
- 伪造文件头: 在 Webshell 代码前添加合法的文件头标识(Magic Number),如
GIF89a(GIF),‰PNG(PNG),ÿØÿà(JPG)。 - 图片马: 将 Webshell 代码插入到正常图片文件的元数据(如 EXIF)或文件末尾,或者与图片文件二进制合并。需要配合文件包含漏洞 (LFI) 或特定解析漏洞才能执行。
- 绕过内容扫描:
- 使用短标签
<?= @eval($_POST['cmd']);?>(需服务器开启short_open_tag)。 - 使用
<script language="php">@eval($_POST['cmd']);</script>。 - 对 Webshell 代码进行编码、加密、混淆。
- 使用短标签
- 二次渲染绕过: 某些网站会对上传的图片进行压缩、裁剪等二次处理。可以构造特殊的图片,使得 Webshell 代码在渲染后仍然保留并可执行。这通常需要对 GD 库等图像处理库有深入了解。
- 伪造文件头: 在 Webshell 代码前添加合法的文件头标识(Magic Number),如
8. 竞争条件 (Race Condition) 绕过
- 原理: 网站的处理逻辑是:先将文件上传到临时目录 -> 再检查文件是否合法 -> 如果不合法则删除。在“上传完成”到“检查并删除”之间存在一个短暂的时间窗口。
- 绕过方法:
- 上传一个“写入器”脚本(如
write.php),其功能是创建或写入真正的 Webshell 文件(如shell.php)。 - 在上传
write.php后,立即、高频地访问write.php的 URL。 - 如果在
write.php被删除之前成功访问到它,它就会执行并创建shell.php。 shell.php因为不是直接上传的,可能不会被检查逻辑删除。
- 上传一个“写入器”脚本(如
9. 双文件上传绕过
- 原理: 网站允许一次上传多个文件,但其安全检查逻辑只检查了第一个文件。
- 绕过方法: 同时上传两个文件,第一个是合法的(如
image.jpg),第二个是 Webshell(如shell.php)。
10. 目录穿越漏洞结合
- 原理: 如果上传时可以通过修改文件名或路径参数实现目录穿越(如
filename=../../shell.php),即使文件保存在非 Web 目录下,也可能通过穿越将其保存到 Web 可访问路径下。
- Title: 文件上传漏洞-学习笔记
- Author: KaldX
- Created at : 2025-04-22 20:00:00
- Updated at : 2025-04-22 20:00:00
- Link: https://blog.kaldx.com/2025/04/22/文件上传漏洞-学习笔记/
- License: This work is licensed under CC BY-NC-SA 4.0.
Comments