Web安全之Java反序列化
JAVA反序列化
漏洞原理:
序列化可以将对象变成可以传输的字符串,方便数据保存传输,反序列化就是将字符串还原成对象。如果web应用没有对用户输入的反序列化字符串进行检测,导致反序列化过程可以被控制,就会造成代码执行,getshell等一系列不可控的后果。
JAVA中的api实现
位置:
java.io.ObjectOutputStream
java.io.ObjectInputStream
序列化过程:
ObjectOutputStream类中的writeObject()方法:
对参数指定的obj对象进行序列化,把字节序列写到一个目标输出流中,按java的标准约定是给文件一个.ser扩展名
ObjectInputStreaml类中的readObject()方法:
从一个源输入流中读取字节序列,再把它们反序列化为一个对象,并将其返回.
java序列化标志:
rO0AB开头,为java序列化base64加密后的数据.
aced开头,java序列化后的16进制数据.
简单实例Demo:
Main.java: package serializeDemo; import java.io.*; import java.io.Serializable; public class Main { public static void main(String[] args) throws Exception{ serializePerson(); //Person person=deserializePerson(); // System.out.print(person); } private static void serializePerson() throws IOException{ Person person = new Person("name:mrob0t",18); ObjectOutputStream oos = new ObjectOutputStream( new FileOutputStream(new File("D:/person.txt")) ); oos.writeObject(person); System.out.println("person序列化成功!"); oos.close(); } private static Person deserializePerson() throws Exception{ ObjectInputStream ois = new ObjectInputStream( new FileInputStream(new File("D:/person.txt")) ); Person person=(Person)ois.readObject(); System.out.println("person对象反序列化成功"); return person; } } Person.java: package serializeDemo; import java.io.Serializable; public class Person implements Serializable { private static final long serialVersionUID = 3604972003323896788L; public Person(String n, int a){ String name; int age; name=n; age=a; } }
漏洞检测与利用:
黑盒检测:
a. 从流量中发现序列化的痕迹,关键字:ac ed 00 05,rO0AB b. Java RMI 的传输 100% 基于反序列化,Java RMI 的默认端口是1099端口
白盒代码审计:
关注以下函数:
ObjectInputStream.readObject
ObjectInputStream.readUnshared
XMLDecoder.readObject
Yaml.load
XStream.fromXML
ObjectMapper.readValue
JSON.parseObject
利用:
payload生成器-ysoserial
自定义工具或脚本
原文地址:https://www.cnblogs.com/mrob0t/p/14787500.html