JNDI漏洞利用探索

本文探讨了JNDI漏洞的自动化测试Bypass利用链和反序列化利用链。通过RegistryContextFactory和LdapCtxFactory进行RMI调用,实现了自动化测试。同时,分析了自动测试反序列化利用链的尝试,包括失败案例和成功策略。总结了利用过程中遇到的问题,如栈溢出和特定利用链的局限性。
摘要由CSDN通过智能技术生成

最近学习了师傅寻找的一些JNDI漏洞的利用链受益匪浅,自己也尝试关于JNDI漏洞利用做一些挖掘,目前JNDI在利用过程我想到了两个问题。

  • 测试每一个JNDI Bypass 利用链都需要手动更改URL很不方便,能否我去请求一个地址,让目标将我所有的链跑一遍?
  • JNDI利用过程中可以通过反序列化利用,能否自动化探测反序列化利用链?

自动测试Bypass 利用链

为了让这种方式更加通用,我们首先考虑的是JDK原生的实现ObjectFactory的类,那么我注意到了下面几个类。

  • com.sun.jndi.rmi.registry.RegistryContextFactory
  • com.sun.jndi.ldap.LdapCtxFactory

RegistryContextFactory

调用分析

通过getURLs从Reference获取url列表并封装为数组,URLsToObject中对数组中的URL列表发起RMI请求,所以RegistryContextFactory满足我们的需求。

public Object getObjectInstance(Object var1, Name var2, Context var3, Hashtable<?, ?> var4) throws NamingException {
     //判断是否为引用对象并且factoryClassname为RegistryContextFactory
        if (!isRegistryRef(var1)) {
            return null;
        } else {
            //从引用对象中获取URL列表并循环发起调用
            Object var5 = URLsToObject(getURLs((Reference)var1), var4);
            if (var5 instanceof RegistryContext) {
                RegistryContext var6 = (RegistryContext)var5;
                var6.reference = (Reference)var1;
            }
            return var5;
        }
    }
  • getURLs获取URL必须满足RefAddr是StringRefAddr类型且Type属性为URL才会保存。
private static String[] getURLs(Reference var0) throws NamingException {
        int var1 = 0;
        String[] var2 = new String[var0.size()];
        Enumeration var3 = var0.getAll();
        //从RefAddr中获取url并保存到数组中
        while(var3.hasMoreElements()) {
            RefAddr var4 = (RefAddr)var3.nextElement();
            //只有RefAddr是StringRefAddr类型,且Type属性为URL才会保存
            if (var4 instanceof StringRefAddr && var4.getType().equals("URL")) {
                var2[var1++] = (String)var4.getContent();
            }
        }
        if (var1 == 0) {
            throw new ConfigurationException("Reference contains no valid addresses");
        } else if (var1 == var0.size()) {
            return var2;
        } else {
            //返回URL数组
            String[] var5 = new String[var1];
            System.arraycopy(var2, 0, var5, 0, var1);
            return var5;
        }
    }
  • URLsToObject中创建rmiURLContextFactory对象并调用getObjectInstancegetObjectInstance中判断传入的object类型如果是数组则调用getUsingURLs.
private static Object URLsToObject(String[] var0, Hashtable<?, ?> var1) throws NamingException {
        rmiURLContextFactory var2 = new rmiURLContextFactory();
        return var2.getObjectInstance(var0, (Name)null, (Context)null, var1);
    }


public Object getObjectInstance(Object var1, Name var2, Context var3, Hashtable<?, ?> var4) throws NamingException {
        if (var1 == null) {
            return new rmiURLContext(var4);
        } else if (var1 instanceof String) {
            return getUsingURL((String)var1, var4);
        } else if (var1 instanceof String[]) {
            //数组类型
            return getUsingURLs((String[])((String[])var1), var4);
        } else {
            throw new ConfigurationException("rmiURLContextFactory.getObjectInstance: argument must be an RMI URL String or an array of them");
        }
    }
  • getUsingURLs创建rmiURLContext并循环调用lookup发起RMI调用直到获取一个对象并返回。
private static Object getUsingURLs(String[] var0, Hashtable<?, ?> var1) throws NamingException {
        if (var0.length == 0) {
            throw new ConfigurationException("rmiURLContextFactory: empty URL array");
        } else {
            rmiURLContext var2 = new rmiURLContext(var1);
            try {
                NamingException var3 = null;
                int var4 = 0;
                while(var4 < var0.length) {
                 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值