任意文件上传漏洞

概述 (Overview)

许多网站提供文件上传功能,例如用户上传头像、上传附件、导入数据等。当用户上传文件时,后端服务器通常会对文件进行一系列检查(如文件类型、扩展名、大小),然后可能进行重命名并存储到指定目录。

如果后端对上传文件的安全检查缺失或不够严格,攻击者就可能上传恶意的可执行文件(如WebShell,通常是一句话木马),并在服务器上执行该文件,从而获得服务器的控制权(即GetShell)。

利用条件 (Conditions)

  • 存在文件上传的功能点。
  • 应用程序允许上传动态脚本文件(如 .php, .jsp, .asp, .aspx)或可以通过其他方式(如解析漏洞)使上传的文件被当作脚本执行。
  • 上传文件的存储目录具有Web服务器的执行权限。
  • 攻击者能够通过URL访问到上传的恶意脚本文件。

上传检测流程与绕过点 (Upload Detection Process & Bypass Points)

一个完整的文件上传流程可能涉及多个环节的检测:

  1. 前端提交 (Client-Side):
    • 检测: JavaScript检测(检查文件扩展名、MIME类型)、Flash AS检测(旧)。
    • 绕过点: 可以通过修改前端JS代码、禁用JS、或使用代理工具拦截修改HTTP请求绕过。
  2. 数据传输 (Data Transmission):
    • 检测: WAF(Web应用防火墙)、IPS(入侵防御系统)可能拦截包含恶意特征(如已知WebShell代码、危险扩展名)的请求。
    • 绕过点: 编码、混淆Payload、分块传输、利用协议特性等。
  3. 后端处理 (Server-Side):
    • 检测:
      • 扩展名检测 (Extension Check): 黑名单(禁止 .php 等)、白名单(只允许 .jpg, .png 等)。
      • MIME类型检测 (MIME Type Check): 检查HTTP请求头中的 Content-Type 字段。
      • 文件头检测 (File Header/Magic Number Check): 检查文件开头的几个字节是否符合特定文件类型的标识。
      • 文件内容检测 (Content Inspection): 检查文件内容是否包含恶意代码特征(如 eval, system 等函数)。
      • 文件结构/图像校验 (Image Validation): 调用图像处理库(如PHP GD库)检查文件是否为有效图像。
    • 绕过点: 最常见的绕过发生在此阶段,方法多样,见下文。
  4. 写入文件系统 (File System Write):
    • 处理: 文件重命名(可能基于时间戳、随机数、用户ID等,使预测文件名困难)、存储到特定目录。
    • 检测: 服务器上的杀毒软件可能查杀恶意文件。
    • 绕过点: 如果重命名规则可预测或存在缺陷,仍可能找到文件。免杀技术绕过杀软。
  5. 访问文件 (File Access):
    • 限制: 上传目录可能没有执行权限(Web服务器配置)、上传后的文件名未知、目录禁止Web访问。
    • 绕过点: 利用解析漏洞、找到泄露文件名的途径、利用目录穿越将文件存到可执行目录。

绕过方法 (Bypass Techniques)

客户端检测绕过 (Bypassing Client-Side Checks)

  • 原理: 客户端检测(主要是JavaScript)仅在用户浏览器中执行,容易被绕过。
  • 方法:
    1. 禁用JavaScript: 在浏览器中临时禁用JavaScript。
    2. 修改前端代码: 使用浏览器开发者工具,找到并删除或修改执行文件检查的JavaScript代码(如 onchange, onsubmit 事件中的校验函数)。
    3. 抓包改包 (通用方法):
      • 先上传一个扩展名符合要求的文件(如 .jpg)。
      • 使用代理工具(如 Burp Suite)拦截HTTP请求。
      • 修改请求中的文件名(filename="shell.php")和可能的 Content-Type
      • 发送修改后的请求。

