1. 漏洞简介
1.1 什么是文件上传漏洞
- 当Web服务没用验证文件上传的文件类型、名称、大小、内容等,则有可能导致恶意PHP、ASP文件绕过Web应用并顺利执行,此时攻击者可能直接拿到服务器权限WebShell。
- 当得到WebShell,则可以提取Web数据、删除Web文件、本地提取、拿下整个服务器甚至内网渗透。
- SQL注入攻击目标为数据库服务,而文件上传漏洞攻击的则是Web服务,实际渗透过程一般结合起来达到对集群的深度控制。
1.2 文件上传漏洞危害
- 服务器被控制
- 客户端被劫持
- 敏感信息泄露
- 恶意文件托管
- 未经授权操作
- 拒绝服务攻击
2. 文件上传漏洞预防
2.1 文件类型/大小/后缀/路径检测/文件名
- 前端通过lavascript验证(文件扩展名、大小)
- 后端检测MIME类型(白名单、重命名、大小)
- 后端检测目录路径(是否合法)确保文件名不包含任何可能被解释为目录或遍历序列(
../
) 的子字符串。
- 重命名上传的文件以避免可能导致现有文件被覆盖的冲突。
2.2 文件内容解析
- 排查恶意代码
- 在完全验证之前不要将文件上传到服务器的永久文件系统。
2.3 上传文件目录修改权限
- 无执行权限
- 读写权限分离
2.4 最小权限运行Web服务
- 降低被getshell后的风险
2.5 优化配置
- 利用php.ini配置
- 尽可能使用已建立的框架来预处理文件上传,而不是尝试编写自己的验证机制。
3. 文件上传漏洞绕过
3.1 客户端Javascript检测情况
- 修改前端js绕过
3.2 服务器安全检测
3.2.1 修改MIME类型
- 修改 HTTP Header 中的
content-type
- 有的站点使用文件头来检测文件类型,这种检查可以在Shell前加入对应的字节以绕过检查。几种常见的文件类型的头字节如下表所示
类型 | 二进制值 |
JPG | FF D8 FF E0 00 10 4A 46 49 46 |
GIF | 47 49 46 38 39 61 |
PNG | 89 50 4E 47 |
TIF | 49 49 2A 00 |
BMP | 42 4D |
- 修改文件扩展名
- 部分服务仅根据后缀、上传时的信息或Magic Header来判断文件类型,此时可以绕过。
- php由于历史原因,部分解释器可能支持符合正则
/ph(p[2-7]?|t(ml)?)/
的后缀,如php
/php5
/pht
/phtml
/shtml
/pwml
/phtm
等 可在禁止上传php文件时测试该类型。 - jsp引擎则可能会解析
jspx
/jspf
/jspa
/jsw
/jsv
/jtml
等后缀,asp支持asa
/asax
/cer
/cdx
/aspx
/ascx
/ashx
/asmx
/asp{80-90}
等后缀。 - 除了这些绕过,其他的后缀同样可能带来问题,如
vbs
/asis
/sh
/reg
/cgi
/exe
/dll
/com
/bat
/pl
/cfc
/cfm
/ini
等。 - 还可通过修改后缀,如:异形后缀、双写、大小写、编码
- 提供多个扩展。根据用于解析文件名的算法,以下文件可能被解释为 PHP 文件或 JPG 图像:
exploit.php.jpg
- 添加尾随字符。一些组件会去除或忽略尾随空格、点等:
exploit.php.
- 尝试对点、正斜杠和反斜杠使用 URL 编码(或双 URL 编码)。如果在验证文件扩展名时该值没有被解码,但后来在服务器端被解码,这也可以让您上传否则会被阻止的恶意文件:
exploit%2Ephp
- 在文件扩展名前添加分号或 URL 编码的空字节字符。如果验证是用 PHP 或 Java 等高级语言编写的,但服务器使用 C/C++ 中的低级函数处理文件,例如,这可能会导致文件名结尾出现差异:
exploit.asp;.jpg
exploit.asp%00.jpg
- 尝试使用多字节 unicode 字符,在 unicode 转换或规范化后可能会转换为空字节和点。
xC0 x2E
如果文件名被解析为 UTF-8 字符串,则类似xC4 xAE
或序列xC0 xAE
可能会被转换为x2E
,但随后会在用于路径之前转换为 ASCII 字符。
3.2.2 修改目录路径检测
- 截断绕过
3.2.3 系统命名检测
在Windows系统中,上传
index.php.
会重命名为 .
,可以绕过后缀检查。 也可尝试 index.php%20
, index.php:1.jpg
index.php::$DATA
等。 在Linux系统中,可以尝试上传名为 index.php/.
或 ./aa/../index.php/.
的文件3.3 .user.ini
在php执行的过程中,除了主
php.ini
之外,PHP 还会在每个目录下扫描 INI 文件,从被执行的 PHP 文件所在目录开始一直上升到 web 根目录($_SERVER['DOCUMENT_ROOT'] 所指定的)。如果被执行的 PHP 文件在 web 根目录之外,则只扫描该目录。 .user.ini
中可以定义除了PHP_INI_SYSTEM以外的模式的选项,故可以使用 .user.ini
加上非php后缀的文件构造一个shell,比如 auto_prepend_file=01.gif
。3.4 WAF绕过
有的waf在编写过程中考虑到性能原因,只处理一部分数据,这时可以通过加入大量垃圾数据来绕过其处理函数。
另外,Waf和Web系统对
boundary
的处理不一致,可以使用错误的 boundary
来完成绕过。3.5 竞争上传绕过
有的服务器采用了先保存,再删除不合法文件的方式,在这种服务器中,可以反复上传一个会生成Web Shell的文件并尝试访问,多次之后即可获得Shell。
3.6 基于 URL 的文件上传中的竞争条件
在允许您通过提供 URL 来上传文件的函数中可能会出现类似的竞争条件。在这种情况下,服务器必须通过 Internet 获取文件并创建本地副本,然后才能执行任何验证。
由于文件是使用 HTTP 加载的,因此开发人员无法使用其框架的内置机制来安全地验证文件。相反,他们可以手动创建自己的流程来临时存储和验证文件,这可能不太安全。
例如,如果文件被加载到具有随机名称的临时目录中,理论上,攻击者应该不可能利用任何竞争条件。如果他们不知道目录的名称,他们将无法请求文件以触发其执行。另一方面,如果随机目录名称是使用 PHP 之类的伪随机函数生成的
uniqid()
,则它可能会被暴力破解。为了使此类攻击更容易,您可以尝试延长处理文件所需的时间,从而延长暴力破解目录名称的窗口。一种方法是上传更大的文件。如果它以块的形式进行处理,您可以通过在开始时创建一个带有有效负载的恶意文件,然后是大量的任意填充字节来利用这一点。
3.6 编码或加密绕过
3.7 利用文件包含漏洞绕过
3.8 覆盖服务器配置
服务器通常不会执行文件,除非它们已被配置为这样做。例如,在 Apache 服务器执行客户端请求的 PHP 文件之前,开发人员可能必须将以下指令添加到他们的
/etc/apache2/apache2.conf
文件中:许多服务器还允许开发人员在各个目录中创建特殊的配置文件,以便覆盖或添加一个或多个全局设置。例如,Apache 服务器将从一个名为(
.htaccess
如果存在)的文件中加载特定于目录的配置。同样,开发人员可以使用
web.config
文件在 IIS 服务器上进行特定于目录的配置。这可能包括如下指令,在这种情况下允许将 JSON 文件提供给用户:Web 服务器在存在时使用这些类型的配置文件,但通常不允许您使用 HTTP 请求访问它们。但是,您可能偶尔会发现无法阻止您上传自己的恶意配置文件的服务器。在这种情况下,即使您需要的文件扩展名被列入黑名单,您也可以欺骗服务器将任意自定义文件扩展名映射到可执行的 MIME 类型。
4. 靶场练习
4.1 使用 Burpsuite 官方靶场练习
4.1.1 Lab: Remote code execution via web shell upload
题目:通过 web shell 上传远程执行代码
- 在账户内上传无限制,即可上传脚本
- 在上传图片作为头像时候,点击 Burp 的 Proxy 中 HTTP History 的 Filter 中的:

