phar反序列化
phar反序列化即在文件系统函数(file_exists()、is_dir()等)参数可控的情况下,配合phar://伪协议,可以不依赖unserialize()直接进行反序列化操作。
原理
phar文件是什么
phar,全称为PHP Archive,phar扩展提供了一种将整个PHP应用程序放入.phar文件中的方法,以方便移动、安装。.phar文件的最大特点是将几个文件组合成一个文件的便捷方式,.phar文件提供了一种将完整的PHP程序分布在一个文件中并从该文件中运行的方法。
可以将phar文件类比为一个压缩文件
phar文件结构
- a stub :可以理解为一个标志,格式为
xxx<?php xxx; __HALT_COMPILER();?>
,前面内容不限,但必须以__HALT_COMPILER();?>
来结尾,否则phar扩展将无法识别这个文件为phar文件。 - a manifest describing the contents :phar文件本质上是一种压缩文件,其中每个被压缩文件的权限、属性等信息都放在这部分。这部分还会以序列化的形式存储用户自定义的meta-data,这是上述攻击手法最核心的地方。
- the file contents :被压缩文件的内容。
- [optional] a signature for verifying Phar integrity (phar file format only) :签名,放在文件末尾。

demo
注意:如果想要生成phar文件,要将php.ini中的phar.readonly选项设置为Off,否则无法生成phar文件。
<?php
class Test {}
$o = new Test();
@unlink("phar.phar");
$phar = new Phar("phar.phar"); //后缀名必须为phar
$phar->startBuffering();
$phar->setStub("<?php __HALT_COMPILER(); ?>"); //设置stub
$phar->setMetadata($o); //将自定义的meta-data存入manifest
$phar->addFromString("test.txt", "test"); //添加要压缩的文件
//签名自动计算
$phar->stopBuffering();
?>
可以看到meta-data是以序列化的形式存储的:
既然有了序列化,那么php程序在利用phar文件的时候必然要进行反序列化,有些函数就会内置反序列化的功能,利用这个函数的反序列化功能就可以实现phar中的meta-data反序列化攻击了
受影响的函数

相关脚本
phar生成脚本.phpphar_gzip压缩及重新打包脚本.py
如果题目源码有过滤了phar的特征值__HALT_COMPILER();
,则可以使用压缩的方法来绕过