JNDI注入原理分析

 

InitialContext.java

public Object lookup(String name) throws NamingException {
//getURLOrDefaultInitCtx函数会分析name的协议头返回对象协议的环境对象
//这里返回Context对象的子类rmiURLContext对象,然后在对应协议中去lookup搜索
//JNDI应用程序需要一种方式来传达定义访问命名和目录服务的环境的各种首选项和属性。 
//Context接口提供检索和更新此环境的方法。 
        return getURLOrDefaultInitCtx(name).lookup(name);
    }

 

我们进入lookup函数

GenericURLContext.class

传入var1="rmi://127.0.0.1:1099/aa"

public Object lookup(String var1) throws NamingException {
//此处this为rmiURLContext类调用对应类的getRootURLContext类为解析RMI地址
//不同协议调用这个函数,根据之前getURLOrDefaultInitCtx(name)返回对象的类型不同,执行不同的getRootURLContext
//进入不同的协议路线
        ResolveResult var2 = this.getRootURLContext(var1, this.myEnv);//获取RMI注册中心相关数据
        Context var3 = (Context)var2.getResolvedObj();//获取注册中心对象

        Object var4;
        try {
            var4 = var3.lookup(var2.getRemainingName());//去注册中心调用lookup查找,我们进入此处,传入name-aa
        } finally {
            var3.close();
        }

        return var4;
    }

JNDI注入原理分析_第1张图片

 

RegistryContext.class

传入var1=aa

 public Object lookup(Name var1) throws NamingException {
        if (var1.isEmpty()) {
            return new RegistryContext(this);
        } else {      //因为var1=aa
            Remote var2;
            try {
                var2 = this.registry.lookup(var1.get(0));//RMI客户端与注册中心通讯,返回RMI服务IP,地址等信息
            } catch (NotBoundException var4) {
                throw new NameNotFoundException(var1.get(0));
            } catch (RemoteException var5) {
                throw (NamingException)wrapRemoteException(var5).fillInStackTrace();
            }

            return this.decodeObject(var2, var1.getPrefix(1));
        }
    }

 

JNDI注入原理分析_第2张图片

JNDI注入原理分析_第3张图片

JNDI注入原理分析_第4张图片

RegistryContext.java

private Object decodeObject(Remote var1, Name var2) throws NamingException {
        try {
//注意到上面的服务端代码,我们在RMI服务端绑定的是一个Reference对象
//如果是Reference对象会进入var.getReference(),与RMI服务器进行一次连接,获取到远程class文件地址。
//如果是普通RMI对象服务,这里不会进行连接,只有在正式远程函数调用的时候才会连接RMI服务。
            Object var3 = var1 instanceof RemoteReference ? ((RemoteReference)var1).getReference() : var1;
            Reference var8 = null;
            if (var3 instanceof Reference) {
                var8 = (Reference)var3;
            } else if (var3 instanceof Referenceable) {
                var8 = ((Referenceable)((Referenceable)var3)).getReference();
            }

            if (var8 != null && var8.getFactoryClassLocation() != null && !trustURLCodebase) {
                throw new ConfigurationException("The object factory is untrusted. Set the system property 'com.sun.jndi.rmi.object.trustURLCodebase' to 'true'.");
            } else {
                return NamingManager.getObjectInstance(var3, var2, this, this.environment);
//获取reference对象进入此处
            }
        } catch (NamingException var5) {
            throw var5;
        } catch (RemoteException var6) {
            throw (NamingException)wrapRemoteException(var6).fillInStackTrace();
        } catch (Exception var7) {
            NamingException var4 = new NamingException();
            var4.setRootCause(var7);
            throw var4;
        }
    }

JNDI注入原理分析_第5张图片

JNDI注入原理分析_第6张图片

 

由于版本是环境版本是jdk1.8,所以抛出的异常,未成功rce

JNDI注入原理分析_第7张图片

未完待续

 

参考链接:https://xz.aliyun.com/t/6633#toc-3

d深入理解JNDI注入与Java反序列化漏洞利用

 

你可能感兴趣的:(漏洞复现)