- 发现在上传完成返回账户时候会通过
GET
加载文件

- 那么通过上传 PHP 脚本:
<?php echo file_get_contents('/home/carlos/secret'); ?>
- 然后返回账户,在 Burp 查看获取文件的
GET
请求便会发现钥匙

4.1.2 Lab: Web shell upload via Content-Type restriction bypass
题目:通过 Content-Type 限制绕过 Web shell 上传
思路:修改
Content-Type
类型绕过- 在正常上传 PHP 脚本通过 Burp 拦截会发现,
Content-Type
不符合

- 通过在 Burp 修改为
image/png
成功上传 PHP 脚本,返回账户,成功获取钥匙

4.1.3 Lab: Web shell upload via path traversal
题目:通过路径遍历上传 Web shell
思路:修改路径将文件上传到非该路径
- 正常情况下,在本题中上传的文件均当作文本,不执行
- 那么利用路径绕过,在上传脚本文件的时候用 Burp 进行拦截,修改文件路径为
../1.php
后放行,即将文件存储于上一级目录下,在路径中将/
进行 URL 编码以绕过路径提取

- 在修改成功后上传,返回账户查看
GET
请求,发现钥匙

4.1.4 Lab: Web shell upload via extension blacklist bypass
题目:通过扩展黑名单绕过 Web shell 上传
思路:通过上传配置文件
.htaccess
使得可以自定义 MIME 类型以绕过类型检查- 在尝试上传 PHP 脚本的时候发现会出现错误

