feat: support addFilterFirst for tomcat

This commit is contained in:
ReaJason
2026-01-12 02:12:34 +08:00
parent 3e2fb861cd
commit d873dae8f3
14 changed files with 659 additions and 14 deletions
@@ -43,28 +43,32 @@ public class ContainerTool {
public static String getUrl(GenericContainer<?> container) {
int port = container.getMappedPort(8080);
String url = "http://127.0.0.1:" + port + "/app";
String host = container.getHost();
String url = "http://" + host + ":" + port + "/app";
log.info("container started, app url is : {}", url);
return url;
}
public static String getUrlFromSpringBoot(GenericContainer<?> container) {
int port = container.getMappedPort(8080);
String url = "http://127.0.0.1:" + port;
String host = container.getHost();
String url = "http://" + host + ":" + port;
log.info("container started, app url is : {}", url);
return url;
}
public static String getUrlFromWebLogic(GenericContainer<?> container) {
int port = container.getMappedPort(7001);
String url = "http://127.0.0.1:" + port + "/app";
String host = container.getHost();
String url = "http://" + host + ":" + port + "/app";
log.info("container started, app url is : {}", url);
return url;
}
public static String getUrlFromWAS(GenericContainer<?> container) {
int port = container.getMappedPort(9080);
String url = "http://127.0.0.1:" + port + "/app";
String host = container.getHost();
String url = "http://" + host + ":" + port + "/app";
log.info("container started, app url is : {}", url);
return url;
}
@@ -11,6 +11,9 @@ import com.reajason.javaweb.probe.config.ResponseBodyConfig;
import lombok.SneakyThrows;
import okhttp3.*;
import java.util.ArrayList;
import java.util.List;
import static org.hamcrest.CoreMatchers.anyOf;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.MatcherAssert.assertThat;
@@ -141,4 +144,41 @@ public class ProbeAssertion {
));
}
}
public static List<String> getFiltersForContext(String probeData, String contextPath) {
List<String> filters = new ArrayList<>();
String[] lines = probeData.split("\n");
boolean inTargetContext = false;
for (String line : lines) {
line = line.trim();
if (line.startsWith("Context:")) {
inTargetContext = line.contains("(" + contextPath + ")");
} else if (inTargetContext) {
if (line.isEmpty() || line.startsWith("Context:")) {
break;
}
if (line.equals("No filters found")) {
break;
}
if (line.contains(" -> ")) {
filters.add(line);
}
}
}
return filters;
}
public static String extractFilterName(String filterLine) {
if (filterLine == null || filterLine.isEmpty()) {
return "";
}
int arrowIndex = filterLine.indexOf(" ->");
if (arrowIndex > 0) {
return filterLine.substring(0, arrowIndex).trim();
}
return filterLine.trim();
}
}
@@ -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.TomcatFilterProbe;
import com.reajason.javaweb.utils.CommonUtil;
import net.bytebuddy.ByteBuddy;
import org.apache.commons.codec.binary.Base64;
@@ -33,4 +34,8 @@ public class DetectionTool {
public static String getServerDetection() {
return getBase64Class(ServerProbe.class);
}
public static String getTomcatFilterProbe() {
return getBase64Class(TomcatFilterProbe.class);
}
}
@@ -4,10 +4,14 @@ 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 org.objectweb.asm.Opcodes;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Test;
import org.objectweb.asm.Opcodes;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.junit.jupiter.Container;
@@ -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.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;
/**
@@ -34,6 +42,12 @@ public class Tomcat10ContainerTest {
.withCopyToContainer(warJakartaFile, "/usr/local/tomcat/webapps/app.war")
.waitingFor(Wait.forHttp("/app"))
.withExposedPorts(8080);
@AfterAll
public static void tearDown() {
log.info(container.getLogs());
}
@Test
void testJDK() {
String url = getUrl(container);
@@ -76,4 +90,24 @@ public class Tomcat10ContainerTest {
String url = getUrl(container);
ProbeAssertion.responseBytecodeIsOk(url, Server.Tomcat, Opcodes.V11);
}
@Test
void testFilterProbe() {
String url = getUrl(container);
String data = VulTool.post(url + "/b64", DetectionTool.getTomcatFilterProbe());
System.out.println(data);
assertThat(data, anyOf(
containsString("Context: ")
));
}
@Test
void testFilterFirstInject() {
String url = getUrl(container);
shellInjectIsOk(url, Server.Tomcat, ShellType.JAKARTA_FILTER, ShellTool.Command, Opcodes.V11, Packers.BigInteger, container);
String data = VulTool.post(url + "/b64", DetectionTool.getTomcatFilterProbe());
List<String> filter = ProbeAssertion.getFiltersForContext(data, "/app");
String filterName = ProbeAssertion.extractFilterName(filter.get(0));
assertThat(filterName, anyOf(startsWith("org.apache.http.web.handlers")));
}
}
@@ -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;
/**
@@ -70,4 +77,24 @@ public class Tomcat11ContainerTest {
String url = getUrl(container);
ProbeAssertion.responseBytecodeIsOk(url, Server.Tomcat, Opcodes.V17);
}
@Test
void testFilterProbe() {
String url = getUrl(container);
String data = VulTool.post(url + "/b64", DetectionTool.getTomcatFilterProbe());
System.out.println(data);
assertThat(data, anyOf(
containsString("Context: ")
));
}
@Test
void testFilterFirstInject() {
String url = getUrl(container);
shellInjectIsOk(url, Server.Tomcat, ShellType.JAKARTA_FILTER, ShellTool.Command, org.objectweb.asm.Opcodes.V11, Packers.BigInteger, container);
String data = VulTool.post(url + "/b64", DetectionTool.getTomcatFilterProbe());
List<String> filter = ProbeAssertion.getFiltersForContext(data, "/app");
String filterName = ProbeAssertion.extractFilterName(filter.get(0));
assertThat(filterName, anyOf(startsWith("org.apache.http.web.handlers")));
}
}
@@ -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;
/**
@@ -71,4 +78,24 @@ public class Tomcat11JRE21ContainerTest {
String url = getUrl(container);
ProbeAssertion.responseBytecodeIsOk(url, Server.Tomcat, Opcodes.V21);
}
@Test
void testFilterProbe() {
String url = getUrl(container);
String data = VulTool.post(url + "/b64", DetectionTool.getTomcatFilterProbe());
System.out.println(data);
assertThat(data, anyOf(
containsString("Context: ")
));
}
@Test
void testFilterFirstInject() {
String url = getUrl(container);
shellInjectIsOk(url, Server.Tomcat, ShellType.JAKARTA_FILTER, ShellTool.Command, org.objectweb.asm.Opcodes.V21, Packers.BigInteger, container);
String data = VulTool.post(url + "/b64", DetectionTool.getTomcatFilterProbe());
List<String> filter = ProbeAssertion.getFiltersForContext(data, "/app");
String filterName = ProbeAssertion.extractFilterName(filter.get(0));
assertThat(filterName, anyOf(startsWith("org.apache.http.web.handlers")));
}
}
@@ -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 org.junit.jupiter.api.AfterAll;
@@ -17,9 +20,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;
/**
@@ -84,4 +91,24 @@ public class Tomcat5ContainerTest {
String url = getUrl(container);
ProbeAssertion.responseBytecodeIsOk(url, Server.Tomcat, Opcodes.V1_6);
}
@Test
void testFilterProbe() {
String url = getUrl(container);
String data = VulTool.post(url + "/b64", DetectionTool.getTomcatFilterProbe());
System.out.println(data);
assertThat(data, anyOf(
containsString("Context: ")
));
}
@Test
void testFilterFirstInject() {
String url = getUrl(container);
shellInjectIsOk(url, Server.Tomcat, ShellType.FILTER, ShellTool.Command, Opcodes.V1_6, Packers.BigInteger, container);
String data = VulTool.post(url + "/b64", DetectionTool.getTomcatFilterProbe());
List<String> filter = ProbeAssertion.getFiltersForContext(data, "/app");
String filterName = ProbeAssertion.extractFilterName(filter.get(0));
assertThat(filterName, anyOf(startsWith("org.apache.http.web.handlers")));
}
}
@@ -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 org.junit.jupiter.api.Test;
@@ -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;
/**
@@ -76,4 +83,24 @@ public class Tomcat6ContainerTest {
String url = getUrl(container);
ProbeAssertion.responseBytecodeIsOk(url, Server.Tomcat, Opcodes.V1_6);
}
@Test
void testFilterProbe() {
String url = getUrl(container);
String data = VulTool.post(url + "/b64", DetectionTool.getTomcatFilterProbe());
System.out.println(data);
assertThat(data, anyOf(
containsString("Context: ")
));
}
@Test
void testFilterFirstInject() {
String url = getUrl(container);
shellInjectIsOk(url, Server.Tomcat, ShellType.FILTER, ShellTool.Command, Opcodes.V1_6, Packers.BigInteger, container);
String data = VulTool.post(url + "/b64", DetectionTool.getTomcatFilterProbe());
List<String> filter = ProbeAssertion.getFiltersForContext(data, "/app");
String filterName = ProbeAssertion.extractFilterName(filter.get(0));
assertThat(filterName, anyOf(startsWith("org.apache.http.web.handlers")));
}
}
@@ -4,11 +4,14 @@ 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 org.objectweb.asm.Opcodes;
import org.junit.jupiter.api.Test;
import org.junitpioneer.jupiter.RetryingTest;
import org.objectweb.asm.Opcodes;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.junit.jupiter.Container;
@@ -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;
/**
@@ -78,4 +85,24 @@ public class Tomcat7ContainerTest {
String url = getUrl(container);
ProbeAssertion.responseBytecodeIsOk(url, Server.Tomcat, Opcodes.V1_7);
}
@Test
void testFilterProbe() {
String url = getUrl(container);
String data = VulTool.post(url + "/b64", DetectionTool.getTomcatFilterProbe());
System.out.println(data);
assertThat(data, anyOf(
containsString("Context: ")
));
}
@Test
void testFilterFirstInject() {
String url = getUrl(container);
shellInjectIsOk(url, Server.Tomcat, ShellType.FILTER, ShellTool.Command, Opcodes.V1_6, Packers.BigInteger, container);
String data = VulTool.post(url + "/b64", DetectionTool.getTomcatFilterProbe());
List<String> filter = ProbeAssertion.getFiltersForContext(data, "/app");
String filterName = ProbeAssertion.extractFilterName(filter.get(0));
assertThat(filterName, anyOf(startsWith("org.apache.http.web.handlers")));
}
}
@@ -4,10 +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 org.objectweb.asm.Opcodes;
import org.junit.jupiter.api.Test;
import org.objectweb.asm.Opcodes;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.junit.jupiter.Container;
@@ -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;
/**
@@ -47,7 +54,9 @@ public class Tomcat8ContainerTest {
void testBasicInfo() {
String url = getUrl(container);
String data = VulTool.post(url + "/b64", DetectionTool.getBasicInfoPrinter());
Files.writeString(Paths.get("src", "test", "resources", "infos", this.getClass().getSimpleName() + "BasicInfo.txt"), data);
Files.writeString(
Paths.get("src", "test", "resources", "infos", this.getClass().getSimpleName() + "BasicInfo.txt"),
data);
}
@Test
@@ -78,4 +87,24 @@ public class Tomcat8ContainerTest {
ProbeAssertion.responseBytecodeIsOk(url, Server.Tomcat, Opcodes.V1_8);
ProbeAssertion.responseBytecodeWithoutPrefixIsOk(url, Server.Tomcat, Opcodes.V1_8);
}
@Test
void testFilterProbe() {
String url = getUrl(container);
String data = VulTool.post(url + "/b64", DetectionTool.getTomcatFilterProbe());
System.out.println(data);
assertThat(data, anyOf(
containsString("Context: ")
));
}
@Test
void testFilterFirstInject() {
String url = getUrl(container);
shellInjectIsOk(url, Server.Tomcat, ShellType.FILTER, ShellTool.Command, Opcodes.V1_6, Packers.BigInteger, container);
String data = VulTool.post(url + "/b64", DetectionTool.getTomcatFilterProbe());
List<String> filter = ProbeAssertion.getFiltersForContext(data, "/app");
String filterName = ProbeAssertion.extractFilterName(filter.get(0));
assertThat(filterName, anyOf(startsWith("org.apache.http.web.handlers")));
}
}
@@ -4,11 +4,14 @@ 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 org.objectweb.asm.Opcodes;
import org.junit.jupiter.api.Test;
import org.junitpioneer.jupiter.RetryingTest;
import org.objectweb.asm.Opcodes;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.junit.jupiter.Container;
@@ -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;
/**
@@ -70,4 +77,24 @@ public class Tomcat9ContainerTest {
String url = getUrl(container);
ProbeAssertion.responseBytecodeIsOk(url, Server.Tomcat, Opcodes.V9);
}
@Test
void testFilterProbe() {
String url = getUrl(container);
String data = VulTool.post(url + "/b64", DetectionTool.getTomcatFilterProbe());
System.out.println(data);
assertThat(data, anyOf(
containsString("Context: ")
));
}
@Test
void testFilterFirstInject() {
String url = getUrl(container);
shellInjectIsOk(url, Server.Tomcat, ShellType.FILTER, ShellTool.Command, Opcodes.V1_6, Packers.BigInteger, container);
String data = VulTool.post(url + "/b64", DetectionTool.getTomcatFilterProbe());
List<String> filter = ProbeAssertion.getFiltersForContext(data, "/app");
String filterName = ProbeAssertion.extractFilterName(filter.get(0));
assertThat(filterName, anyOf(startsWith("org.apache.http.web.handlers")));
}
}