Luke a Pro

Luke Sun

Developer & Marketer

🇺🇦
EN||

文件上传漏洞

| , 2 minutes reading.

1. 定义

文件上传漏洞 发生在 Web 服务器允许用户在未经充分验证(如文件名、类型、内容或大小)的情况下,将文件上传至其文件系统时。

最严重的后果是 远程代码执行 (Remote Code Execution, RCE):攻击者上传一个脚本(如 shell.php),然后该脚本在服务器上被执行。

2. 技术原理

服务器通常根据文件扩展名或 MIME 类型来决定如何处理文件。

  1. 扩展名绕过: 攻击者将 shell.php 重命名为 shell.php.jpg 或利用零字节截断 shell.php%00.jpg
  2. MIME 伪造: 在发送 PHP 脚本时,将 HTTP 标头中的 Content-Type 修改为 image/jpeg
  3. 多语言型文件 (Polyglots): 创建一个合法的图像文件,但在其元数据 (EXIF) 中包含有效的 PHP 代码。

如果服务器将此类文件保存到公开目录(如 /uploads),且服务器配置允许在该目录下执行 PHP/ASP 文件,那么访问 site.com/uploads/shell.php 就会触发恶意程序的执行。

3. 攻击流程 (Web Shell)

sequenceDiagram
    participant Attacker as 攻击者
    participant Server as 服务器
    participant FS as 文件系统

    Attacker->>Server: POST /upload 将 shell.php 伪装为 shell.jpg
    Note right of Attacker: 内容: PHP Web Shell 代码

    Server->>Server: 检查扩展名 .jpg - 通过
    Server->>FS: 保存至 /var/www/uploads/shell.jpg

    Attacker->>Server: GET /uploads/shell.jpg
    Note right of Attacker: 服务器执行了 PHP 因为<br/>配置允许 .jpg 以脚本方式运行<br/>或文件被重命名回了 .php
    
    Server-->>Attacker: 返回命令执行结果

4. 真实案例:ImageTragick (2016)

目标: 使用 ImageMagick 的数千个网站。 漏洞类别: 文件处理 / 命令注入 (CVE-2016-3714)。

漏洞背景: ImageMagick 是一个被广泛使用的图像处理库(当时包括 Facebook 和 Yahoo 在内的许多网站都在使用它来缩放用户上传的照片)。 它在处理 SVG (矢量图) 文件时存在缺陷:支持通过“委托 (delegates)”执行 Shell 命令。

攻击过程: 攻击者上传了一个精心构造的图像文件(看起来是 .jpg.mvg),内容如下:

fill 'url(https://example.com/image.jpg"|ls "-la)'

当服务器尝试“缩放”这张图片时,ImageMagick 执行了 ls -la 命令。这意味着攻击者只需上传一张头像就能实现完全的远程代码执行。

5. 深度防御策略

A. 扩展名白名单 (Allowlist)

绝不使用黑名单(如禁止 .php, .exe)。攻击者总能找到绕过方法,如 .php5, .phtml 等。

  • 白名单机制: 仅接受特定的安全扩展名:.jpg, .png, .pdf

B. 内容校验 (魔数 Magic Bytes)

不要相信文件扩展名或 Content-Type 标头(这些都是用户可控的)。

  • 机制: 读取文件的前几个字节(魔数)来验证其真实类型。
    • JPEG = FF D8 FF
    • PNG = 89 50 4E 47
  • 如果魔数与扩展名不匹配,则拒绝文件。

C. 文件名随机化

不要使用用户提供的原始文件名(如 my_vacation.jpg)。

  • 防御措施: 在存储时将文件重命名为 UUID (如 f47ac10b...jpg)。这可以防止覆盖关键系统文件,并能防御部分路径遍历尝试。

D. 存储于 Web 根目录之外

将上传的文件存储在 Web 服务器无法直接访问的目录中(例如 S3 桶或私有文件夹)。通过一个读取文件流的控制器来间接提供文件内容。这能从根源上防止服务器直接“执行”上传的文件。

6. 参考资料