CVE-2024-21006 Weblogic 远程代码执行挖掘思路
Hu3sky1 发表于 四川 技术文章 5644浏览 · 2024-04-16 02:24

前世

漏洞的最终利用方式和 CVE-2024-20931CVE-2023-21839 一致,都是利用 IIOP -> JNDI 去造成远程代码执行,不过在整个触发的过程中有所不同。
这两次利用都是以weblogic.jndi.internal.BasicNamingNode#lookupSharable为入口,在resolveObject里触发jndi注入,具体的调用这里就不细讲了。

今生

这里我把目光放在下面的方法里,当restOfName长度不为0,并且object类型不为BasicNamingNode,就会走到else判断里
这里的namelookup传入的name值,objectlookup的对象

这里需要看一下restOfName如何赋值,getRest方法如下

private String getRest(String name) throws NamingException {  
    int nameLength = name.length();  
    if (nameLength == 0) {  
        return name;  
    } else {  
        char firstChar = name.charAt(0);  
        int i;  
        if (firstChar == '"') {  
            i = name.indexOf(34, 1);  
            this.checkQuoteClose(i, name);  
            ++i;  
            if (i < nameLength && this.isSeparator(name.charAt(i))) {  
                ++i;  
            }  

            return name.substring(i);  
        } else if (firstChar == '\'') {  
            i = name.indexOf(39, 1);  
            this.checkQuoteClose(i, name);  
            ++i;  
            if (i < nameLength && this.isSeparator(name.charAt(i))) {  
                ++i;  
            }  

            return name.substring(i);  
        } else {  
            for(i = 0; i < nameLength; ++i) {  
                char currentChar = name.charAt(i);  
                switch (currentChar) {  
                    case '"':  
                    case '\'':  
                        throw new InvalidNameException("Unescaped quote in a component");  
                    case '\\':  
                        ++i;  
                        if (i == nameLength) {  
                            throw new InvalidNameException("An escape at the end of a name must be escaped");  
                        }  
                        break;  
                    default:  
                        if (this.isSeparator(currentChar)) {  
                            return name.substring(i + 1);  
                        }  
                }  
            }  

            return "";  
        }  
    }  
}

name的第一个字符是'" 或者name里存在./

就能解析出rest,于是我们跟进getContinuationCtx方法,这里先调用了JNDIUtils.isValidReferenceObject


跟进isValidReferenceObject,继续调用isValidJndiScheme

通过调用processURLAddrs方法提取出ref对象里的classFactoryLocation属性,然后判断classFactoryLocation允许的协议-jndiAllowScheme,允许的协议默认为空,也就是说不允许利用远程http协议地址让jndi去加载远程class。

回到getContinuationCtx方法,继续调用 javax.naming.spi.NamingManager#getContinuationContext,走到原生的jndi流程里。

一直跟到javax.naming.spi.NamingManager#getObjectInstance

寻找本地ObjectFactory

跟进getObjectFactoryFromReference,首先进行factory本地加载,如果加载不到,去加载远程class,但是前面已经提到,无法加载远程class,因为classFactoryLocation不被允许使用任何协议

于是,只能去考虑本地ObjectFactory,如果这里返回的ObjectFactory,在后续调用factory.getObjectInsatce方法里,存在恶意调用,那么也可以进行利用。最终,寻找到了一个可以利用的ObjectFactoryweblogic.application.naming.MessageDestinationObjectFactory

来看下他的getObjectInstance方法,obj就是lookup的对象

调用对象的lookupMessageDestination
并且这里的jndiName是实例里的属性,可控,所以最终造成jndi注入。

时间线

  • 2024-03-29 漏洞提交至Oracle
  • 2024-04-16 Oracle发布补丁通告
1 条评论
某人
表情
可输入 255