Weblogic CVE-2023-21931
2023-4-23 11:49:2 Author: 白帽子左一(查看原文) 阅读量:68 收藏

扫码领资料

获网安教程

免费&进群

近些年,Weblogic反序列化漏洞一直围绕着反序列化的触发点进行漏洞挖掘,事实上还有很多存在反序列化但无法实时利用的点,在大家平时的漏洞挖掘中容易忽略。在行业内也有一些关于”后反序列化“的进一步讨论,这些看似无法利用的漏洞,其实可以通过一些后续的技巧完成稳定的利用效果。例如,进行bind()rebind()操作后,并没有触发漏洞,此时可以尝试其他方法如lookup()lookupLink()等触发漏洞。

通过这种思路我们发现了两个Weblogic的后反序列化漏洞(CVE-2023-21931、CVE-2023-21839),获得了Oracle的官方确认。本文以这两个Weblogic漏洞为例,分享"后反序列化漏洞"的利用思路。我们相信还有很多这类的漏洞在未来会逐渐被挖掘出来,希望本篇文章能够给大家一些启发。

Weblogic反序列化漏洞挖掘思路是利用 readObject()readResolve()readExternal()等反序列化方法对恶意序列化数据进行操作,以达到攻击目的。常规的漏洞思路重点关注Weblogic在反序列化过程中进行恶意攻击,而忽略了反序列化完成后的操作。后反序列化漏洞挖掘的思路重点关注Weblogic完成反序列化过程后,在达到某个时机或执行操作后触发的漏洞攻击。

在Weblogic中,如果进行bind()rebind()操作后,并没有触发漏洞,此时可以尝试其他方法如lookup()lookupLink()等触发漏洞。

本文将以 lookup() 方法作为漏洞触发点,对 Weblogic 后反序列化漏洞的攻击过程进行分析和漏洞实例展示。

通过跟踪调用堆栈,我们发现lookup()的流程如下:

  • Weblogic在接收到请求后,通过BasicServerRef类中的invoke()方法解析传入数据。

  • 通过_invoke()方法,Weblogic根据传入的方法名resolve_any 执行的resolve_any()方法。

  • resolve_any()方法中,通过resolveObject()方法对传入的绑定命名进行解析。

  • resolveObject()方法中,根据上下文信息调用其中的lookup()方法。

  • 根据上下文中的信息,经过在WLContextImplWLEventContextImpl、 WLEventContextImpl 、RootNamingNodeServerNamingNode 、BasicNamingNode类中一系列的lookup()方法调用,实现BasicNamingNode类中的resolveObject()方法调用。

  • 由于传入resolveObject()方法中的obj不是NamingNode类的实例,且mode的值默认为1,所以会调用WLNamingManager类中的getObjectInstance()方法。

最终,可以看到WLNamingManager类的getObjectInstance()方法根据传入的对象接口类型,调用对象中的getReferent()方法,完成漏洞触发点的lookup()方法调用。实际上这两个CVE漏洞都是通过getObjectInstance()的两个分支触发的。

CVE-2023-21931的漏洞触发点在WLNamingManager类的 getObjectInstance()方法中,当传入的 boundObject 对象是 LinkRef 的实现类时,则调用传入对象 boundObject 的 getLinkName() 方法,并通过lookup() 方法对 getLinkName() 方法返回的 linkAddrType 地址进行远程JNDI加载。在实例化 LinkRef 类时,可以通过类中的构造方法给 linkAddrType 传入一个JNDI地址。这样,我们就可以调用 lookup() 方法对自定义的JNDI地址进行远程加载,达到攻击的目的。

package weblogic.jndi.internal;
public final class WLNamingManager {
public static Object getObjectInstance(Object boundObject, Name name, Context ctx, Hashtable env) throws NamingException {
if (boundObject instanceof ClassTypeOpaqueReference) {
......
} else if (boundObject instanceof LinkRef) {
String linkName = ((LinkRef)boundObject).getLinkName();
InitialContext ic = null;
try {
ic = new InitialContext(env);
boundObject = ic.lookup(linkName); // 漏洞触发点
} catch (NamingException var15) {
......
} finally {......}
}
}
}

漏洞JNDI地址构造在LinkRef这个类中,LinkRef是Java的一个原生类。通过LinkRef类中的构造方法,我们可以控制变量linkAddrType的值, 再通过getLinkName()方法将linkAddrType作为字符串返回。

package javax.naming;
public class LinkRef extends Reference {
static final String linkClassName = LinkRef.class.getName();
static final String linkAddrType = "LinkAddress";

public LinkRef(Name linkName) {
super(linkClassName, new StringRefAddr(linkAddrType, linkName.toString()));
}

public LinkRef(String linkName) {
super(linkClassName, new StringRefAddr(linkAddrType, linkName));
}

public String getLinkName() throws NamingException {
if (className != null && className.equals(linkClassName)) {
RefAddr addr = get(linkAddrType);
if (addr != null && addr instanceof StringRefAddr) {
return (String)((StringRefAddr)addr).getContent();
}
}
throw new MalformedLinkException();
}
}

在上述过程中,rebind()lookup()方法的反序列化过程并未执行恶意操作,而是在完成反序列化之后,通过调用类WLNamingManagergetObjectInstance()方法的lookup()才触发漏洞,进行远程恶意加载JNDI地址操作的。

我们在GOBY中已经集成了CVE-2023-21931漏洞,并加入了回显和反弹shell的功能。演示效果如下:

ForeignOpaqueReferenceOpaqueReference接口的实现类。在ForeignOpaqueReference类中声明了两个私有变量:jndiEnvironmentremoteJNDIName,同时声明了两个构造方法,在有参构造方法中接收envremoteJNDIName,并分别赋值给了上面的两个私有类变量。

