文章目录
- 一、Java序列化和反序列化
- 1、序列化和反序列化的含义和用途
- 序列化主要使用场景
- 反序列化漏洞出现的原因
- 下一期
一、Java序列化和反序列化
1、序列化和反序列化的含义和用途
Java对象(存在于内存)———序列化——>>字符串/二进制流(存在于磁盘、网络)
Java对象(存在于内存)<<———反序列化——字符串/二进制流(存在于磁盘、网络)
这样做就是为了方便存储和传输,实现对象的持久化,方便协议解释
序列化主要使用场景
1、持久化内存数据
2、网络传输对象
3、远程方法调用(RMI)
序列化
java.io.ObjectOutputStream.writeObject()
反序列化
java.io.ObjectInputStream.readObject()
反序列化漏洞出现的原因
readObject()是可以进行重写的,如果我们重写了这个类,那么在代码中就不会去调用原始的readObject(),而是调用我们重写的readObject(),如果重写的readObject()中执行了一些敏感的方法,再加上一些参数可被控制就会造成漏洞
验证POC,确定一个程序是否有漏洞的操作,会打开一个计算器
public class UnsafeTest{}public static void main(String args[]) throws Exception{UnsafeClass Unsafe = new UnsafeClass();Unsafe.name = "hacked by yy";//序列化FileOutputStream fos = new FileOutputStream("D: /yy.java");ObjectOutputStream os = new ObjectOutputStream(fos);os.writeObject(Unsafe);os.close();/从反序列化FileInputStream fis = new FileInputStream("D: /yy.class");ObjectInputStream ois = new ObjectInputStream(fis);UnsafeClass objectFromDisk = (UnsafeClass)ois.readObject();System.out. println(objectFromDisk.name);ois.close();}}
如果我们运行上面的代码,进行序列化和反序列化时,计算器被打开,则证明漏洞存在(用来序列化的类是重写后的,加了Runtime)
如果有一个接口或程序,允许接受一个序列化字符串,然后去将其反序列化,那么我们可以自己构建一个恶意类,里面包含重写的readObject()方法,进行序列化,交给接口或程序去反序列化,就会因为传输来的类中有重写的readObject()方法,在反序列化时,会使用重写的方法,从而执行我们包含在其中的命令
实际上并没有这么简单,因为要知道服务器上有没有这个类(自己写的类不一定在别人的项目中存在),所以,我们需要去寻找在java中有没有一个现存的类,要求 重写了readObject()方法,然后还要有 存在参数能够控制,让我们的恶意代码让他去帮我执行的这样的类
1、重写类的readObject()方法
2、反序列过程中会执行自定义的readObject()
下一期
Apache Commons Collections 反序列化漏洞