安全矩阵

 找回密码
 立即注册
搜索
查看: 990|回复: 0

java反序列化之原生

[复制链接]

260

主题

275

帖子

1065

积分

金牌会员

Rank: 6Rank: 6

积分
1065
发表于 2022-9-15 07:50:58 | 显示全部楼层 |阅读模式
java反序列化之原生
原文链接:java反序列化之原生
原创 xinyuan 合天网安实验室 2022-09-14 17:28 发表于湖南


早就想学java安全,但一直无从下手,今天下定决心好好学习,当然以下内容可能会有些许错误,小白的烦恼。

序列化与反序列化
Java序列化是指把Java对象转换为字节序列的过程;而Java反序列化是指把字节序列恢复为Java对象的过程。
序列化分为两大部分:序列化和反序列化。序列化是这个过程的第一部分,将数据分解成字节流,以便存储在文件中或在网络上传输。反序列化就是打开字节流并重构对象。对象序列化不仅要将基本数据类型转换成字节表示,有时还要恢复数据。恢复数据要求有恢复数据的对象实例。

为什么需要序列化与反序列化
我们知道,当两个进程进行远程通信时,可以相互发送各种类型的数据,包括文本、图片、音频、视频等, 而这些数据都会以二进制序列的形式在网络上传送。那么当两个Java进程进行通信时,能否实现进程间的对象传送呢?答案是可以的。如何做到呢?这就需要Java序列化与反序列化了。换句话说,一方面,发送方需要把这个Java对象转换为字节序列,然后在网络上传送;另一方面,接收方需要从字节序列中恢复出Java对象。
当我们明晰了为什么需要Java序列化和反序列化后,我们很自然地会想Java序列化的好处。其好处一是实现了数据的持久化,通过序列化可以把数据永久地保存到硬盘上(通常存放在文件里),二是,利用序列化实现远程通信,即在网络上传送对象的字节序列。
① 想把内存中的对象保存到一个文件中或者数据库中时候;② 想用套接字在网络上传送对象的时候;③ 想通过RMI传输对象的时候

为什么会产生安全问题?
只要服务端反序列化数据,客户端传递类的readObject中代码会自动执行,给予攻击者在服务器上运行代码的能力。

几种常见的序列化和反序列化协议
XML&SOAP
JSON
Protobuf

理解
类比快递、打包和拆包
有些快递打包和拆包时有独特需求、比如易碎朝上,类比重写writeObject和readObject

实例
Java反序列化的操作,很多是需要开发者深入参与的,所以你会发现大量的库会实现readObject 、 writeObject 方法,这和PHP中__wakeup 、__sleep 很少使用是存在鲜明对比的。我在《Java安全漫谈 - 06.RMI篇(3)》的最后一部分,讲到了classAnnotations ,这次再来说说 objectAnnotation 。Java在序列化时一个对象,将会调用这个对象中的writeObject 方法,参数类型是 ObjectOutputStream ,开发者可以将任何内容写入这个stream中;反序列化时,会调用 readObject ,开发者也可以从中读取出前面写入的内容,并进行处理。

创建一个person类
  1. import java.io.IOException;
  2. import java.io.ObjectInputStream;
  3. import java.io.Serializable;
  4. publicclass Person implementsSerializable {
  5.     privateString name;
  6.     privateint age;
  7.     publicPerson(){}
  8.     publicPerson(String name,int age){
  9.         this.name=name;
  10.         this.age=age;
  11.     }
  12. @Override
  13.     publicString toString() {
  14.         return"Person{"+
  15.         "name='" + name + "\'" +
  16.                 ",'age=" + age +
  17.                 '}';
  18.     }
  19. }
复制代码

创建一个序列化类
  1. import java.io.FileOutputStream;
  2. import java.io.IOException;
  3. import java.io.ObjectOutputStream;
  4. public class SerializationTest {
  5.     public static void serialize(Object obj) throws IOException {
  6.         ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("ser.bin"));
  7. oos.writeObject(obj);
  8.     }
  9.     public static void main(String[] args) throws Exception{
  10.         Person person=new Person("xinyuan",22);
  11.         serialize(person);
  12.         System.out.println(person);
  13.     }
  14. }
复制代码

创建一个反序列化类
  1. import java.io.FileInputStream;
  2. import java.io.IOException;
  3. import java.io.ObjectInputStream;
  4. public class UnserializationTest {
  5.     public static Object unserialize(String Filename) throws IOException, ClassNotFoundException {
  6. ObjectInputStream ois=new ObjectInputStream(new FileInputStream("ser.bin"));
  7. Object obj = ois.readObject();
  8.         return obj;
  9.     }
  10.     public static void main(String[] args) throws Exception{
  11.         Person person=(Person) unserialize("ser.bin");
  12.         System.out.println(person);
  13.     }
  14. }
复制代码

可能的形式
1.入口类的readObject直接调用危险方法
编辑
在person类,重写readObject方法,序列化后,反序列化
编辑
2.入口类参数中包含可控类,该类有危险方法,readObject时调用。
3.入口类参数包含可控类,该类又调用其他有危险方法的类,readObject时调用
条件
共同条件 继承Serializable
入口类 source(重写readObject 参数类型宽泛 最好jdk自带) Map

调用链 gadget chain 相同名称,相同类型
执行类 sink(rce ssrf 写文件等等)
https://github.com/frohoff/ysoserial/






回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|安全矩阵

GMT+8, 2024-11-29 13:53 , Processed in 0.012468 second(s), 18 queries .

Powered by Discuz! X4.0

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表