APP端抓包 (Mobile App Traffic Interception)

  • 设置代理:
    1. 在Burp Suite中设置代理监听 All interfaces
    2. 在手机的Wi-Fi设置中,配置HTTP代理指向运行Burp的电脑IP和端口(如 192.168.1.100:8080)。
    3. 手机浏览器访问 http://<burp_ip>:<burp_port> (如 http://192.168.1.100:8080) 下载并安装Burp的CA证书。
    4. Android: 可能需要将证书扩展名改为 .crt,然后在 设置 -> 安全 -> 加密与凭据 -> 从存储设备安装 (或类似路径) 安装证书。对于Android 7+,应用默认不信任用户安装的CA证书,可能需要Root设备并使用Magisk模块(如 Move Certificates)或修改应用Manifest(如果能重新打包)。
    5. iOS: 安装描述文件后,需要在 设置 -> 通用 -> 关于本机 -> 证书信任设置 中手动信任该根证书。
  • 绕过证书固定 (Certificate Pinning):
    • 如果APP使用了证书固定,直接设置代理会失败。
    • 需要使用框架(如 Xposed + JustTrustMe, Frida)来Hook掉APP的证书校验逻辑。
  • 模拟器配置 (Mumu为例):
    • 可能需要使用 adb 命令打开Wi-Fi设置界面:
      adb connect 127.0.0.1:7555 # 连接模拟器 (端口可能不同)
      adb shell am start -a android.settings.WIFI_SETTINGS # 打开WiFi设置
      

服务器端检测绕过 (Bypassing Server-Side Checks)

  1. MIME类型检测绕过:

    • 原理: 服务器检查HTTP请求头中的 Content-Type 字段。此字段由浏览器(或客户端)设置,可以被篡改。
    • 方法: 抓包,将 Content-Type 修改为服务器允许的类型(白名单),如 image/jpeg, image/png
    • 常见白名单MIME类型: image/jpeg, image/png, image/gif, text/plain, application/pdf, application/msword, application/zip
  2. 文件头检测绕过 (Magic Number Check):

    • 原理: 服务器检查文件开头的几个字节(文件头/Magic Number)是否符合特定格式。
    • 方法: 在WebShell代码前添加合法的文件头。
    • 示例:
      • GIF89a<?php phpinfo(); ?> (保存为 .php 或配合解析漏洞)
      • \xFF\xD8\xFF<?php phpinfo(); ?> (JPEG文件头,注意需要是原始字节)
      • \x89PNG\r\n\x1a\n<?php phpinfo(); ?> (PNG文件头,注意需要是原始字节)
    • 注意: 文件扩展名仍需能被解析为脚本,或结合解析漏洞。
  3. 文件结构/图像校验绕过:

    • 原理: 服务器调用图像处理函数(如PHP的 getimagesize(), imagecreatefromgif())检查文件是否为有效的、完整的图像。简单添加文件头无法通过。
    • 方法: 制作图片马 (Image Webshell)。将一个合法的图片文件与WebShell代码合并。
    • Windows命令: copy /b image.jpg + shell.php webshell.jpg
    • Linux命令: cat image.jpg shell.php > webshell.jpg
    • 注意: 上传后的文件需要配合解析漏洞(如Apache AddHandler 配置错误)才能执行代码,或者用于包含漏洞(LFI)中。
  4. 恶意文件内容检测绕过 (Content Inspection):

    • 原理: WAF或服务器端代码扫描文件内容,查找已知的WebShell特征码或危险函数(如 eval, system, assert, base64_decode, java.lang.Runtime)。
    • 方法:
      • 使用混淆/编码: 对WebShell代码进行编码(Base64, Hex, URL)、拆分、变形,绕过特征匹配。
      • 使用免杀WebShell: 寻找或制作难以被检测到的WebShell。
        • Weevely: 一个强大的隐蔽PHP Webshell生成工具 (Kali自带)。
        • GitHub项目: 在GitHub搜索 webshell,但需自行判断安全性(可能包含后门)。
      • 利用语言特性: 使用不常见的函数组合、回调函数、反序列化等方式执行命令。

