在WebLogic官方发布的10月份安全补丁中,包含了由Venustech ADLab提交的CVE-2019-2890的修复。该漏洞通过T3协议发送恶意的反序列化数据绕过了Weblogic的黑名单,成功反序列化执行任意命令。通过官方公告可知,该漏洞的利用条件是需要认证。
Weblogic 10.3.6.0.0
Weblogic 12.1.3.0.0
Weblogic 12.2.1.3.0
下面以10.3.6.0作为分析版本。问题出现在PersistentContext
类上,通过查看继承关系我们知道PersistentContext
类实现了序列化接口Serializable
。
我们来看看它的readObject
方法,将ObjectInputStream
类对象var1
传入readSubject
方法。
跟进readSubject
方法发现,会先从var1
中读取反序列化数据当中的对象数据。然后调用EncryptionUtil.decrypt
方法进行解密,最后解密后的数据被用于反序列化为对象。
至此我们知道PersistenContext
序列化数据中还携带了其他对象反序列化后的加密数据。如果我们在序列化PersistentContext
时,将恶意对象反序列化数据先加密,然后writeObject
,就可以让其携带恶意对象,绕过Weblogic黑名单进行反序列化了。
根据以上思路,我们编写一个携带恶意对象的PersistenContext
类。只需修改下原来代码中的writeSubject
方法为如下,其中Poc.getObject()
就是我们的恶意对象。
在进行序列化之前我们要处理四个问题。第一个问题是创建PersistenContext对象报错。
这是因为PersistenContext
初始化时调用了SecurityServiceManager.isKernelIdentity()
进行内核身份判断。isKernelIdentity
方法无论如何都会抛出一个NotSupportedException
异常,导致我们序列化被终止。
我们可以将其注释掉
第二个问题是反序列化PersistenContext类会出现卡死现象。这是因为PersistenContext
等相关的类都会有一个AuthenticatedSubject
静态对象要初始化。
初始化时会进入到如下代码。
我们需要ceClient
变量为true
,否则会一直进循环执行ceSubjectManagerLock.wait()
进行等待,无法序列化!而ceClient
是从系统属性com.bea.core.internal.client
获取的,所以在序列化之前需要将该属性设置为true
。
第三个问题是恶意对象没有被加密。这是因为在调用EncryptionUtil.encrypt
方法加密时,会根据Kernel.isServer()
为true
时才会进行加密,否则返回原数据。
因此加密之前需要调用KernelStatus.setIsServer(true)
设置状态为true
。
第四个问题,加密时需要SerializedSystemIni.dat
文件。 我们需要目标服务器weblogic当前使用域下该文件放到我们poc的根目录。这也是官方将这个漏洞划分为需要认证的原因。
解决完这四个问题,就可以将PersistenContext
对象反序列化为文件了。最后通过t3协议发送反序列化数据给Weblogic,即可执行任意命令。
通过对比,发现最新补丁在反序列化时,使用WSFilteringObjectInputStream
对要反序列化的对象进行过滤。
WSFilteringObjectInputStream
实现了Weblogic下的过滤接口 FilteringObjectInputStream
。在其resolveClass
方法中,检查要反序列化的类是不是Subject
的子类,不是则会抛出一个非法类异常,反序列化终止!
这个漏洞需要满足以下两个条件,才能触发成功,较为鸡肋。
Weblogic开启t3协议
可以获取到SerializedSystemIni.dat
文件
但是在实际环境中,如果部署在weblogic的站点存在任意文件下载
或者任意文件读取
,那么配合上该漏洞即可执行任意命令。
Oracle Critical Patch Update Advisory - October 2019