ForeignOpaqueReference类的getReferent()方法是OpaqueReference接口的实现方法,在getReferent()方法中,retVal = context.lookup(this.remoteJNDIName); 对本类remoteJNDIName变量中的JNDI地址进行远程加载,导致了反序列化漏洞。

package weblogic.jndi.internal;
public class ForeignOpaqueReference implements OpaqueReference, Serializable {
private Hashtable jndiEnvironment;
private String remoteJNDIName;
......
public ForeignOpaqueReference(String remoteJNDIName, Hashtable env) {
this.remoteJNDIName = remoteJNDIName;
this.jndiEnvironment = env;
}
public Object getReferent(Name name, Context ctx) throws NamingException {
InitialContext context;
if (this.jndiEnvironment == null) {
context = new InitialContext();
} else {
Hashtable properties = this.decrypt();
context = new InitialContext(properties);
}
Object retVal;
try {
retVal = context.lookup(this.remoteJNDIName); // 漏洞点
} finally {
context.close();
}
return retVal;
}
......
}

getReferent()调用分析

package weblogic.jndi;
public interface OpaqueReference {
Object getReferent(Name var1, Context var2) throws NamingException;
String toString();
}

OpaqueReference 接口有两个抽象方法:getReferent() 和 toString();

ForeignOpaqueReference 类的 getReferent() 方法调用在WLNamingManager类中。

在 WLNamingManager 类的 getObjectInstance() 方法中,当传入的 boundObject 对象实现了 OpaqueReference 接口时,则会调用该对象的 getReferent() 方法,即 boundObject = ((OpaqueReference)boundObject).getReferent(name, ctx);

正如上方提到的 ForeignOpaqueReference 类实现了 OpaqueReference 接口,因此会调用该类中的 getReferent() 方法,导致反序列化代码执行漏洞。

package weblogic.jndi.internal;
public final class WLNamingManager {
public static Object getObjectInstance(Object boundObject, Name name, Context ctx, Hashtable env) throws NamingException {
if (boundObject instanceof ClassTypeOpaqueReference) {
......
} else if (boundObject instanceof OpaqueReference) {
boundObject = ((OpaqueReference)boundObject).getReferent(name, ctx);
} else if (boundObject instanceof LinkRef) {
...
}
}
}

与CVE-2023-21931漏洞原理相同,CVE-2023-21839也是在反序列化过程中没有进行恶意操作,而是完成反序列化过程后执行了漏洞类ForeignOpaqueReferencegetReferent()方法中的lookup()才触发的漏洞。

在GOBY中,我们已经集成了CVE-2023-21839漏洞,并添加了回显以及反弹Shell的功能。以下是演示效果:

CVE-2023-21931

  • 2022年8月12日 漏洞提交官方

  • 2022年8月19日 漏洞官方确认

  • 2023年4月18日 漏洞官方修复

CVE-2023-21839

  • 2022年7月31日 漏洞提交官方

  • 2022年8月5日 漏洞官方确认

  • 2023年1月16日 漏洞官方修复

Vulfocus weblogic 环境

docker pull vulfocus/vcpe-1.0-a-oracle-weblogic:12.2.1.2.0-jdk-release
docker pull vulfocus/vcpe-1.0-a-oracle-weblogic:12.2.1.1.0-jdk-release
docker pull vulfocus/vcpe-1.0-a-oracle-weblogic:12.2.1.3.0-jdk-release
docker pull vulfocus/vcpe-1.0-a-oracle-weblogic:12.2.1.4.0-jdk-release
docker pull vulfocus/vcpe-1.0-a-oracle-weblogic:12.2.1.0.0-jdk-release
docker pull vulfocus/vcpe-1.0-a-oracle-weblogic:14.1.1.0.0-jdk-release
docker pull vulfocus/vcpe-1.0-a-oracle-weblogic:12.1.2.0.0-jdk-release
docker pull vulfocus/vcpe-1.0-a-oracle-weblogic:12.1.3.0.0-jdk-release
docker pull vulfocus/vcpe-1.0-a-oracle-weblogic:10.3.6.0-jdk-release

及时安装相关漏洞补丁

http://rui0.cn/archives/1338

https://github.com/Ruil1n/after-deserialization-attack

来源:https://xz.aliyun.com/t/12459

声明:⽂中所涉及的技术、思路和⼯具仅供以安全为⽬的的学习交流使⽤,任何⼈不得将其⽤于⾮法⽤途以及盈利等⽬的,否则后果⾃⾏承担。所有渗透都需获取授权

@
学习更多渗透技能!体验靶场实战练习

hack视频资料及工具

(部分展示)

往期推荐

【精选】SRC快速入门+上分小秘籍+实战指南

爬取免费代理,拥有自己的代理池

漏洞挖掘|密码找回中的套路

渗透测试岗位面试题(重点:渗透思路)

漏洞挖掘 | 通用型漏洞挖掘思路技巧

干货|列了几种均能过安全狗的方法!

一名大学生的黑客成长史到入狱的自述

攻防演练|红队手段之将蓝队逼到关站!

巧用FOFA挖到你的第一个漏洞

看到这里了,点个“赞”、“再看”吧

文章来源: http://mp.weixin.qq.com/s?__biz=MzI4NTcxMjQ1MA==&mid=2247594167&idx=1&sn=d99d21abd561a7666784a9504b6e656b&chksm=ebeb399adc9cb08cab15b0c0b82cc1f4028c8837be5d32ffcf0501264ca9e763c1b8f1b3ffda#rd
如有侵权请联系:admin#unsafe.sh