其他技巧 (Other Tricks)

  1. filename 属性绕过:
    • 场景: WAF可能只检查第一个 filename 属性的扩展名。
    • 方法: 抓包,在 Content-Disposition 头中添加多个 filename 属性。
      Content-Disposition: form-data; name="file"; filename="shell.jpg"; filename="shell.php"
      
      (具体效果依赖于服务器和WAF的解析方式)
  2. 目录穿越 (Path Traversal):
    • 场景: 上传目录可控(如通过参数指定子目录),且后端代码未正确处理 ../
    • 方法: 抓包修改上传路径,尝试使用 ../ 将文件上传到预期目录之外的可执行目录。
    • 示例: 正常上传到 /uploads/avatar/,尝试修改路径为 ../../webshell/shell.php,可能将文件上传到 /uploads/webshell/shell.php
  3. 可控扩展名检测类型:
    • 场景: 允许上传的扩展名列表由配置或参数控制。
    • 方法:
      • 后台配置: 如果获得后台权限,直接修改允许上传的扩展名列表,添加 .php 等。
      • 前端参数: 如果允许的类型在前端(如隐藏字段)或请求参数中传递,修改该参数值。

常见解析漏洞 (Common Parsing Vulnerabilities)

利用Web服务器或语言解释器的解析缺陷,使非预期扩展名的文件被当作脚本执行。

  1. IIS 5.x/6.0 解析漏洞:

    • 分号文件名 (.asp;.jpg): 服务器将 ; 后面的内容视为路径参数,文件 shell.asp;.jpg 会被当作 shell.asp 执行。
    • 目录名 (/shell.asp/): 名为 shell.asp 的目录下的所有文件(无论扩展名)都会被当作ASP脚本执行。
  2. Apache 解析漏洞 (配置错误):

    • 多后缀解析: 从右向左解析,直到遇到认识的扩展名。如果 httpd.conf 中有类似 AddHandler application/x-httpd-php .php 的配置,那么 shell.php.jpg 文件会被当作 shell.php 执行。
    • .htaccess 文件: 如果允许上传 .htaccess 文件,可以在其中添加 AddType application/x-httpd-php .jpg 使所有 .jpg 文件被当作PHP执行,或使用 <FilesMatch> 指令。
  3. Nginx 解析漏洞:

    • PHP CGI 路径修复 (cgi.fix_pathinfo): 当PHP配置 cgi.fix_pathinfo=1 (默认值) 时,Nginx + PHP-FPM 环境下访问 http://site.com/shell.jpg/xxx.php,如果 /shell.jpg/xxx.php 不存在,PHP会尝试将 /shell.jpg 作为PHP文件执行。需要Nginx配置将 .php 请求转发给PHP-FPM。
    • 空字节 (%00) 截断 (旧版本 Nginx < 0.8.41 + PHP < 5.3.4): 访问 http://site.com/shell.jpg%00.php 可能导致 shell.jpg 被当作PHP执行。
    • Nginx 文件名逻辑漏洞 (CVE-2013-4547): 影响版本 Nginx 0.8.41 - 1.4.3 / 1.5.0 - 1.5.7。上传带空格的文件名 shell.jpg (注意末尾空格),访问时请求 shell.jpg \0.php (空格+空字节+.php,需URL编码),可能导致 shell.jpg 文件被当作PHP执行。
  4. Apache 路径穿越与RCE (特定版本):

    • CVE-2021-41773 (Apache 2.4.49): 路径穿越漏洞,可读取Web目录外文件。如果启用了CGI,可能导致远程代码执行。
    • CVE-2021-42013 (Apache 2.4.50): 对上一个漏洞的不完整修复,仍然存在路径穿越。
    • 利用: 构造类似 /.%2e/.%2e/.%2e/etc/passwd 的URL进行目录穿越。

