feat: support spring response body writer

This commit is contained in:
ReaJason
2025-11-20 00:36:25 +08:00
parent fe86bc04c1
commit 44d087829d
8 changed files with 116 additions and 5 deletions
@@ -67,6 +67,8 @@ public class ResponseBodyGenerator extends ByteBuddyShellGenerator<ResponseBodyC
private Class<?> getWriterClass() {
switch (probeContentConfig.getServer()) {
case Server.SpringWebMvc:
return SpringWebMvcWriter.class;
case Server.Jetty:
return JettyWriter.class;
case Server.Tomcat:
@@ -0,0 +1,81 @@
package com.reajason.javaweb.probe.payload.response;
import java.io.PrintWriter;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/**
* @author ReaJason
* @since 2025/11/11
*/
public class SpringWebMvcWriter {
public SpringWebMvcWriter() {
try {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
Object requestAttributes = invokeMethod(classLoader.loadClass("org.springframework.web.context.request.RequestContextHolder"), "getRequestAttributes", null, null);
Object request = invokeMethod(requestAttributes, "getRequest", null, null);
Object response = invokeMethod(requestAttributes, "getResponse", null, null);
String data = getDataFromReq(request);
if (data != null && !data.isEmpty()) {
PrintWriter writer = (PrintWriter) invokeMethod(response, "getWriter", null, null);
try {
writer.write(run(data));
} catch (Throwable e) {
e.printStackTrace(writer);
}
writer.flush();
writer.close();
return;
}
} catch (Throwable e) {
e.printStackTrace();
}
}
private String getDataFromReq(Object request) throws Exception {
return null;
}
private String run(String data) throws Exception {
return null;
}
@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(obj.getClass() + " Method not found: " + methodName);
}
method.setAccessible(true);
return method.invoke(obj instanceof Class ? null : obj, param);
}
@SuppressWarnings("all")
public static Object getFieldValue(Object obj, String name) throws Exception {
Class<?> clazz = obj.getClass();
while (clazz != Object.class) {
try {
Field field = clazz.getDeclaredField(name);
field.setAccessible(true);
return field.get(obj);
} catch (NoSuchFieldException var5) {
clazz = clazz.getSuperclass();
}
}
throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name);
}
}
@@ -39,7 +39,7 @@ public class SpringBoot1ContainerTest {
void testJDK() {
String url = getUrlFromSpringBoot(container);
String data = VulTool.post(url + "/b64", DetectionTool.getJdkDetection());
assertEquals("JDK|1.8.0_342|52", data);
assertEquals("JDK|1.8.0_472|52", data);
}
@Test
@@ -64,6 +64,13 @@ public class SpringBoot1ContainerTest {
ProbeAssertion.responseCommandIsOk(url, Server.Tomcat, Opcodes.V1_6);
}
@Test
@SneakyThrows
void testCommandReqHeaderResponseBodySpring() {
String url = getUrlFromSpringBoot(container);
ProbeAssertion.responseCommandIsOk(url, Server.SpringWebMvc, Opcodes.V1_6);
}
@Test
@SneakyThrows
void testBytecodeReqParamResponseBody() {
@@ -40,7 +40,7 @@ public class SpringBoot2ContainerTest {
void testJDK() {
String url = getUrlFromSpringBoot(container);
String data = VulTool.post(url + "/b64", DetectionTool.getJdkDetection());
assertEquals("JRE|1.8.0_342|52", data);
assertEquals("JDK|1.8.0_472|52", data);
}
@Test
@@ -65,6 +65,13 @@ public class SpringBoot2ContainerTest {
ProbeAssertion.responseCommandIsOk(url, Server.Tomcat, Opcodes.V1_6);
}
@Test
@SneakyThrows
void testCommandReqHeaderResponseBodySpring() {
String url = getUrlFromSpringBoot(container);
ProbeAssertion.responseCommandIsOk(url, Server.SpringWebMvc, Opcodes.V1_6);
}
@Test
@SneakyThrows
void testBytecodeReqParamResponseBody() {
@@ -40,7 +40,7 @@ public class SpringBoot2JettyContainerTest {
void testJDK() {
String url = getUrlFromSpringBoot(container);
String data = VulTool.post(url + "/b64", DetectionTool.getJdkDetection());
assertEquals("JDK|1.8.0_342|52", data);
assertEquals("JDK|1.8.0_472|52", data);
}
@Test
@@ -39,7 +39,7 @@ public class SpringBoot2UndertowContainerTest {
void testJDK() {
String url = getUrlFromSpringBoot(container);
String data = VulTool.post(url + "/b64", DetectionTool.getJdkDetection());
assertEquals("JDK|1.8.0_342|52", data);
assertEquals("JDK|1.8.0_472|52", data);
}
@Test
@@ -64,6 +64,13 @@ public class SpringBoot2WarContainerTest {
ProbeAssertion.responseCommandIsOk(url, Server.Tomcat, Opcodes.V1_6);
}
@Test
@SneakyThrows
void testCommandReqHeaderResponseBodySpring() {
String url = getUrl(container);
ProbeAssertion.responseCommandIsOk(url, Server.SpringWebMvc, Opcodes.V1_6);
}
@Test
@SneakyThrows
void testBytecodeReqParamResponseBody() {
@@ -39,7 +39,7 @@ public class SpringBoot3ContainerTest {
void testJDK() {
String url = getUrlFromSpringBoot(container);
String data = VulTool.post(url + "/b64", DetectionTool.getJdkDetection());
assertEquals("JDK|17.0.2|61", data);
assertEquals("JDK|17.0.17|61", data);
}
@Test
@@ -64,6 +64,13 @@ public class SpringBoot3ContainerTest {
ProbeAssertion.responseCommandIsOk(url, Server.Tomcat, Opcodes.V17);
}
@Test
@SneakyThrows
void testCommandReqHeaderResponseBodySpring() {
String url = getUrlFromSpringBoot(container);
ProbeAssertion.responseCommandIsOk(url, Server.SpringWebMvc, Opcodes.V17);
}
@Test
@SneakyThrows
void testBytecodeReqParamResponseBody() {