java反序列化
Contents
当数据在网络中传输时,我们需要把我们代码中的数据固定成某种特定的数据格式去传输,目前使用最为广泛的 两种格式是: json和xml. 但是这两种格式默认只支持了基本的数据类型,如数字,字符串等。
当我们想序列一些自定义对象时,它们就无能为力了。 因此各种语言,各个框架都自定义了自己的一套规则自定义对象。
基本使用
还是直接先看代码吧
我们先定义一个类
|
|
可以看到这个Person类实现了java.io.Serializable
接口,这也是一个类序列化的必要条件。
序列化
先实例化Person类
|
|
将person类序列化并保存
|
|
这里用到ObjectOutputStream
的writeObject
方法将其序列化
用winhex打开person.ser
可以看到开头两位是AC ED, 这也是java反序列化的魔术字符,有时我们在ctf看到这时,就知道这跟java反序列化逃不了干系了。
反序列化
有出就有进。 反序列化用的是ObjectInputStream
的readObject
方法
|
|
运行后打印出了我们在上面设置的name: wwww
writeObject和readObject
有时候,我们会想在序列化和反序列化时做一些事情,例如在序列化时存个链接,在反序列时再把这请求这链接拿到结果等等
java Serializable接口贴心的为我们准备了两个方法实现这个功能:
- writeObject 序列化时自动调用
- readObject 反序列化时自动调用 直接看示例
|
|
那么漏洞呢?
漏洞
上面说了java会在反序列化时自动调用类的readObject方法,那么如果开发人员在readObject上写上了恶意代码, 如:
|
|
那么在反序列化时就会自动执行命令了。
什么? 不会有这样的开发人员?
确实不大可能会有这么缺心眼的开发者。 因此我们往往需要通过将java内自带的库或者比较通用的库,将它们的readObject串联起来, 从而达成我们想要的目的。
更详细的ObjectInputStream.readObject之后发生了什么? 可以看这篇文章:http://www.lmxspace.com/2019/11/20/Java%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E8%BF%87%E7%A8%8B%E6%B7%B1%E7%A9%B6/
下一篇文章会用一个简短的调用链来了解什么是"gadget".