高级绕过技巧 (Advanced Bypass Techniques)

  1. 二次渲染/重绘图绕过:

    • 场景: 应用程序上传图片后,会调用GD库等图像处理库进行缩放、裁剪或加水印等操作(二次渲染),这通常会破坏嵌入在图片数据中的简单WebShell。
    • 方法:
      1. 上传一张正常图片,获取被服务器处理(渲染)后的图片。
      2. 比较处理前后的图片二进制数据,找到未被渲染过程改变的数据区域。
      3. 将WebShell代码精确地插入到这些“稳定”区域。
      4. 上传修改后的图片。由于WebShell在稳定区,二次渲染后代码可能仍然存活。
    • 工具: 有一些脚本尝试自动化这个过程,如 Bypass-PHP-GD-Process-To-RCE
  2. phpinfo() 与 LFI 联合利用 (PHP Multipart/form-data 临时文件):

    • 场景: 目标存在本地文件包含漏洞 (LFI),并且能访问 phpinfo() 页面,但不知道上传文件的绝对路径或WebShell被查杀。
    • 原理: PHP处理 multipart/form-data 类型(文件上传)的请求时,会将上传的文件内容保存到一个临时文件中(如 /tmp/phpXXXXXX)。这个临时文件名和路径会显示在 phpinfo() 页面的 $_FILES 变量信息中。脚本执行完毕后,临时文件会被删除。
    • 方法 (条件竞争):
      1. 构造一个包含文件上传(上传一个简单的PHP代码文件)和触发 phpinfo() 的请求。
      2. 通过发送大量数据(填充请求体)或并发请求等方式,尝试延长PHP脚本的执行时间,或使 phpinfo() 输出变慢(流式输出)。
      3. 在发送请求的同时,快速、并发地发送LFI请求,尝试包含 phpinfo() 中泄露的临时文件路径。
      4. 如果在临时文件被删除前成功包含了它,就能执行上传的PHP代码。
    • 工具: 有现成的脚本可以帮助实现这种条件竞争攻击,如 LFI Suite 或特定 PoC 脚本。
  3. 在线解压缩功能漏洞利用:

    • 场景: 网站允许上传 .zip, .rar 等压缩包,并在服务器端自动解压。
    • 方法:
      1. 直接打包WebShell: 将WebShell文件放入压缩包上传。
      2. 目录穿越: 在压缩包内创建包含 ../ 的路径,尝试将文件解压到Web目录或其他敏感位置。 (需要解压工具支持或存在漏洞)
      3. 软链接/符号链接: 在压缩包中包含指向服务器敏感文件(如 /etc/passwd)或目录(如 /)的软链接。如果服务器解压时遵循链接(通常不安全配置),可能读取或覆盖文件。
      4. Zip Slip 漏洞: 一种特殊的目录穿越,利用解压库处理包含 ../ 文件名的缺陷。
      5. 绕过内容检测: 如果服务器解压后会检查文件内容,可以尝试将WebShell放在深层目录结构中,或使用加密压缩包(如果支持并知道密码处理方式)。

防御策略 (Defense Strategies)

  1. 使用白名单验证扩展名: 仅允许上传已知安全的文件类型(如 .jpg, .png, .pdf, .docx),拒绝其他所有类型。避免使用黑名单。
  2. 严格检查MIME类型: 检查 Content-Type,但不能单独依赖此项(可伪造)。应结合扩展名检查。
  3. 文件内容检测:
    • 图像文件: 使用图像处理库(如PHP GD, ImageMagick)尝试打开并重新保存图片。无效图片或包含恶意代码的图片通常会导致处理失败或代码被破坏。
    • 扫描恶意特征: 使用服务器端杀毒软件或专门的WebShell扫描工具检查文件内容。
  4. 安全重命名:
    • 对上传的文件使用随机生成的、不可预测的文件名(如UUID)存储,并去掉原始扩展名或强制使用安全扩展名(如.dat)。
    • 在数据库中记录原始文件名与随机文件名、真实文件类型的映射关系。
  5. 隔离存储:
    • 将上传文件存储在Web根目录之外的、不可直接通过URL访问的独立目录。
    • 如果需要Web访问,通过后端脚本读取文件内容并设置正确的 Content-Type 输出,而不是直接链接到文件。
  6. 设置目录权限: 确保上传文件存储目录没有执行权限(移除Web服务器的脚本执行权限)。
  7. 限制文件大小: 对上传文件的大小进行合理限制。
  8. WAF/RASP: 使用Web应用防火墙或运行时应用自我保护(RASP)技术,帮助检测和阻止已知的上传攻击。
  9. 定期更新: 及时更新Web服务器、PHP/Java等语言环境、以及使用的第三方库,修复已知的解析漏洞和安全缺陷。
  10. 安全配置: 避免不安全的服务器配置(如Apache的 AddHandler 滥用,Nginx的 cgi.fix_pathinfo 问题)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值