原生Java序列化
被序列化的物件必須繼承Serializble
Person.java
package com.superman; ? import java.io.Serializable; ? public class Person implements Serializable { private String name; private int age; ? @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + '}'; } ? public String getName() { return name; } ? public void setName(String name) { this.name = name; } ? public int getAge() { return age; } ? public void setAge(int age) { this.age = age; } ? public Person(String name, int age) { this.name = name; this.age = age; } }
序列化程式 URLCC.java
package com.superman; ? import java.io.Serializable; ? public class Person implements Serializable { private String name; private int age; ? @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + '}'; } ? public String getName() { return name; } ? public void setName(String name) { this.name = name; } ? public int getAge() { return age; } ? public void setAge(int age) { this.age = age; } ? public Person(String name, int age) { this.name = name; this.age = age; } }
反序列化程式 UnserializeTest.java
package com.superman; ? import java.io.*; ? public class UnserializeTest { public static Object unserialize(String Filename) throws IOException, ClassNotFoundException { ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(Filename)); Object object = objectInputStream.readObject(); return object; } public static void main(String[] args) throws IOException, ClassNotFoundException { Person person = (Person) unserialize("C://ser.txt"); System.out.println(person); } }
?
當被序列化物件里面重寫了readObject方法,反序列化時重寫的readObject中代碼會自動執行,
如將上面Person類添加一個readObject方法
Person.java
package com.superman; ? import java.io.*; ? public class UnserializeTest { public static Object unserialize(String Filename) throws IOException, ClassNotFoundException { ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(Filename)); Object object = objectInputStream.readObject(); return object; } public static void main(String[] args) throws IOException, ClassNotFoundException { Person person = (Person) unserialize("C://ser.txt"); System.out.println(person); } }
反序列化漏洞條件
共同條件繼承Serializable
入口類 source(重寫readobject方法,呼叫常見函式,引數型別寬泛,最好jdk自帶)
呼叫鏈 gadget chain 相同名稱,相同型別
執行類sink (rce ssrf寫檔案等)
URLDNS鏈就是利用了hashCode方法,具體分析如下,
尋找入口類
Map介面引數型別寬泛,其實作類HashMap()繼承Serializable并重寫了readObject方法,readObject里面呼叫了常見的函式,一般都是使用該類為入口類


for回圈遍歷mapping,并將鍵進行hash計算確保鍵的唯一性,走進hash方法,當key不為null時進行hashCode計算,而hashCode方法是一個常用方法,

這樣我們就找到了一個入口類hashMap
首先URL類也繼承了Serializable

并且與HashMap一樣實作了hashCode方法

嘗試寫下序列化方法
URLCC.java
package com.superman; ? import java.io.*; ? public class UnserializeTest { public static Object unserialize(String Filename) throws IOException, ClassNotFoundException { ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(Filename)); Object object = objectInputStream.readObject(); return object; } public static void main(String[] args) throws IOException, ClassNotFoundException { Person person = (Person) unserialize("C://ser.txt"); System.out.println(person); } }
?
當我們去序列化的時候發現dnslog平臺會接收到請求,追其原因是當hash.put時會觸發key.hashCode(),而這個key在代碼中是URL類物件,

URL的hashCode方法,當hashCode等于-1時便走不進希望的handler.hashCode方法,實作getHostAddress方法去請求dns,其中hashCode初始化賦值-1,所以需要用反射修改其屬性值

handler.hashCode代碼

修改代碼邏輯

URLCC.java
package com.superman; ? import java.io.*; ? public class UnserializeTest { public static Object unserialize(String Filename) throws IOException, ClassNotFoundException { ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(Filename)); Object object = objectInputStream.readObject(); return object; } public static void main(String[] args) throws IOException, ClassNotFoundException { Person person = (Person) unserialize("C://ser.txt"); System.out.println(person); } }
UnserializeTest.java
package com.superman; ? import java.io.*; ? public class UnserializeTest { public static Object unserialize(String Filename) throws IOException, ClassNotFoundException { ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(Filename)); Object object = objectInputStream.readObject(); return object; } public static void main(String[] args) throws IOException, ClassNotFoundException { Person person = (Person) unserialize("C://ser.txt"); System.out.println(person); } }
?
總結下來這類反序列化利用就是反序列化后呼叫HashMap的重寫的readobject,里面繼續呼叫到key.hashCode等常用方法,只要找同樣為Object型別有hashCode方法的類即可,URLDNS鏈并不能存在實際危害,只是用來探測是否能反序列化利用的工具鏈,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/421641.html
標籤:訊息安全
上一篇:Ubuntu上的Mariadb我為CURRENT_USER使用的用戶是root@%而不是root@localhost

