【反序列化漏洞】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





目录
相关文章
|
7月前
|
JSON 网络协议 安全
【Java】(10)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
387 3
|
7月前
|
JSON 网络协议 安全
【Java基础】(1)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
362 1
|
8月前
|
XML JSON 编解码
从JSON到Protobuf,深入序列化方案的选型与原理
序列化是数据跨边界传输的“翻译官”,将结构化数据转为二进制流。JSON可读性强但冗余大,Protobuf高效紧凑、性能优越,成主流选择。不同场景需权衡标准化与定制优化,选最合适方案。
537 3
|
11月前
|
存储 Java 编译器
说一说关于序列化/反序列化中的细节问题
我是小假 期待与你的下一次相遇 ~
218 1
|
11月前
|
JSON Java 数据库连接
|
12月前
|
存储 安全 IDE
说一说序列化与反序列化中存在的问题
本文详细解析了Java中的序列化机制,包括序列化的概念、实现方式及应用场景。通过Student类的实例演示了对象的序列化与反序列化过程,并分析了`Serializable`接口的作用以及`serialVersionUID`的重要意义。此外,文章还探讨了如何通过自定义`readObject()`方法增强序列化的安全性,以及解决可序列化单例模式中可能产生的多实例问题。最后提供了代码示例和运行结果,帮助读者深入理解序列化的原理与实践技巧。
298 4
|
12月前
|
JSON JavaScript 前端开发
Go语言JSON 序列化与反序列化 -《Go语言实战指南》
本文介绍了 Go 语言中使用 `encoding/json` 包实现 JSON 与数据结构之间的转换。内容涵盖序列化(`Marshal`)和反序列化(`Unmarshal`),包括基本示例、结构体字段标签的使用、控制字段行为的标签(如 `omitempty` 和 `-`)、处理 `map` 和切片、嵌套结构体序列化、反序列化未知结构(使用 `map[string]interface{}`)以及 JSON 数组的解析。最后通过表格总结了序列化与反序列化的方法及类型要求,帮助开发者快速掌握 JSON 数据处理技巧。
|
存储 安全 Java
Java编程中的对象序列化与反序列化
【10月更文挑战第22天】在Java的世界里,对象序列化和反序列化是数据持久化和网络传输的关键技术。本文将带你了解如何在Java中实现对象的序列化与反序列化,并探讨其背后的原理。通过实际代码示例,我们将一步步展示如何将复杂数据结构转换为字节流,以及如何将这些字节流还原为Java对象。文章还将讨论在使用序列化时应注意的安全性问题,以确保你的应用程序既高效又安全。
|
JSON 数据格式 索引
Python中序列化/反序列化JSON格式的数据
【11月更文挑战第4天】本文介绍了 Python 中使用 `json` 模块进行序列化和反序列化的操作。序列化是指将 Python 对象(如字典、列表)转换为 JSON 字符串,主要使用 `json.dumps` 方法。示例包括基本的字典和列表序列化,以及自定义类的序列化。反序列化则是将 JSON 字符串转换回 Python 对象,使用 `json.loads` 方法。文中还提供了具体的代码示例,展示了如何处理不同类型的 Python 对象。
802 1
|
存储 安全 Java
Java编程中的对象序列化与反序列化
【10月更文挑战第3天】在Java编程的世界里,对象序列化与反序列化是实现数据持久化和网络传输的关键技术。本文将深入探讨Java序列化的原理、应用场景以及如何通过代码示例实现对象的序列化与反序列化过程。从基础概念到实践操作,我们将一步步揭示这一技术的魅力所在。