Phar反序列化漏洞是PHP中的一种安全漏洞,与PHP的Phar扩展和对象反序列化机制有关。Phar扩展允许将多个文件打包成一个单一的Phar归档文件,类似于ZIP或TAR。当Phar归档文件被加载时,PHP会自动反序列化其中的元数据。如果攻击者能够控制Phar归档文件的内容,他们可以构造恶意的元数据,使其在反序列化时触发任意代码执行。这种漏洞通常发生在应用程序对用户上传的文件处理不当,允许攻击者上传并加载恶意的Phar文件时。
前提知识
怎么构造pop
链:
序列化后,类便会被重构,我们可以通过,覆盖类中的属性变量,来触发魔术方法,进而执行危险方法或函数。
phar
文件结构
phar
文件主要由四部分组成
- a stub
格式为:xxx<?php xxx;__HALT_COMPILER();?>
。要求是必须以**__HALT_COMPILER();?>
**结尾,否则phar
拓展将无法识别这个文件为phar
文件。
- a manifest describing the contents
phar
文件中被压缩的文件的一些信息,其中Meta-data
部分的信息会以序列化的形式储存,这里是漏洞利用的关键点。
- the file contents
被压缩的文件的内容。
- a signature for verifying Phar integrity
签名,放在文件末尾,格式如下:

注意:需要修改php.ini
文件中的phar.readonly = On
为phar.readonly = Off
,才能成功生成.phar
文件。
一个简单的例子
|
运行代码,会在同目录下生成一个phar.phar
文件,其内容如下,可以看到meta-data
是以序列化的形式存储的。

php
大部分的文件系统函数,在参数可控的情况下,通过phar://
伪协议解析phar
文件时,都会将meta-data
进行反序列化。如下:
进行反序列化操作
|
利用前提条件
先简单说一下phar
反序列化漏洞能够利用的基本前提:
phar
文件能够上传到服务器- 要有可利用的魔术方法,来触发反序列化
- 文件操作函数的参数可控,且:
/
、phar
字符没有被过滤
ctf
实战练习
1.[CISCN2019 华北赛区 Day1 Web1]Dropbox
2.[SWPUCTF 2018]SimplePHP
怎么构造pop
链:
序列化后,类便会被重构,我们可以通过,覆盖类中的属性变量,来触发魔术方法,进而执行危险方法或函数。
|
3.[GXYCTF2019]BabysqliV3.0
分析upload.php
源码
|
实例化一个类的对象后,会自发调用__construct()
构造函数。
function __construct() #构造函数。它在创建类的新对象时自动调用 |
然后会调用upload($file)
方法,下面的[^a-z0-9]
表示,匹配任何非小写字母或非数字的符号。
function upload($file) #file = $_FILES["file"] |
上面最后一行代码看起来比较乱,其实就是利用.
连接了五个部分,下面我框出了要连接的内容。
如果其中,$file['tmp_name']=tmp_name
、$this->Filename=filename
,那么连接起来就是这样的:move_uploaded_file('tmp_name', 'filename');
。
而move_uploaded_file()
是一个用于将上传的文件,从临时目录移动到新的路径下的函数,如下:
move_uploaded_file('临时文件路径', '目标文件路径'); |
接下来将随着类的销毁,会自发调用__destruct
析构函数。
function __destruct() |
成功绕过if
后,便能执行move_uploaded_file($file['tmp_name'], $this->Filename);
。然后回到主程序流中,即将进行if
语句的判断,但此时也触发了__toString()
函数。
function __toString() |
__toString()
执行完后,程序会接着执行echo file_get_contents($this->Filename);
。
phar
反序列化利用思路
Uploader
类中有一个魔术方法__destruct()
,其中我们可以利用eval($this->cmd)
,但是要绕过if
语句,否则,$this->cmd
会被重新赋值,那么exp.phar
中的对$this->cmd
值便无效了。
而绕过if
需要使token
等于$_SESSION['user']
,通过前面对源码的分析及上传文件后的回显可知,$_SESSION['user']
其实就是回显里的.txt
前面的一串字符。
exp.php
|
解题过程
随便上传一个文件,点击两次’上传’,得到token
。
然后运行exp.php
,生成exp.phar
文件,上传exp.phar
,这里只点击一次’上传’即可。
再随便上传一个文件,Burp
抓包,添加参数name=/var/www/html/flag.php
后,发送即可获得flag
。
唉,这道题写一天了,也没真正搞清楚,只能先放这儿了。