java反序列化漏洞原理
1.首先是序列化的过程
序列化: ObjectOutputStream类 --> writeObject()
将对象进行序列化,把字节序列写到一个目标输出流中.ser
2.反序列化
反序列化: ObjectInputStream类 --> readObject()
从一个源输入流中读取字节序列,再把它们反序列化为一个对象
如果序列化字节序列内容可控,那么即可执行恶意类
参考代码:
这段代码中exec本来是去序列化一个String类型对象,并存储序列化流文件,之后读取序列化流文件展示。
如果对象改变,变成一个恶意类evil,则反序列化,还原对象时则会还原成恶意类,而执行构造函数中的恶意代码
import java.io.*; public class main { public static void main(String[] args) throws IOException, ClassNotFoundException { new main().exec(); } public void exec() throws IOException, ClassNotFoundException { //String s="hello"; evil s=new evil(); byte[] ObjectBytes=serialize(s); File file = new File("test.ser"); FileOutputStream fos = new FileOutputStream(file); fos.write(ObjectBytes); File file2 = new File("test.ser"); FileInputStream fis = new FileInputStream(file); byte[] byteArray = new byte[(int) file.length()]; fis.read(byteArray); String s2=(String)deserialize(byteArray); System.out.println(s2); } private byte[] serialize(final Object obj) throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); ObjectOutputStream objOut = new ObjectOutputStream(out); objOut.writeObject(obj); return out.toByteArray(); } private Object deserialize(final byte[] serialized) throws IOException, ClassNotFoundException { ByteArrayInputStream in = new ByteArrayInputStream(serialized); ObjectInputStream objIn = new ObjectInputStream(in); return objIn.readObject(); } }
import java.io.IOException; public class evil { public evil() throws IOException { Runtime rt = Runtime.getRuntime(); rt.exec("calc"); } }