利用PHAR协议进行PHP反序列化攻击

robots

 

PHAR (“Php ARchive”) 是PHP中的打包文件,相当于Java中的JAR文件,在php5.3或者更高的版本中默认开启。PHAR文件缺省状态是只读的,当我们要创建一个Phar文件需要修改php.ini中的phar.readonly,修改为:phar.readonly = 0

当通过phar://协议对phar文件进行文件操作时,将会对phar文件中的Meta-data进行反序列化操作,可能造成一些反序列化漏洞。

本文由锦行科技的安全研究团队提供,从攻击者的角度展示了PHAR反序列化攻击的原理和过程。

 

1 PHAR文件结构

stub phar:文件标识,格式为xxx<?php xxx;HALT_COMPILER();?>,该部分必须以 HALT_COMPILER();?> 进行结尾,否则将无法识别,前面的内容无限制要求。

manifest:压缩文件的属性等信息,其中的Meta-data会以序列化的形式存储。

contents:压缩文件的内容

signature
:签名,放在文件末尾

 

2 生成PHAR文件

生成程序如下:

生成phar文件,使用16进制工具查看,可以看到Meta-data中的序列化对象

 

3 测试反序列化

测试程序如下:

运行结果,可以看到打印了‘test’,证明对象被反序列化创建后销毁。

虽然在创建PHAR文件时后缀是固定的,但完成创建后我们是可以修改phar的后缀名的,例如修改成.jpg,当执行include(‘phar://phar.jpg’);时也可触发反序列化。

几乎所有文件操作函数都可触发phar反序列化

 

4CTF演示

题目地址:[CISCN2019 华北赛区 Day1 Web1]Dropbox(链接:https://buuoj.cn/challenges#%5BCISCN2019%20%E5%8D%8E%E5%8C%97%E8%B5%9B%E5%8C%BA%20Day1%20Web1%5DDropbox)

进入题目后,随意注册账号上传文件,上传点只能上传图片后缀图片

点击下载,有任意文件读取,但是不能读取flag.txt

于是读取网页源码,传入filename=../../xxx.php

detele.php

class.php

分析源代码

可以看到删除文件时使用了File类的delete函数,File类的delete使用了unlink函数,可以触发phar反序列化。

继续看到class.php的File类的close()函数中调用了file_get_contents函数,可以读取文件。但是要怎么触发呢,我们可以看到FileList的__call函数,如果我们可以让FileList参数files为数组且数组中一个类为File,只要有类可以执行$FileList->close(),就可以读取文件并在FileList的析构函数中显示出来了。我们看到User类的析构函数,执行了$db->close()。so,我们让User的$db参数等于FileList就行了。

利用链:User类的$db赋值为FileList类,User类的析构函数执行close方法->触发FileList的__call函数,让$file值为File,执行$file的close函数->File执行close读取文件,控制$filename为想读取的文件->FileList对象销毁,执行析构函数,回显结果。

生成phar文件代码:

生成phar文件,修改后缀为jpg,上传
删除文件处修改filename为‘phar://phar.jpg’,读取到flag文件

(完)