反序列化杂记

admin 2024年2月16日00:52:46评论13 views字数 2171阅读7分14秒阅读模式

概念

简而言之,序列化是把对象转化成字节码,反序列化则是将字节码恢复为对象。序列化需要使用到ObjcetOutputStream类的writeObeject函数,可以ObjectOutputStream可以理解成对象输出字节流,而writeObject函数可以理解成写入对象,要把对象写入到类里面然后输出成字节流。而反序列化则是需要使用ObjectInputStream类的readObject函数,ObjectInputStream可以理解成对象输入字节流,把字节流恢复成对象,本来反序列化就是在字节流里面提取对象,readObject函数字面意思就是读取对象,从字节流里面读取出对象,这些类和函数都可以这样去理解。

序列化的必要

当一个类实现了Serializable接口时,它的所有属性都会被默认序列化,即对象的状态会被保存和恢复。使用transient关键字修饰一个属性可以阻止其被序列化。被声明为transient的属性在序列化过程中会被忽略,不会被保存到输出流中。当对象被反序列化时,这些属性会被设置为默认值(例如,数值类型为0,引用类型为null)。

反序列化的形成

攻击者构造了一个恶意利用链并将其序列化成数据,然后传入到应用,应用接受数据之后传入到后台,后台对数据进行反序列化将数据构造成对象,在此过程中,会调用恶意利用链执行相应的命令。

反序列化的过程其实就是一个数据到对象的过程。在这个过程中,应用必须根据数据源去调用一些默认方法(比如构造函数和 Getter/Setter)。在反序列化过程中,序列化/反序列化库会读取序列化数据,并使用这些数据来实例化目标类。为了创建对象,通常会调用目标类的构造函数。构造函数负责初始化对象的状态,分配内存等操作。

接下来,库会根据序列化数据中的属性值调用目标类的 setter 方法。这些 setter 方法用于将属性值设置到对象中,以恢复对象的状态。在某些情况下,库可能还会调用目标类的 getter 方法,以获取对象的属性值。这可以在反序列化过程中进行一些验证、处理或其他操作。在反序列化过程中,还涉及到一些接口类或基类,如 Map、List 和 Object。应用程序需要根据数据源来判断选择哪个具体的接口实现类,并调用其默认方法。攻击者可以利用这一点来控制反序列化过程中应用程序调用的接口实现类的默认方法。通过对不同接口类的默认方法进行组合,攻击者可以操纵反序列化的调用过程,实现执行任意命令的功能。这种攻击方式被称为"漏洞链"(gadget chain)攻击,攻击者通过构造恶意的序列化数据,使其在反序列化过程中调用一系列的对象和方法,最终达到执行恶意代码的目的。

getter和setter方法的调用可以看https://mp.weixin.qq.com/s/XPbbgLcBmHE7dmHswY_S3Q

至于其他的map之类的可以参考一下https://su18.org/post/hessian/

反序列化触发点

除了常见的ObjectInputStream.readObject可以触发反序列化操作外,还有以下几种触发方式:

ObjectInputStream.readObject // Java标准库中的方法,用于将流转化为对象。
ObjectInputStream.readUnshared // readUnshared()方法读取的对象不允许后续的readObject()和readUnshared()调用引用这次调用反序列化得到的对象。这个方法可以用于创建独立的对象实例,而不是共享已经存在的对象。
XMLDecoder.readObject // Java中用于XML反序列化的方法之一。它可以将XML格式的数据转化为对象。
Yaml.load // 可以将YAML格式的字符串转化为对象。YAML是一种人类可读的数据序列化格式,常用于配置文件和数据交换。
XStream.fromXML //XStream库中的方法,用于将XML转化为Java对象。XStream是一个流行的Java对象与XML相互转化的库,它可以将Java对象序列化为XML格式,也可以将XML反序列化为Java对象。
ObjectMapper.readValue // Jackson库中的方法,用于将JSON数据转化为Java对象,readValue()方法可以将JSON字符串或流转化为Java对象。
JSON.parseObject //Fastjson库中的方法,用于将JSON数据转化为Java对象。
Gson.fromJson() //Google Gson库中的方法,用于将JSON数据转化为Java对象。
Jsonb.fromJson() //Java JSON Binding (JSON-B) API中的方法,用于将JSON数据转化为Java对象,JSON-B是Java EE的一部分。
MessagePack.unpack() //MessagePack库中的方法,用于将MessagePack格式的数据转化为Java对象。
Protobuf.parseFrom() //Google Protocol Buffers库中的方法,用于将Protocol Buffers格式的数据转化为Java对象。

原文始发于微信公众号(安全学习之路):反序列化杂记

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年2月16日00:52:46
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   反序列化杂记http://cn-sec.com/archives/2245808.html

发表评论

匿名网友 填写信息