前言
我们在之前学习的反序列化漏洞 无一不是利用了unserialize()这个函数 但是我们没有去考虑 假设此时的题目并没有给我们这个函数 我们还能否实现反序列化呢
其实是可以的 在2018年的BlackHat 大会上 Sam Thomas研究员分享了一个方法 可以在文件系统函数的参数可控的情况下 配合phar协议 不依赖unserialize函数进行反序列化
phar文件
在此之前我们需要先学习一下phar文件 这是php中的一种打包格式 可以粗略的将其理解为一个将多个文件打包在一块的整合包
它主要有四个部分组成
1 | 1. stub部分:这是phar文件的标识 可以理解为一个标志 格式为xxx<?php xxx; __HALT_COMPILER();?> 最关键的是后面的这个__HALT_COMPILER();?>结尾 前面的内容没有限制 |
原理分析
那么假设现在的靶机情况是这样的 :
存在一个危险的类 其中有destruct等魔术方法 会在对象创建销毁 反序列化发生等关键时候触发代码执行
1 | <?php |
此时我们就可以在本地仿照这个类编写一个phar文件
1 | <?php |
经过上述操作 test.phar 文件创建完成
(注意 要将php.ini中的phar.readonly选项设置为Off,否则无法生成phar文件)
此时我们只需要把这个phar文件上传到目标靶机
然后利用靶机php文件之中的
1 | $filename = $_GET['filename']; |
这一部分 这一部分调用了文件操作函数 这些函数操作phar文件的时候会触发元数据的反序列化
此时被反序列化之后 触发魔术方法 执行恶意的诸如命令 攻击成功
在先知社区的文章之中提供了这样一张图片 展示了收到这个漏洞高攻击影响的函数有以下几种
当这些函数直接使用我们传入的路径为参数的时候 就i有Phar反序列化的攻击之处
但是很多时候 文件上传的入口是不运行我们直接传入phar文件的 更大概率是会存在黑名单或者白名单 此时应该怎么办呢?
这时候我们可以使用phar://伪协议 这个
phar伪协议
这个协议是php解压缩包的一个函数 不管后缀是什么 都会将路径下的文件当作压缩包来解压
语法:
1 | phar://压缩包路径/压缩包内部文件名 |
利用phar://伪协议不管扫描后缀都会当作压缩包来解压的特性 我们可以修改test.phar的后缀为可以通过后缀名检测的任意后缀 之后继续包含就行
例题演示
[HNCTF 2022 WEEK3]ez_phar
我们点进来看到这是一个反序列化题目 但是没有unserialize()
同时发现这里面有文件操作函数file_exists()很明显这是一个phar反序列化题目 对于这种题目 还需要一个文件上传页面
使用dirsearch扫一下 找到了upload.php
ok那么现在万事俱备了 开始编写phar文件
1 | <?php |
此时这个phar文件就会生成在你写以上代码的文件的相同目录之下
我们将其上传一下看看
发现过滤了后缀名 那么就将phar文件后缀改成.png之后使用phar伪协议上传
上传成功 此时我们来到第一个页面 使用phar伪协议
可以看到反序列化成功 ls被成功执行 接下来就是修改RCE内容 得到flag
小解
phar反序列化主要利用的知识是数据(Metadata)是以序列化(serialize)格式存储的 当通过phar://协议访问Phar文件时 PHP会自动反序列化(unserialize)元数据 无论是否实际使用这些元数据
主要利用有几个前提:
- php.ini中的phar.readonly选项设置为Off
- 存在文件操作函数
- 存在文件上传页面
参考文章:
Phar与Stream Wrapper造成PHP RCE的深入挖掘-先知社区
Phar与Stream Wrapper造成PHP RCE的深入挖掘-先知社区