phar反序列化

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();,则可以使用压缩的方法来绕过