weblogic CVE-2020-2963、CNVD-2020-23019 反序列化漏洞分析与复现
字数 1668 2025-08-15 21:32:22
WebLogic CVE-2020-2963 和 CNVD-2020-23019 反序列化漏洞分析与复现
漏洞概述
这两个漏洞都是2020年5月发布的补丁修复的反序列化漏洞,存在于Oracle WebLogic Server中:
- CNVD-2020-23019 - 影响
SOAPInvokeState类的反序列化过程 - CVE-2020-2963 - 影响
WlsSSLAdapter类的反序列化过程
这两个漏洞都涉及不安全的反序列化操作,可能导致远程代码执行。
漏洞原理分析
反序列化防御机制
在WebLogic中,默认通过以下机制防御反序列化漏洞:
- 使用
FilterInputStream而非ObjectInputStream进行反序列化 FilterInputStream会检查反序列化的类中是否存在可利用的Gadget- 通过T3协议反序列化时,默认参数为
FilterInputStream
漏洞产生的原因是某些类的readObject或readExternal方法中直接使用了ObjectInputStream,绕过了安全机制。
CNVD-2020-23019 (SOAPInvokeState)
漏洞点在SOAPInvokeState类的readExternal方法中:
if ((flags & 1) != 0) {
try {
len = in.readInt();
byte[] bytes = new byte[len];
in.readFully(bytes);
bytes = EncryptionUtil.decrypt(bytes);
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
ObjectInputStream in2 = new ObjectInputStream(bais); // 漏洞点
this.subject = (AuthenticatedSubject)in2.readObject();
} catch (Exception var13) {
(new NonCatalogLogger("WebServices")).warning("Couldn't completely read SOAPInvokeState object", var13);
}
}
触发条件:
- 实例化的
SOAPInvokeState对象中包含subject字段 - 通过
writeExternal方法写入序列化数据时,如果subject != null,会触发上述流程
if (this.subject != null) {
ByteArrayOutputStream var12 = new ByteArrayOutputStream();
ObjectOutputStream var13 = new ObjectOutputStream(var12);
var13.writeObject(this.subject);
var13.flush();
byte[] var5 = var12.toByteArray();
var5 = EncryptionUtil.encrypt(var5);
var1.writeInt(var5.length);
var1.write(var5);
}
CVE-2020-2963 (WlsSSLAdapter)
漏洞点在WlsSSLAdapter类的readEncryptedField方法中:
private Object readEncryptedField(ObjectInputStream in) throws IOException, ClassNotFoundException {
int length = in.readInt();
if (length <= 0) {
return in.readObject();
} else {
byte[] bytes = new byte[length];
in.readFully(bytes);
bytes = EncryptionUtil.decrypt(bytes);
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
ObjectInputStream in2 = new ObjectInputStream(bais); // 漏洞点
return in2.readObject();
}
}
加密机制分析
加密过程有以下特点:
EncryptionUtil.encrypt会根据Kernel.isServer()决定是否加密- 如果为
true则加密,否则返回原数据 - 可通过
KernelStatus.setIsServer(true)设置状态
- 如果为
- 加密密钥来自
SerializedSystemIni.dat文件- 路径:
DomainDir.getRootDir() + "/security/SerializedSystemIni.dat" - 或:
DomainDir.getRootDir() + "/SerializedSystemIni.dat"
- 路径:
- 需要读取该文件才能正确加密/解密数据
漏洞利用条件
- 能够构造恶意序列化数据并通过T3/IIOP等协议发送到WebLogic
- 对于CNVD-2020-23019:
- 需要控制
SOAPInvokeState对象的subject字段
- 需要控制
- 对于CVE-2020-2963:
- 需要触发
readEncryptedField方法
- 需要触发
- 如果目标使用加密:
- 需要获取
SerializedSystemIni.dat文件 - 或绕过加密机制
- 需要获取
漏洞复现(POC)
CNVD-2020-23019 POC示例
BadAttributeValueExpException exp = null;
try {
exp = cve_2020_2555.getBadAttributeValueExpException();
} catch (Exception e) {
e.printStackTrace();
}
out2.writeObject(exp);
out2.flush();
byte[] bytes = baos.toByteArray();
bytes = EncryptionUtil.encrypt(bytes);
out.writeInt(bytes.length);
out.write(bytes);
利用步骤
- 构造恶意
SOAPInvokeState或WlsSSLAdapter对象 - 设置必要的字段触发反序列化流程
- 处理加密问题:
- 设置
KernelStatus.setIsServer(true)绕过加密 - 或获取
SerializedSystemIni.dat文件进行正确加密
- 设置
- 通过T3/IIOP协议发送恶意序列化数据
修复方案
- 应用Oracle官方补丁
- 补丁修改内容:
- 将
ObjectInputStream替换为FilterInputStream - 增加反序列化类检查
- 将
参考链接
- FortiGuard分析:
总结
这两个漏洞都是由于WebLogic中特定类的不安全反序列化操作导致的,利用条件相对苛刻但危害严重。防御此类漏洞的关键是确保所有反序列化操作都使用安全的FilterInputStream并实施严格的类检查机制。