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

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

这里需要看一下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方法里,存在恶意调用,那么也可以进行利用。最终,寻找到了一个可以利用的ObjectFactory,weblogic.application.naming.MessageDestinationObjectFactory
来看下他的getObjectInstance方法,obj就是lookup的对象

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

时间线
- 2024-03-29 漏洞提交至Oracle
- 2024-04-16 Oracle发布补丁通告
师傅这个在高版本的jdk可以使用吗?我的理解是高版本jdk虽然是打本地工厂类,但是这个本地工厂类最后的实现还是jndi,还是绕不过高版本