fix: SpringBoot4 WebFlux Base64Utils not found

This commit is contained in:
ReaJason
2026-08-25 22:08:36 +08:00
parent f28290f529
commit d240b37124
36 changed files with 1589 additions and 10 deletions
+8
View File
@@ -0,0 +1,8 @@
FROM eclipse-temurin:17.0.17_10-jdk
WORKDIR /app
COPY build/libs/vul-springboot4-webflux.jar /app/app.jar
EXPOSE 8080
ENTRYPOINT java $JAVA_OPTS -jar app.jar
@@ -0,0 +1,15 @@
plugins {
id("java")
id("org.springframework.boot") version "4.0.8"
id("io.spring.dependency-management") version "1.1.7"
}
java {
toolchain {
languageVersion = JavaLanguageVersion.of(17)
}
}
dependencies {
implementation("org.springframework.boot:spring-boot-starter-webflux")
}
@@ -0,0 +1,14 @@
package com.reajason.javaweb.vul.springboot4;
public class ClassDefiner extends ClassLoader {
public ClassDefiner() {
}
public ClassDefiner(ClassLoader parent) {
super(parent);
}
public Class<?> defineClass(byte[] code) {
return defineClass(null, code, 0, code.length);
}
}
@@ -0,0 +1,13 @@
package com.reajason.javaweb.vul.springboot4;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class VulSpringboot4Application {
public static void main(String[] args) {
SpringApplication.run(VulSpringboot4Application.class, args);
}
}
@@ -0,0 +1,35 @@
package com.reajason.javaweb.vul.springboot4.controller;
import com.reajason.javaweb.vul.springboot4.ClassDefiner;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import java.util.Base64;
/**
* @author ReaJason
* @since 2024/12/22
*/
@RestController
@RequestMapping("/b64")
public class Base64ClassLoaderController {
@PostMapping
public Mono<String> handleFormSubmission(ServerWebExchange exchange) {
return exchange.getFormData()
.flatMap(formData -> {
String data = formData.getFirst("data");
byte[] bytes = Base64.getDecoder().decode(data);
Object o = null;
try {
o = new ClassDefiner(Thread.currentThread().getContextClassLoader()).defineClass(bytes).newInstance();
} catch (Exception e) {
throw new RuntimeException(e);
}
return Mono.just(o.toString());
});
}
}
@@ -0,0 +1,123 @@
package com.reajason.javaweb.vul.springboot4.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.zip.GZIPInputStream;
/**
* @author ReaJason
* @since 2024/12/22
*/
@RestController
public class IndexController {
@RequestMapping("/test")
public String test() throws ClassNotFoundException, InvocationTargetException, NoSuchMethodException, IllegalAccessException {
return "";
}
@SuppressWarnings("all")
public static Object invokeMethod(Object obj, String methodName) throws
Exception {
return invokeMethod(obj, methodName, new Class[0], new Object[0]);
}
@SuppressWarnings("all")
public static Object invokeMethod(Object obj, String methodName, Class<?>[] paramClazz, Object[] param) throws
Exception {
Class<?> clazz = (obj instanceof Class) ? (Class<?>) obj : obj.getClass();
Method method = null;
while (clazz != null && method == null) {
try {
if (paramClazz == null) {
method = clazz.getDeclaredMethod(methodName);
} else {
method = clazz.getDeclaredMethod(methodName, paramClazz);
}
} catch (NoSuchMethodException e) {
clazz = clazz.getSuperclass();
}
}
if (method == null) {
throw new NoSuchMethodException("Method not found: " + methodName);
}
method.setAccessible(true);
return method.invoke(obj instanceof Class ? null : obj, param);
}
@SuppressWarnings("all")
public static byte[] decodeBase64(String base64Str) throws Exception {
Class<?> decoderClass;
try {
decoderClass = Class.forName("java.util.Base64");
Object decoder = decoderClass.getMethod("getDecoder").invoke(null);
return (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, base64Str);
} catch (Exception ignored) {
decoderClass = Class.forName("sun.misc.BASE64Decoder");
return (byte[]) decoderClass.getMethod("decodeBuffer", String.class).invoke(decoderClass.newInstance(), base64Str);
}
}
@SuppressWarnings("all")
public static byte[] gzipDecompress(byte[] compressedData) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
GZIPInputStream gzipInputStream = null;
try {
gzipInputStream = new GZIPInputStream(new ByteArrayInputStream(compressedData));
byte[] buffer = new byte[4096];
int n;
while ((n = gzipInputStream.read(buffer)) > 0) {
out.write(buffer, 0, n);
}
} finally {
if (gzipInputStream != null) {
try {
gzipInputStream.close();
} catch (IOException ignored) {
}
}
out.close();
}
return out.toByteArray();
}
@SuppressWarnings("all")
public static Field getField(Object obj, String name) throws NoSuchFieldException, IllegalAccessException {
for (Class<?> clazz = obj.getClass();
clazz != Object.class;
clazz = clazz.getSuperclass()) {
try {
return clazz.getDeclaredField(name);
} catch (NoSuchFieldException ignored) {
}
}
throw new NoSuchFieldException(name);
}
@SuppressWarnings("all")
public static Object getFieldValue(Object obj, String name) throws NoSuchFieldException, IllegalAccessException {
try {
Field field = getField(obj, name);
field.setAccessible(true);
return field.get(obj);
} catch (NoSuchFieldException ignored) {
}
return null;
}
@GetMapping("/")
public String index() {
return "hello";
}
}
@@ -0,0 +1 @@
spring.application.name=vul-springboot4