PHP Phar反序列化
PHP Phar反序列化
昨天讲了PHP中的session反序列化,今天就再浅谈一下Phar反序列化
Phar反序列化可以做到的花样有很多,这篇博客就简单说一说当作笔记
一、Phar 相关基础
Phar是将php文件打包而成的一种压缩文档,类似于Java中的jar包,在PHP 5.3 或更高版本中默认开启。它有一个特性就是phar文件会以序列化的形式储存用户自定义的meta-data。以扩展反序列化漏洞的攻击面,配合phar://协议使用。
所有PHAR文件都使用.phar作为文件扩展名,PHAR格式的归档需要使用自己写的PHP代码。
PHAR文件的本质同就是一种特殊的压缩文件,所以将后缀改为zip后是可以解压的。读取phar文件所用到的伪协议phar://是可以直接打开压缩文件的。 PHAR文件默认状态是只读的,使用Phar文件不需要任何的配置。但我们在构筑脚本时需要生成phar文件,此时应在php.ini中关闭phar.readonly,把前面的;注释符删掉,还有下面有一个phar.require_hash = On,前面的注释符也删了。

Phar 文件结构
- 文件标识头 格式为
xxx<?php xxx; __HALT_COMPILER();?>,前面内容不限,但必须以__HALT_COMPILER();?>来结尾,否则phar扩展将无法识别这个文件为phar文件。 - 压缩文件信息 phar本质上是一种压缩文件,那就有存储文件的地方。第二段
a manifest describing the contents,这是存放压缩文件权限、属性等信息的地方,这部分还会以序列化的形式存储用户自定义的meta-data,是反序列化的攻击点。 - 压缩文件内容 存放phar内的文件,这部分无关紧要,有东西存进去就好。
- 数字签名 放在文件末尾,格式如下
就是这个文件由四部分组成,每种文件都是有它独特的一种文件格式的,有首有尾。而__HALT_COMPILER();就是相当于图片中的文件头的功能,没有它,图片无法解析,同样的,没有文件头,php识别不出来它是phar文件,也就无法起作用。
生成 Phar 文件
1 | |
编译后可以看到看到文件头是<?php __halt_compiler(); ?>以及中间的部分内容是序列化的形式存在于这个文件中。
该方法在文件系统函数(file_exists()、is_dir()等)参数可控的情况下,配合phar://伪协议,可以不依赖unserialize()直接进行反序列化操作。
https://paper.seebug.org/680/得知:有序列化数据必然会有反序列化操作,php一大部分的文件系统函数在通过`phar://`伪协议解析phar文件时,都会将`meta-data`进行反序列化,测试后受影响的函数如下:(仿照大佬的图)
这里使用file_get_contents()函数来进行实验。
1 | |

析构方法被调用,注意此处 weakup 等方法不会被调用
这样就可以在不调用unserialize()的情况下进行反序列化操作
__HALT_COMPILER();必须大写,小写不会被识别出来。导致无法进行反序列化操作。
因为考虑到在上传的时候,可能只会允许上传图片(jpg/png/gif),上传时将test.phar修改文件扩展名为jpg也可以进行反序列化,不会影响解析。
如果对文件头有识别的,也可以使用GIF文件头GIF89a来绕过检测,具体操作与文件上传部分细节类似,不再赘述。
二、Phar 反序列化漏洞利用
既然很多函数可以触发phar反序列化,那么接下来就要实际利用该漏洞
漏洞利用条件
- phar文件要能够上传到服务器端。
- 要有可用的魔术方法作为“跳板”。
- 文件操作函数的参数可控,且
:、/、phar等特殊字符没有被过滤
接下来一个题目为例
[HNCTF 2022 WEEK3]ez_phar
题目代码如下
1 | |
可以看到在源码中有file_exists()函数,这个函数在上面受影响的图表中有
题目提示upload something,所以扫描一下,有upload.php

然后我们用这个代码生成一个.phar文件
1 | |
然后运行之后在当前目录下生成了一个2.phar文件,将这个文件改名为2.jpg上传,然后返回主页面,传入?filename=phar://./upload/2.jpg
ok,有了,然后直接获取flag就行