0x03CVE-2020-14644 weblogic iiop反序列化漏洞分析

CVE-2020-14644 weblogic iiop反序列化漏洞分析

参考:

0x1 https://my.oschina.net/u/4280983/blog/4477476

0x2 宽字节的推文

0x1 漏洞介绍

0x01 WebLogic组件

WebLogic是美国Oracle公司出品的一个application server,是一个基于JAVAEE架构的中间件,WebLogic是用于开发、集成、部署和管理大型分布式Web应用、网络应用和数据库应用的Java应用服务器,适用于云环境和传统环境的应用服务器组件。

0x02 漏洞简介

Oracle官方在2020年7月份发布的最新安全补丁中披露了此漏洞。此漏洞CVSS评分9.8,受影响的版本是12.2.1.3.0、12.2.1.4.0和14.1.1.0.0。该漏洞允许未经身份验证的攻击者通过 IIOP , T3 进行网络访问,攻击者成功攻击此漏洞可能导致Oracle WebLogic Server被接管。

0x2 漏洞分析

0x01 相关知识
JDK的classloader类和defineClass方法

​ 一个类在被使用之前,会经历class文件生成—>加载—>连接—>初始化等阶段。其中加载阶段主要完成三件事:1、通过类的全限定名来获取定义次类的二进制字节流,2、将该二进制字节流定义的静态数据结构转换成方法区的运行时数据结构,3、在内存中生成一个代表该类的Class对象,供外部通过该对象来获取类的元数据信息。

​ JDK中的ClassLoader类中有个方法是defineClass,可以根据类全限定名和类的字节数组,加载一个类并返回对应的Class对象到 JVM(Java Virtual Machine)中。

image-20201015110556771

如上图所示,如果参数’name’(类名)和’b’(类文件的二进制数据)可控,理论上我们可以加载任何类,我们可以通过该方法,构造符合class格式的bytes数组作为类去加载。(注意:1、一般情况下,通过defineClass加载的类不允许同名,2、一个类中的类名name和类字节数组b中的类名要对应)

javassist

​ javassist是一个开源的分析、编辑和创建Java字节码的类库。它提供了更高级的API,执行效率相对ASM较差,但无需掌握字节码指令的知识,对使用者要求较低。它直接使用java编码的形式,不需要了解虚拟机指令,就能动态改变类的结构,或者动态生成类。

0x02 漏洞代码分析

该漏洞的原理是在反序列化时,通过使用defineClass方法,加载恶意类。

关键类:com.tangosol.internal.util.invoke.RemoteConstructor

在RemoteConstructor类中,构造实例的代码如下:

image-20201014111222573

其中RemotableSupport类,可以理解为是coherence自定义的Classloader,在其中实现了defineClass,具有加载类的功能。查看其中的realize方法:

image-20201015110307308

先执行this.registerIfAbsent(constructor.getDefinition())方法

image-20201015110341915

RemotableSupport中定义了 Map 类型的 f_mapDefinitions 的变量充当缓存,每次调用realize时就会先在缓存中查找ClassDefinition。

执行完成后,调用getRemotableClass方法,获取clz。查看ClassDefinition类

image-20201014112030482

可以看到getRemotableClass返回m_clz,并且m_clz是用transient修饰的(transient的含义:将不需要序列化的属性前添加关键字transient,序列化对象的时候,这个属性就不会被序列化,最终变量为NULL)

所以clz为NULL。于是在realize方法中,就会进入if分支,调用defineClass加载恶意类字节码。

RemotableSupport 继承了ClassLoader,所以它的 defineClass 就是调用了父类的 defineClass来加载类。

需要注意的是BinClassName变量的命名,使用的是ClassIdentity类中的getName方法

image-20201015110410957

image-20201015110448486

ClassIdentity类中的构造方法是将clazz作为参数,然后提取该类的一些特征信息,如Basename等。其中getName函数可以简化为:getName() = package + “/“ + baseName + “$” + version

image-20201014105230694

image-20201014105430256

所以 ClassIdentity 中的字节数组 byte[] 中的对应的 Class 的类名必须为 package + “.” + baseName + “$” + version,否则可能会加载失败。

继续分析realize方法,加载类之后调用了createInstance方法

image-20201014152406910

aoArgs作为参数进行实例化对象,所以将恶意代码写在构造方法中,实例化之后就会执行恶意代码。

image-20201015110636109

所以只要构造一个带有包名类的恶意代码写进构造函数中,通过 javassist动态修改类名,将原类名加上 $ 和 version 值对应,通过iiop协议和反序列化发送给weblogic服务器,即可实现漏洞利用

0x3 漏洞复现

0x01 漏洞利用-弹计算器

image-20201015110723660

0x02 漏洞利用-信息回显

1、开启weblogic服务器

image-20201015110854978

2、查看weblogic服务器的网络配置信息

image-20201015110937437

3、在攻击机上,编写特制的恶意类(写入weblogic服务器的Ip和weblogic服务的端口以及攻击命令),打包jar包,运行,就可以直接获取到weblogic服务器的信息

image-20201109171158094

0x4 漏洞防护方案

0x01 官方方案:

官方已经针对此漏洞发布补丁,请受影响的用户参考以下链接安装补丁更新:

https://www.oracle.com/security-alerts/cpujul2020.html

0x02 临时解决方案:
关闭IIOP协议:

在WebLogic控制台中,选择“服务”->”AdminServer”->”协议”,取消“启用IIOP”的勾选。并重启WebLogic项目,使配置生效。

控制T3服务:

在WebLogic界面中选择安全-筛选器,在下方出现的界面中找到“连接筛选器”,在里面输入:security.net.ConnectionFilterImpl,然后在连接筛选器规则中输入:127.0.0.1 * * allow t3 t3s,0.0.0.0/0 * * deny t3 t3s。最后保存并重启服务器即可生效。