type
Post
status
Published
date
slug
summary
tags
CTF
推荐
category
CTF-Knowledge
category (1)
icon
password
comment
参考文章:
https://juejin.cn/post/7152298620656549896#heading-1
https://paper.seebug.org/680/
https://cloud.tencent.com/developer/article/2278965
PHP 反序列化
0x01 关于 Phar
Phar 含义
Phar 本质上还是一种压缩包,但它是 PHP 的压缩文档,类似于 jar 包在 Java 里面差不多的样子。它可以把多个文件存放至同一个文件中,无需解压,PHP 就可以进行访问并执行内部语句。
默认开启版本 PHP Version >= 5.3
Phar 文件结构
- 在说文件结构之前,我们可以先通过这个脚本生成一个 .phar 文件
ProducePhar.php
Phar 文件结构大致可分为四个部分
下面细说一些
stub
Stub 是 Phar 的文件标识,也可以理解为它就是 Phar 的文件头,这个 Stub 其实就是一个简单的 PHP 文件,它的格式具有一定的要求,具体如下
这行代码的含义,也就是说前面的内容是不限制的,但在该 PHP 语句中,必须有__HALT_COMPILER(),没有这个,PHP 就无法识别出它是 Phar 文件。 这个其实就类似于图片文件头,比如 gif 文件没有 GIF89A 文件头就无法正确的解析图片,010 Editor 里面的 phar 文件头如图

img
manifest
a manifest describing the contents,用于存放文件的属性、权限等信息。 这里也是反序列化的攻击点,因为这里以序列化的形式存储了用户自定义的 Meta-data

img
在我们上面生成的 phar 文件中,manifest 的内容如图

img
contents
用于存放 Phar 文件的内容
Signature
[optional] a signature for verifying Phar integrity (phar file format only),签名(可选参数),位于文件末尾,具体格式如下

img
从官方文档中不难看出,签证尾部的 01 代表 md5 加密,02 代表 sha1 加密,04 代表 sha256 加密,08 代表 sha512 加密

img
当我们修改文件的内容时,签名就会变得无效,这个时候需要更换一个新的签名更换签名的脚本
0x02 Phar 反序列化漏洞
漏洞成因
Phar 反序列化之所以存在,是因为 Phar 文件中的 manifest 字段存储了序列化的数据,这其实就是用户的 mete-data,PHP 使用 phar_parse_metedata() 函数解析 meta 数据时,会调用 php_var_unserialize() 函数进行反序列化。具体解析代码如下
php-src/ext/phar/phar.c

img
那么该如何触发反序列化呢,一般是配合 Phar 伪协议,伪协议使用较多的是一些文件操作函数,只有这些函数能进行反序列化操作,单纯的 phar:// 的伪协议并不能触发反序列化,如 fopen()、copy()、file_exists() 等,具体如下图

img
通过两个小 demo 来证明一下 file_get_contents() 可用:

img
成功触发,同样可以试一试其他的函数

img
这里会打印出的数据有之前在 test.txt 中写入的内容 空格,以及该打印出的 $this->name 的内容 —— drunkbaby
所以此处我们可以用一种别样的方式来触发反序列化,回想一下之前 PHP 反序列化的时候,是需要一个 unserialize() 反序列化的入口类的,但是在 Phar 反序列化当中,这一过程更为隐蔽。
接下来我们简单总结一下利用条件
利用条件
1)需要入口,也就是上面能够对 phar 文件进行反序列化的地方。
2)存在可利用的魔术方法,用魔术方法作为跳板,这其实也就是 POP 链的思想。
3)文件操作函数的参数可控,且:、/、phar等特殊字符没有被过滤。
简单 Demo
VulDemo1.php
这道 Demo 就是完美满足我们 phar 反序列化攻击的需求,首先存在入口函数 —— file_exists(),其次存在能够利用的魔术方法,魔术方法这里其实写了一个命令执行。并且毫无过滤。
所以我们直接构造恶意的 phar 文件,EXP 如下
复制
正常情况下应该是会给我们提供文件上传的功能点,这里我没有写,但是可以直接利用,payload 为
复制

img
0x03 Phar 反序列化 Bypass 的攻防二相性
对 Phar 内文件检测白名单
我们利用Phar反序列化的第一步就是需要上传Phar文件到服务器,而如果服务端存在防护,比如这种
这里的 bypass 比较简单,核心语句是这个
这和上面例题所说的 exp 是一样的
绕过 Phar 等关键字检测
Phar反序列化中,我们一般思路是上传Phar文件后,通过给参数赋值为Phar://xxx来实现反序列化,而一些防护可能会采取禁止参数开头为Phar等关键字的方式来防止Phar反序列化,示例代码如下
我们的办法是使用各种协议来进行绕过,具体如下
绕过 __HALT_COMPILER 检测
我们在前文初识Phar时就提到过,PHP 通过 __HALT_COMPILER来识别 Phar 文件,那么出于安全考虑,即为了防止 Phar 反序列化的出现,可能就会对这个进行过滤,示例代码如下
这里的话绕过思路有两个 1、将 Phar 文件的内容写到压缩包注释中,压缩为 zip 文件,示例代码如下
2、将生成的Phar文件进行gzip压缩,压缩命令如下
压缩后同样也可以进行反序列化
0x04 实战例题
[CISCN2019 华北赛区 Day1 Web1]Dropbox
- 首先通过正常的登录注册业务进到正常的逻辑当中去,发现有个文件上传的业务点。
- 作者:qetx
- 链接:http://qetx.top/article/6a9ba8b4-2790-4a44-8d0b-4547061cd02a
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。








