Skip to content

Commit 13204c0

Browse files
committed
refactor: probe integration-test
1 parent c70a2b3 commit 13204c0

File tree

70 files changed

+1738
-5056
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

70 files changed

+1738
-5056
lines changed

integration-test/script/bes_pid.sh

Lines changed: 0 additions & 2 deletions
This file was deleted.

integration-test/src/test/java/com/reajason/javaweb/integration/ContainerTool.java

Lines changed: 0 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -28,21 +28,13 @@ public class ContainerTool {
2828
public static final MountableFile springBoot3WebfluxJarFile = MountableFile.forHostPath(Path.of("..", "vul", "vul-springboot3-webflux", "build", "libs", "vul-springboot3-webflux.jar").toAbsolutePath());
2929

3030
public static final Path neoGeorgDockerfile = Path.of("..", "assets", "neoreg", "Dockerfile").toAbsolutePath();
31-
public static final Path springBoot1Dockerfile = Path.of("..", "vul", "vul-springboot1", "Dockerfile").toAbsolutePath();
32-
public static final Path springBoot2Dockerfile = Path.of("..", "vul", "vul-springboot2", "Dockerfile").toAbsolutePath();
33-
public static final Path springBoot2JettyDockerfile = Path.of("..", "vul", "vul-springboot2-jetty", "Dockerfile").toAbsolutePath();
34-
public static final Path springBoot2UndertowDockerfile = Path.of("..", "vul", "vul-springboot2-undertow", "Dockerfile").toAbsolutePath();
35-
public static final Path springBoot2WebfluxDockerfile = Path.of("..", "vul", "vul-springboot2-webflux", "Dockerfile").toAbsolutePath();
36-
public static final Path springBoot3Dockerfile = Path.of("..", "vul", "vul-springboot3", "Dockerfile").toAbsolutePath();
37-
public static final Path springBoot3WebfluxDockerfile = Path.of("..", "vul", "vul-springboot3-webflux", "Dockerfile").toAbsolutePath();
3831

3932
public static final MountableFile jattachFile = MountableFile.forHostPath(Path.of("..", "assets", "agent", "jattach-linux"));
4033
public static final MountableFile tomcatPid = MountableFile.forHostPath(Path.of("script", "tomcat_pid.sh"));
4134
public static final MountableFile tongweb8Pid = MountableFile.forHostPath(Path.of("script", "tongweb8_pid.sh"));
4235
public static final MountableFile resinPid = MountableFile.forHostPath(Path.of("script", "resin_pid.sh"));
4336
public static final MountableFile jbossPid = MountableFile.forHostPath(Path.of("script", "jboss_pid.sh"));
4437
public static final MountableFile glassfishPid = MountableFile.forHostPath(Path.of("script", "glassfish_pid.sh"));
45-
public static final MountableFile besPid = MountableFile.forHostPath(Path.of("script", "bes_pid.sh"));
4638
public static final MountableFile apusicPid = MountableFile.forHostPath(Path.of("script", "apusic_pid.sh"));
4739
public static final MountableFile jettyPid = MountableFile.forHostPath(Path.of("script", "jetty_pid.sh"));
4840
public static final MountableFile webspherePid = MountableFile.forHostPath(Path.of("script", "websphere_pid.sh"));
@@ -57,28 +49,4 @@ public static String getUrl(GenericContainer<?> container) {
5749
log.info("container started, app url is : {}", url);
5850
return url;
5951
}
60-
61-
public static String getUrlFromSpringBoot(GenericContainer<?> container) {
62-
int port = container.getMappedPort(8080);
63-
String host = container.getHost();
64-
String url = "http://" + host + ":" + port;
65-
log.info("container started, app url is : {}", url);
66-
return url;
67-
}
68-
69-
public static String getUrlFromWebLogic(GenericContainer<?> container) {
70-
int port = container.getMappedPort(7001);
71-
String host = container.getHost();
72-
String url = "http://" + host + ":" + port + "/app";
73-
log.info("container started, app url is : {}", url);
74-
return url;
75-
}
76-
77-
public static String getUrlFromWAS(GenericContainer<?> container) {
78-
int port = container.getMappedPort(9080);
79-
String host = container.getHost();
80-
String url = "http://" + host + ":" + port + "/app";
81-
log.info("container started, app url is : {}", url);
82-
return url;
83-
}
8452
}
Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
package com.reajason.javaweb.integration.probe;
2+
3+
import com.reajason.javaweb.Server;
4+
import com.reajason.javaweb.integration.ProbeAssertion;
5+
import com.reajason.javaweb.integration.ShellAssertion;
6+
import com.reajason.javaweb.integration.VulTool;
7+
import com.reajason.javaweb.memshell.MemShellResult;
8+
import com.reajason.javaweb.memshell.ShellTool;
9+
import com.reajason.javaweb.memshell.ShellType;
10+
import com.reajason.javaweb.packer.Packers;
11+
import com.reajason.javaweb.probe.payload.FilterProbeFactory;
12+
import lombok.SneakyThrows;
13+
import lombok.extern.slf4j.Slf4j;
14+
import net.bytebuddy.jar.asm.Opcodes;
15+
import org.apache.commons.lang3.StringUtils;
16+
import org.junit.jupiter.api.AfterAll;
17+
import org.junit.jupiter.api.Assumptions;
18+
import org.junit.jupiter.api.Test;
19+
import org.junit.jupiter.api.TestInstance;
20+
import org.testcontainers.containers.GenericContainer;
21+
import org.testcontainers.containers.wait.strategy.Wait;
22+
import org.testcontainers.images.builder.ImageFromDockerfile;
23+
24+
import java.nio.file.Files;
25+
import java.nio.file.Paths;
26+
import java.util.List;
27+
28+
import static com.reajason.javaweb.integration.ShellAssertion.shellInjectIsOk;
29+
import static org.junit.jupiter.api.Assertions.assertEquals;
30+
31+
/**
32+
* Abstract base class for probe container tests.
33+
* Provides common test methods that are shared across all probe tests.
34+
*
35+
* @author ReaJason
36+
* @since 2024/12/4
37+
*/
38+
@Slf4j
39+
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
40+
public abstract class AbstractProbeContainerTest {
41+
42+
/**
43+
* Subclasses must provide their configuration.
44+
*/
45+
protected abstract ProbeTestConfig getConfig();
46+
47+
/**
48+
* Subclasses must provide their container instance.
49+
*/
50+
protected abstract GenericContainer<?> getContainer();
51+
52+
/**
53+
* Helper to build a container from config.
54+
*/
55+
protected static GenericContainer<?> buildContainer(ProbeTestConfig config) {
56+
GenericContainer<?> container = new GenericContainer<>(config.getImageName());
57+
58+
if (config.getWarFile() != null && StringUtils.isNotBlank(config.getWarDeployPath())) {
59+
container.withCopyToContainer(config.getWarFile(), config.getWarDeployPath());
60+
}
61+
62+
if(config.getJarFile() != null && StringUtils.isNotBlank(config.getJarDeployPath())){
63+
container.withCopyFileToContainer(config.getJarFile(), config.getJarDeployPath());
64+
}
65+
66+
if (config.getWaitStrategy() != null) {
67+
container.waitingFor(config.getWaitStrategy());
68+
} else if (StringUtils.isNotBlank(config.getHealthCheckPath())) {
69+
container.waitingFor(Wait.forHttp(config.getHealthCheckPath()));
70+
}
71+
72+
container.withExposedPorts(config.getExposedPort());
73+
74+
if (config.isPrivilegedMode()) {
75+
container.withPrivilegedMode(true);
76+
}
77+
if(config.getCommand() != null){
78+
container.withCommand(config.getCommand());
79+
}
80+
81+
return container;
82+
}
83+
84+
/**
85+
* Get the URL based on the configured strategy.
86+
*/
87+
protected String getUrl() {
88+
GenericContainer<?> container = getContainer();
89+
ProbeTestConfig config = getConfig();
90+
int port = container.getMappedPort(config.getExposedPort());
91+
String host = container.getHost();
92+
93+
String url = "http://" + host + ":" + port;
94+
String contextPath = config.getContextPath();
95+
if (StringUtils.isNotBlank(contextPath)) {
96+
if (!contextPath.startsWith("/")) {
97+
contextPath = "/" + contextPath;
98+
}
99+
url += contextPath;
100+
}
101+
102+
log.info("container started, app url is: {}", url);
103+
return url;
104+
}
105+
106+
@AfterAll
107+
void tearDown() {
108+
GenericContainer<?> container = getContainer();
109+
if (container != null) {
110+
log.info(container.getLogs());
111+
}
112+
}
113+
114+
// ==================== Test Methods ====================
115+
116+
@Test
117+
protected void testJDK() {
118+
doTestJDK();
119+
}
120+
121+
/**
122+
* Subclasses can override testJDK() with @RetryingTest(3) and call this method.
123+
*/
124+
protected void doTestJDK() {
125+
String url = getUrl();
126+
String data = VulTool.post(url + "/b64", DetectionTool.getJdkDetection());
127+
assertEquals(getConfig().getExpectedJdkVersion(), data);
128+
}
129+
130+
@Test
131+
@SneakyThrows
132+
void testBasicInfo() {
133+
String url = getUrl();
134+
String data = VulTool.post(url + "/b64", DetectionTool.getBasicInfoPrinter());
135+
Files.writeString(
136+
Paths.get("src", "test", "resources", "infos", this.getClass().getSimpleName() + "BasicInfo.txt"),
137+
data);
138+
}
139+
140+
@Test
141+
void testServerDetection() {
142+
String url = getUrl();
143+
String data = VulTool.post(url + "/b64", DetectionTool.getServerDetection());
144+
assertEquals(getConfig().getServer(), data);
145+
}
146+
147+
@Test
148+
@SneakyThrows
149+
protected void testCommandReqHeaderResponseBody() {
150+
Assumptions.assumeTrue(getConfig().isSupportsCommand(),
151+
"Command test not supported for this server");
152+
String url = getUrl();
153+
ProbeAssertion.responseCommandIsOk(url, getConfig().getServer(), getConfig().getTargetJdkVersion());
154+
}
155+
156+
@Test
157+
@SneakyThrows
158+
protected void testScriptEngineReqHeaderResponseBody() {
159+
Assumptions.assumeTrue(getConfig().isSupportsScriptEngine(),
160+
"ScriptEngine test not supported for this server");
161+
String url = getUrl();
162+
ProbeAssertion.responseScriptEngineIsOk(url, getConfig().getServer(), getConfig().getTargetJdkVersion());
163+
}
164+
165+
@Test
166+
@SneakyThrows
167+
void testBytecodeReqParamResponseBody() {
168+
Assumptions.assumeTrue(getConfig().isSupportsBytecode(),
169+
"Bytecode test not supported for this server");
170+
String url = getUrl();
171+
ProbeAssertion.responseBytecodeIsOk(url, getConfig().getServer(), getConfig().getTargetJdkVersion());
172+
if (getConfig().isSupportsBytecodeWithoutPrefix()) {
173+
ProbeAssertion.responseBytecodeWithoutPrefixIsOk(url, getConfig().getServer(), getConfig().getTargetJdkVersion());
174+
}
175+
}
176+
177+
@Test
178+
void testFilterProbe() {
179+
Assumptions.assumeTrue(getConfig().isSupportsFilterProbe(),
180+
"Filter probe test not supported for this server");
181+
String url = getUrl();
182+
String data = VulTool.post(url + "/b64", FilterProbeFactory.getBase64ByServer(getConfig().getServer()));
183+
ShellAssertion.assertFilterProbeIsRight(data);
184+
}
185+
186+
@Test
187+
protected void testFilterFirstInject() {
188+
Assumptions.assumeTrue(getConfig().isSupportsFilterProbe(),
189+
"Filter first inject test not supported for this server");
190+
String url = getUrl();
191+
ProbeTestConfig config = getConfig();
192+
193+
String shellType = config.isJakarta() ? ShellType.JAKARTA_FILTER : ShellType.FILTER;
194+
MemShellResult memShellResult = shellInjectIsOk(
195+
url,
196+
config.getServer(),
197+
shellType,
198+
ShellTool.Command,
199+
getConfig().getTargetJdkVersion(),
200+
Packers.BigInteger,
201+
getContainer());
202+
203+
String data = VulTool.post(url + "/b64", FilterProbeFactory.getBase64ByServer(config.getServer()));
204+
List<String> filter = ProbeAssertion.getFiltersForContext(data, "/app");
205+
String filterName = ProbeAssertion.extractFilterName(filter.get(0));
206+
assertEquals(filterName, memShellResult.getShellClassName());
207+
}
208+
209+
@Test
210+
@SneakyThrows
211+
protected void testCommandReqHeaderResponseBodySpring() {
212+
Assumptions.assumeTrue(getConfig().isSupportsSpringWebMvc(),
213+
"Spring WebMVC test not supported for this server");
214+
String url = getUrl();
215+
ProbeAssertion.responseCommandIsOk(url, Server.SpringWebMvc, getConfig().getTargetJdkVersion());
216+
}
217+
}

0 commit comments

Comments
 (0)