Weblogic CVE-2023-21931 漏洞挖掘技巧:后反序列化利用
字数 2023 2025-08-11 08:36:26
WebLogic 后反序列化漏洞分析与利用技术
1. 概述
WebLogic 反序列化漏洞近年来主要围绕反序列化触发点进行挖掘,但实际上还存在许多"后反序列化"漏洞点。这类漏洞在反序列化过程中无法实时利用,但可以通过后续操作完成稳定利用。
本文以 CVE-2023-21931 和 CVE-2023-21839 为例,详细分析"后反序列化漏洞"的利用思路和技术细节。
2. 后反序列化漏洞概念
2.1 传统反序列化漏洞
- 关注 readObject()、readResolve()、readExternal() 等反序列化方法
- 利用恶意序列化数据在反序列化过程中进行攻击
2.2 后反序列化漏洞
- 关注反序列化完成后的操作
- 在特定时机或执行特定操作后触发漏洞
- 常见触发点:bind()、rebind()、lookup()、lookupLink() 等方法
3. lookup() 方法触发流程分析
WebLogic 中 lookup() 方法的调用流程如下:
- 请求到达后,BasicServerRef.invoke() 解析传入数据
- 通过 _invoke() 方法,根据方法名 resolve_any 执行 resolve_any()
- resolve_any() 通过 resolveObject() 解析绑定命名
- resolveObject() 根据上下文调用 lookup()
- 经过 WLContextImpl、WLEventContextImpl、RootNamingNode、ServerNamingNode、BasicNamingNode 等一系列 lookup() 调用
- 最终在 BasicNamingNode.resolveObject() 中调用 WLNamingManager.getObjectInstance()
关键点:当传入 resolveObject() 的 obj 不是 NamingNode 实例且 mode=1 时,会调用 WLNamingManager.getObjectInstance()
4. CVE-2023-21931 漏洞分析
4.1 漏洞位置
- WLNamingManager.getObjectInstance() 方法
- 当 boundObject 是 LinkRef 实现类时触发
4.2 漏洞触发流程
- 调用 boundObject.getLinkName() 获取 linkAddrType
- 通过 InitialContext.lookup() 加载 linkAddrType 指定的远程 JNDI 地址
- 攻击者可控制 LinkRef 构造时的 JNDI 地址
4.3 关键代码
// WLNamingManager.getObjectInstance()
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) {...}
}
4.4 LinkRef 类分析
public class LinkRef extends Reference {
static final String linkAddrType = "LinkAddress";
public LinkRef(String linkName) {
super(linkClassName, new StringRefAddr(linkAddrType, linkName));
}
public String getLinkName() throws NamingException {
RefAddr addr = get(linkAddrType);
return (String)((StringRefAddr)addr).getContent();
}
}
4.5 利用特点
- rebind() 和 lookup() 的反序列化过程不执行恶意操作
- 反序列化完成后,通过 WLNamingManager.getObjectInstance() 的 lookup() 触发漏洞
- 可加载远程恶意 JNDI 地址
5. CVE-2023-21839 漏洞分析
5.1 漏洞位置
- ForeignOpaqueReference.getReferent() 方法
- ForeignOpaqueReference 实现了 OpaqueReference 接口
5.2 漏洞触发流程
- ForeignOpaqueReference 构造时接收 env 和 remoteJNDIName
- getReferent() 方法中执行 context.lookup(this.remoteJNDIName)
- 攻击者可控制 remoteJNDIName 指定的 JNDI 地址
5.3 关键代码
public class ForeignOpaqueReference implements OpaqueReference, Serializable {
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 = new InitialContext(properties);
Object retVal;
try {
retVal = context.lookup(this.remoteJNDIName); // 漏洞点
} finally {...}
return retVal;
}
}
5.4 触发路径
- WLNamingManager.getObjectInstance() 检测 boundObject 是否实现 OpaqueReference
- 调用 boundObject.getReferent(name, ctx)
- ForeignOpaqueReference.getReferent() 执行恶意 lookup()
6. 漏洞时间线
CVE-2023-21931
- 2022年8月12日:漏洞提交
- 2022年8月19日:官方确认
- 2023年4月18日:官方修复
CVE-2023-21839
- 2022年7月31日:漏洞提交
- 2022年8月5日:官方确认
- 2023年1月16日:官方修复
7. 研究环境搭建
可使用 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-j
8. 参考资源
- Java"后反序列化漏洞"利用思路 - Ruilin
- Ruil1n/after-deserialization-attack: Java After-Deserialization Attack
注:本文所述漏洞已在 Goby 安全工具中集成,支持扫描验证和漏洞利用。