跳转到帖子

游客您好,欢迎来到黑客世界论坛!您可以在这里进行注册。

赤队小组-代号1949(原CHT攻防小组)在这个瞬息万变的网络时代,我们保持初心,创造最好的社区来共同交流网络技术。您可以在论坛获取黑客攻防技巧与知识,您也可以加入我们的Telegram交流群 共同实时探讨交流。论坛禁止各种广告,请注册用户查看我们的使用与隐私策略,谢谢您的配合。小组成员可以获取论坛隐藏内容!

TheHackerWorld官方

关于 Java 序列化和反序列化的谈话

精选回复

发布于

前言

目前Java安全的普及可以说是红队的必知之道。我曾经陷入了学习Java安全的初衷——学习CC链——放弃——再次开始学习Java的安全恶性循环就像背单词,总是止步于放弃。最后,在看到高级scz的博客后,我下定了决心。

基本用途

不再介绍序列化和反序列化的概念,让我们直接看一下用户。

对于可序列化的类,它需要实现可序列化外部化接口,前者是一个空接口:

public interface Serializable {  
}

它仅用于标识此类可以序列化,后者继承前者。

Java 对象的序列化步骤:

  • 创建一个可以包装另一个类型的输出流java.io.ObjectOutputStream

  • writeObject通过其方法编写对象

carbon.png

反序列化 Java 对象的步骤:

  • 创建一个可以包装另一种类型的输入流java.io.ObjectInputStream

  • 读取对象通过对象的方法读取对象

carbon%2520%281%29.png

序列化数据格式

将序列化数据写入文件并观察:carbon%2520%282%29.png

您可以看到有一些可读的字符串,包括类名和一些成员变量名称和值。

使用该工具:序列化转储程序可以轻松还原序列化数据,例如原始流文件:

ter.png

对于十六进制数据:

term.png

完整输入:

co.png

与 Oracle 官方文档中的对象序列化流协议 [2] 部分相比,让我们讨论以下序列化数据的结构。

首先是幻数和协议版本。您可以在 ObjectStreamConstants接口中看到定义:

codei.png

后跟内容,即一个或多个内容,后者由反对者块数据组成。

对象里面的内容是序列化数据的核心,由以下任何内容组成:

  • 新对象:对象

  • 新类:种类

  • 新数组:数组

  • 新字符串:字符串

  • newEnum:枚举类型

  • newClassDesc:类定义

  • 上一页对象:对类型的引用

  • 空引用:空

  • 异常:异常

  • TC_RESET:重置引用 ID

请参阅新对象:

carbon%2520%289%29.png

我们使用上面的例子来比较,包含一个 newObject 的内容,TC_OBJECTafter classDesc,它包含类名和长度、serialVersionUID、属性名称和长度、父类和其他信息。在此之后是 newHandle,前者是序列化数据中当前结构的唯一 ID,后者是序列化 object.classdata[] 中的信息。

newClassDescand classDesc并不相同,从定义中可以看出:

carbon%2520%2810%29.png

classDescEquivalent to newClassDescthe 封装,它可以是 newClassDescbe 的空值或指向类定义的指针。

在这一点上,你可能想知道,我为什么要阅读这个无聊的文档?你为什么不开始谈论CC链?

需要了解有关序列化数据结构的详细信息有三个原因:

  • 帮助理解通过填充序列化数据中的垃圾字符来绕过 WAF 的原理

  • 帮助以后了解 JDK 8u20 本机反序列化漏洞

  • 也许您会遇到需要使用其他语言来执行 Java 反序列化漏洞的情况

属性的效果

在 PHP 中序列化时,变量的作用域会影响序列化的数据,那么在 Java 中是否有类似的情况呢?

将两个变量添加到 Personclass 中:

carbon%2520%2811%29.png

观察序列化数据后,发现这两个变量都不存在:

term.png

由 static 或 transient 关键字修改的变量不会出现在序列化数据中,这是出于一些敏感数据的考虑。

但是如果你尝试在反序列化后调用这两个变量,你可以看到地址正常输出,而密码为空:

jb.png

这是因为寻址一个静态变量,并且调用它在 JVM 中注册的值,而不是序列化后获得的值。

如果要序列化由瞬态关键字修改的变量,则需要使用 外部化接口:

cd.png

在这里,如果用于解析,将发生以下错误:test.rawSerializationDumper

2022-09-19_09-39.png

原因是实现 Externalizable 接口的类,其序列化是通过该方法写入流的 writeExternal,也必须通过相应的 readExternalMethod 进行解析,因此 SerializationDumper这样的序列化数据如果不提供原始类就无法解析。

对象流类分析

ObjectStreamClass 它可以用来分析JVM中加载的序列化类的序列化特征,包括字段描述信息和serialVersionUID等。

ObjectStreamClass有两种静态方法:

carbon%2520%286%29.png

lookup(Class<?>cl) ObjectStreamClass如果提供的类是可序列化的,则返回一个实例,否则为 null:

carbon%2520%287%29.png

carbon%2520%288%29.png

该方法将返回相应的实例,而不管提供的类是否可反序列化。lookup any(Class<?>cl)

获取ObjectStreamClass实例后,可以调用相应的方法来获取信息:

  • getDeclaredSUID:提取序列号

  • getSerialFields:提取所需的序列化字段,如果没有,则提取默认字段

关于 ObjectInputStream.resolveClass()

图片.png

解析类该方法接收一个ObjectStreamClass实例,获取其类名,然后使用反射返回此类的Class实例。实际上,允许在反序列化期间返回对象之前替换或解析对象。

此方法在 Apache Shiro 中被覆盖:

carbon%2520%285%29.png

这导致了 Shiro 反序列化漏洞的一些有趣情况,这将在后面的 Shiro 文章中详细讨论。

重写此方法也是防御反序列化漏洞的一种方法,例如 SerialKiller [3] 项目:

uuggf.png

黑名单或白名单防御是通过重写来执行的。ObjectInputStream.resolveClass()

readObjectNoData

反序列化过程中,如果序列化类的超类与反序列化类的超类不同,因为序列化时的类与反序列化时的版本不同,或者因为收到的序列化数据不完整,或者序列化数据有害,会影响初始化的对象字段值。

创建帐户或登录后发表意见

最近浏览 0

  • 没有会员查看此页面。