- 修改
filename
为.htaccess
,然后将Content-Type
修改为text/plain
文件中包含
AddType application/x-httpd-php .l33t

- 上传后缀为
.l33t
的一句话木马,
<?php echo file_get_contents('/home/carlos/secret'); ?>
会自动映射到
x-httpd-php
类型
- 回到账户,会发现钥匙

4.1.5 Lab: Web shell upload via obfuscated file extension
题目:通过混淆文件扩展名上传 Web shell
思路:通过修改后缀名绕过检测
- 在尝试上传脚本文件的时候会发现只允许上传 Jpg 或 Png 文件,那么修改文件后缀名字,在后缀名字面前添加 URL 编码
%00
即空字节编码;

- 然后发送时候会发现系统剥离了文件空字节和后面的 Jpg 后缀;

- 当返回账户时候修改访问文件为

- 则能在返回结果中发现钥匙
4.1.6 Lab: Remote code execution via polyglot web shell upload
题目:通过多语言 Web shell 上传远程执行代码
思路:在本题目中不能直接提交非
jpg
或 png
的文件,但没有对文件后缀进行限制,则将图片和脚本文件结合,以 php
后缀从而绕过检测。- 尝试上传脚本文件,发现出现上传文件错误;

- 通过在cmd中使用
copy 1.jpg /b+1.php/a 2.php
将1.jpg
和1.php
脚本文件生成包含图片二进制码的2.php
脚本文件,上传;
1.php
脚本文件:合成的
2.php
文件包含:
- 再返回账号然后在
GET
请求2.php
文件中发现钥匙;

参考文章
本文章仅提供学习使用,有任何问题,欢迎您在底部评论区留言,一起交流~
- Author:KoGe
- URL:https://www.shipangshuo.xyz/article/file-upload
- Copyright:All articles in this blog, except for special statements, adopt BY-NC-SA agreement. Please indicate the source!
Relate Posts