java反序列化漏洞简单学习

    技术2022-07-10  153

    知识点

    反序列化并不只存在于php,也存在各种语言中,如java、python等。 在学习java反序列化之前,我们需要知道一个基础知识:重写。

    重写

    重写,顾名思义就是重新改写该方法,从而达到想要的结果。需要注意的是:

    只有拥有继承关系时才能重写,也就是说,只能重写父类的同名方法。方法重写时, 方法名与形参列表必须一致。方法重写时,子类的权限修饰符必须要大于或者等于父类的权限修饰符。方法重写时,子类的返回值类型必须要小于或者 等于父类的返回值类型。方法重写时, 子类抛出的异常类型要小于或者等于父类抛出的异常类型。 Exception(最坏) RuntimeException(小坏) (顺带提一嘴重载,重载就是一个类里的两个或以上同名方法就是方法重载,两个函数的参数类型或者参数数目必须不一样,但函数名一致)

    代码准备

    正常序列化

    package com.sertest; import java.io.*; import java.io.Serializable; class SerObj implements Serializable//实现Serializable接口,使其可以被序列化 { public String name; public int time; } public class ser{ public static void main(String args[]) throws Exception{ // 实例化对象 SerObj serObj = new SerObj(); serObj.name = "serobj"; serObj.time = 10; // 以下就是序列化操作 // 打开object.ser文件 FileOutputStream fos = new FileOutputStream("object.ser"); ObjectOutputStream oos = new ObjectOutputStream(fos); // 使用writeObject()方法将serObj对象写到object.ser文件 oos.writeObject(serObj); oos.close(); fos.close(); } }

    正常反序列化

    package com.sertest; import java.io.*; public class Unser { public static void main(String args[]) throws Exception { FileInputStream fis = new FileInputStream("object.ser"); ObjectInputStream ois = new ObjectInputStream(fis); SerObj deSerobj = (SerObj) ois.readObject(); System.out.println(deSerobj.name); ois.close(); fis.close(); } }

    此时的结果时正常的。

    重写readobject方法后的恶意代码

    package com.sertest; import java.io.*; class Evil implements Serializable { public String name; public int time; private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); Runtime.getRuntime().exec("calc.exe"); } } public class hack_test { public static void main(String args[])throws Exception { Evil h2 = new Evil(); h2.name = "serobj"; h2.time = 10; FileOutputStream fos = new FileOutputStream("hack.ser"); ObjectOutputStream os = new ObjectOutputStream(fos); os.writeObject(h2); os.close(); } }

    反序列化代码:

    package com.sertest; import java.io.*; public class Unser { public static void main(String args[]) throws Exception { FileInputStream fis = new FileInputStream("hack.ser"); ObjectInputStream ois = new ObjectInputStream(fis); Evil deSerobj = (Evil) ois.readObject();//这里的类在反序列化的时候需要改变为包含恶意代码的类的名称,这样改是为了看得更明白 System.out.println(deSerobj.name); ois.close(); fis.close(); } }

    此时在反序列化时,由于恶意代码重写了readObject,所以在调用时调用的是已经被重写的readObject方法,执行了恶意代码。

    本来想试行一下把这两个打包成jar文件包,然后一个用来序列化数据一个用来反序列化数据,奈何java编程水平有限,只能做到这个地步。实际上生成恶意序列化数据的时候肯定要使用同一个类名和变量名,不然会因类名不同而报错,那就不能成功了。 以后有时间的话看能不能写一个简单的链出来,再了解一下JAVA的反射机制,这样能对相关的利用就能有一定程度的理解了。 参考文章: https://www.cnblogs.com/Fluorescence-tjy/p/11222052.html

    Processed: 0.010, SQL: 9