Phar反序列化攻击可绕过unserialize()调用限制,通过phar://协议或自动识别文件头触发;需满足PHP≥5.3、phar.readonly=Off、可控文件路径及存在文件操作函数;恶意Phar将载荷存于Manifest元数据,利用__destruct等魔术方法执行命令。

Phar文件能绕过传统反序列化必须调用unserialize()的限制,只要存在任意文件操作函数处理恶意Phar,就可能触发反序列化。核心在于Phar的Manifest区域存储了序列化对象,PHP在解析Phar时会自动反序列化这部分数据。
触发前提条件
成功利用需同时满足三点:
- 目标PHP版本 ≥ 5.3,且
phar.readonly = Off(php.ini中配置) - 服务器允许上传Phar文件,或攻击者能控制文件路径(如临时上传目录)
- 代码中存在对用户可控路径的文件操作,例如:
file_exists()、is_dir()、filesize()、file_get_contents()、getimagesize()等
构造恶意Phar文件
关键步骤是将攻击载荷写入Manifest元数据区:
- 定义一个含危险魔术方法(如
__destruct或__wakeup)的类 - 用
Phar::setMetadata()把该类实例写入Phar元数据 - 设置合法stub(如
<?php __HALT_COMPILER(); ?>),并至少添加一个虚拟文件内容 - 关闭缓冲后,重命名文件为
.phar,也可改后缀绕过检测(如.jpg、.png)
服务端触发方式
攻击者只需让目标代码执行类似以下任一调用即可触发:
立即学习“PHP免费学习笔记(深入)”;
-
file_exists('phar://upload/evil.jpg/test.txt');(注意协议+路径拼接) file_get_contents('phar://tmp/phpA1B2C3.jpg');-
getimagesize($_FILES['avatar']['tmp_name']);(若上传的是伪装Phar图片)
只要参数中含phar://伪协议或PHP自动识别Phar文件头,就会解析Manifest并反序列化元数据。
常见绕过技巧
防御方常过滤.phar后缀或拦截协议名,攻击者有对应应对方式:
- 将Phar文件改为
.jpg、.png等白名单后缀,仍可被phar://识别 - 嵌套进ZIP/TAR压缩包,再通过
zip://或tar://协议间接加载Phar - PHP 8.0+中
phar.stream.unchanged默认开启,但若关闭或使用旧版本,仍可生效 - 部分场景下,即使没显式写
phar://,PHP也会在file_exists($path)中自动识别本地Phar文件头



















