一步一步回顾分析攻防演习中的 WebLogic T3 反序列化 0day 漏洞 – 作者:奇安信代码卫士

一、前言

本次攻防演习期间,有人发现 Weblogic T3反序列化0day漏洞。攻击者可在原Jdk7u21 POC 基础上,加上 java.rmi.MarshalledObject 绕过黑名单,达到入侵目的,具体如下。

二、Jdk7u21的PoC分析

gadget 如下:

图片[1]-一步一步回顾分析攻防演习中的 WebLogic T3 反序列化 0day 漏洞 – 作者:奇安信代码卫士-安全小百科

1、分析第一部分利用链

Jdk7u21的第一部分利用链如下。

图片[2]-一步一步回顾分析攻防演习中的 WebLogic T3 反序列化 0day 漏洞 – 作者:奇安信代码卫士-安全小百科

在对 LinkedHashSet 反序列化过程中,会进入 HashSet.readObject() 函数,关键代码块如下。

图片[3]-一步一步回顾分析攻防演习中的 WebLogic T3 反序列化 0day 漏洞 – 作者:奇安信代码卫士-安全小百科

根据 POC 信息,可知该函数会依次读取 LinkedHashSet 的 templates 和proxy对象,并将它们加入 map中。为什么需要加载两个对象呢?继续进入map.put() 函数,如下。

图片[4]-一步一步回顾分析攻防演习中的 WebLogic T3 反序列化 0day 漏洞 – 作者:奇安信代码卫士-安全小百科

该函数会计算存储进map的第一个对象Templates的Hash值,进入hash(key),如下。

图片[5]-一步一步回顾分析攻防演习中的 WebLogic T3 反序列化 0day 漏洞 – 作者:奇安信代码卫士-安全小百科

程序会执行常规hash运算,注意,其中的 k.hashCode() 调用了系统函数;而如果构造动态代理,编写或寻找到合适代理类,则极有可能使多个存储进map的对象的hash值一致。返回至HashMap.put() 函数,继续分析,进入至indexFor(hash, table.length) 函数,如下。

图片[6]-一步一步回顾分析攻防演习中的 WebLogic T3 反序列化 0day 漏洞 – 作者:奇安信代码卫士-安全小百科

table对象的原定义代码是table[bucketIndex] = new Entry<>(hash, key, value, e),负责保存 map 中每个对象及 hash 值等信息。此函数没有保存对象信息功能,仅仅负责统计返回当前对象在 table 中的索引值。随后返回至HashMap.put() 函数。

随后,如当前对象不在 table 中,则不进入循环,而是进入 addEntry(hash, key, value, i); 且在此期间进入父类方法,最终当前对象被保存至 table 中,关键代码如下。

图片[7]-一步一步回顾分析攻防演习中的 WebLogic T3 反序列化 0day 漏洞 – 作者:奇安信代码卫士-安全小百科

保存完第一个对象后,程序返回到 HashSet.readObject() 方法,并在 map 中添加第二个对象。如第二个对象是代理对象,则其 hash 值可能与前一个对象的hash 值碰撞,从而有利于绕过代码的验证逻辑,便于未来开展入侵测试;如POC中存在第二个代理对象,则会继续进入 map.put()。

进入 hash(key),计算第二个代理对象的hash值,进入 HashMap.hash() 函数。

在 POC 中,第二个代理对象的代理类是 AnnotationInvocationHandler,因此执行 k.hashCode() 时,会首先进入 AnnotationInvocationHandler.invoke() 方法,如下。

图片[8]-一步一步回顾分析攻防演习中的 WebLogic T3 反序列化 0day 漏洞 – 作者:奇安信代码卫士-安全小百科

根据方法名进入this.hashCodeImpl();,相关的代码块如下。

图片[9]-一步一步回顾分析攻防演习中的 WebLogic T3 反序列化 0day 漏洞 – 作者:奇安信代码卫士-安全小百科

var3信息来自AnnotationInvocationHandler的memberValues成员变量:如var3 中只有一条map信息,且该map的key为”f5a5a608″而value是加入map的第一个对象,则经调试分析发现,此时会发生两个对象hash值碰撞的情况。返回至 HashMap.put() 继续分析。

在循环代码块中,存在关键比较逻辑,如下。

图片[10]-一步一步回顾分析攻防演习中的 WebLogic T3 反序列化 0day 漏洞 – 作者:奇安信代码卫士-安全小百科

该逻辑首先会比较两个对象的hash值是否相等:根据 PoC 可知两值相等,并且会执行至 key.equals(k)。k是第一个对象,key是第二个代理对象,则会执行代理类invoke()方法。POC中的代理类是AnnotationInvocationHandler,则进入AnnotationInvocationHandler.invoke(),随后再进入this.equalsImpl(var3[0]),如下。

图片[11]-一步一步回顾分析攻防演习中的 WebLogic T3 反序列化 0day 漏洞 – 作者:奇安信代码卫士-安全小百科

Var5表示代理类的第一个方法,var1 表示前述的第一个对象,type 成员变量必须是第一个成员变量。根据代码 var5.invoke(var1) 可知,此方法必须是无参的,而POC中代理类 AnnotationInvocationHandler 的第一个方法getOutputProperties() 符合要求,因此进入TemplatesImpl.getOutputProperties(),如下。

图片[12]-一步一步回顾分析攻防演习中的 WebLogic T3 反序列化 0day 漏洞 – 作者:奇安信代码卫士-安全小百科

总体而言,第一部分链需同时满足如下关键条件:

LinkedHashSet 需要依次加入类对象和一个代理对象,设法使两个对象存在hash 碰撞情况;

代理对象的代理类 AnnotationInvocationHandler 的第二个成员变量仅存储一个 map 结构数据,key 为”f5a5a608″,value 是第一个类对象;

代理类 AnnotationInvocationHandler 的 type 成员变量必须是第一个类对象可转化的类;以及

代理类的待利用方法需要是无参的。

2、分析第二部分利用链

Jdk7u21的第二部分利用链如下。

图片[13]-一步一步回顾分析攻防演习中的 WebLogic T3 反序列化 0day 漏洞 – 作者:奇安信代码卫士-安全小百科

会在创建TransformerImpl 类过程中调用 getTransletInstance() 函数,函数信息如下。

图片[14]-一步一步回顾分析攻防演习中的 WebLogic T3 反序列化 0day 漏洞 – 作者:奇安信代码卫士-安全小百科

从中可知 _name 变量不能为 null,否则程序中断;那么当 _class 变量为 null时,会调用defineTransletClasses()执行什么重要指令呢?进入defineTransletClasses(),如下。

图片[15]-一步一步回顾分析攻防演习中的 WebLogic T3 反序列化 0day 漏洞 – 作者:奇安信代码卫士-安全小百科图片[16]-一步一步回顾分析攻防演习中的 WebLogic T3 反序列化 0day 漏洞 – 作者:奇安信代码卫士-安全小百科

由此可知在当前情况下,_bytecodes 不能为 null,否则程序报错终止;随后调用 new TransletClassLoader(ObjectFactory.findClassLoader()) 加载信息,但具体可以加载什么呢?继续分析进入下面代码块。

图片[17]-一步一步回顾分析攻防演习中的 WebLogic T3 反序列化 0day 漏洞 – 作者:奇安信代码卫士-安全小百科

TransletClassLoader 继承自ClassLoader,主要功能包括根据字节码文件加载类的defineClass函数,因此这里成功创建并返回了TransletClassLoader类加载器。返回到defineTransletClasses()函数继续分析。

loader 即为创建的 TransletClassLoader 类加载器;_class 变量是自发创建的类数组,_auxClasses 变量是 hash 表;后续关键代码如下。

图片[18]-一步一步回顾分析攻防演习中的 WebLogic T3 反序列化 0day 漏洞 – 作者:奇安信代码卫士-安全小百科

在循环代码块中,采用loader加载 _bytecodes[i],说明 _bytecodes 变量是一个包含多个类的字节码数组;随后会将 _bytecodes[i] 的父类与ABSTRACT_TRANSLET(ABSTRACT_TRANSLET=”com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet”) 比较,相等则 _transletIndex 为i,否则将类信息保存至 _auxClasses 变量。循环完毕后,根据语句可知_transletIndex 不能小于0,否则程序报错中断。因此,_bytecodes 中至少有一个类的父类是 com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet。最终返回至 getTransletInstance() 函数继续分析,如下。

图片[19]-一步一步回顾分析攻防演习中的 WebLogic T3 反序列化 0day 漏洞 – 作者:奇安信代码卫士-安全小百科

_class 变量包含多个加载的类,如果_transletIndex 变量是这些类中父类为ABSTRACT_TRANSLET 的类索引号,则会顺利实例化此类对象;然而,如果在此类构造函数中加入恶意代码则达到恶意利用的目的。

一言以蔽之,攻击者可以构造一个TemplatesImpl类对象,关键要求:

其 _name 变量不能为 null;

_class=null;以及

_bytecodes 变量是字节码类数组,包含一个父类为com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet的恶意类。

当前,Jdk7u21 的 POC 符合要求。

三、MarshalledObject 分析

Weblogic 将上述调用链中的com.sun.org.apache.xalan.internal.xsltc.trax 加入黑名单后,库中的 TemplatesImpl 类等会被检测到,从而成功阻止 Jdk7u21的 PoC 遭入侵利用。新 0day 的 PoC主要应用了 MarshalledObject 类绕过黑名单的检测,利用过程和 Jdk7u21 PoC 类似:将 MarshalledObject 对象作为恶意类,在程序执行过程中调用到其 get() 方法,反序列化 objBytes 成员变量,而这一切只需预先在此成员变量中保存 Jdk7u21 PoC 序列化数据即可。

分析 MarshalledObject 类。符合要求的无参函数 get() 相关代码如下。

图片[20]-一步一步回顾分析攻防演习中的 WebLogic T3 反序列化 0day 漏洞 – 作者:奇安信代码卫士-安全小百科

objBytes 变量不能为 null,程序可保存序列化后数据的 objBytes 变量 private byte[] objBytes = null; 至字节数组缓冲区bin变量,随后采用读入MarshalledObjectInputStream 对象,最后进入 in.reaObject() 方法。

因此,可将序列化恶意类对象保存至 objBytes 变量,当程序执行至 get() 方法时,即会调用 readObject() 解析执行恶意类对象。

四、POC构造

团队成员设计实现的 PoC 如下。

图片[21]-一步一步回顾分析攻防演习中的 WebLogic T3 反序列化 0day 漏洞 – 作者:奇安信代码卫士-安全小百科

图片[22]-一步一步回顾分析攻防演习中的 WebLogic T3 反序列化 0day 漏洞 – 作者:奇安信代码卫士-安全小百科

图片[23]-一步一步回顾分析攻防演习中的 WebLogic T3 反序列化 0day 漏洞 – 作者:奇安信代码卫士-安全小百科图片[24]-一步一步回顾分析攻防演习中的 WebLogic T3 反序列化 0day 漏洞 – 作者:奇安信代码卫士-安全小百科

五、实验复现

在 JDK7u21、Weblogic12.1.3.0 上通过T3协议发送攻击脚本,成功在 tmp 文件夹创建文件,如下。

图片[25]-一步一步回顾分析攻防演习中的 WebLogic T3 反序列化 0day 漏洞 – 作者:奇安信代码卫士-安全小百科

EXP 如下:

图片[26]-一步一步回顾分析攻防演习中的 WebLogic T3 反序列化 0day 漏洞 – 作者:奇安信代码卫士-安全小百科

图片[27]-一步一步回顾分析攻防演习中的 WebLogic T3 反序列化 0day 漏洞 – 作者:奇安信代码卫士-安全小百科

图片[28]-一步一步回顾分析攻防演习中的 WebLogic T3 反序列化 0day 漏洞 – 作者:奇安信代码卫士-安全小百科

图片[29]-一步一步回顾分析攻防演习中的 WebLogic T3 反序列化 0day 漏洞 – 作者:奇安信代码卫士-安全小百科

图片[30]-一步一步回顾分析攻防演习中的 WebLogic T3 反序列化 0day 漏洞 – 作者:奇安信代码卫士-安全小百科图片[31]-一步一步回顾分析攻防演习中的 WebLogic T3 反序列化 0day 漏洞 – 作者:奇安信代码卫士-安全小百科

图片[32]-一步一步回顾分析攻防演习中的 WebLogic T3 反序列化 0day 漏洞 – 作者:奇安信代码卫士-安全小百科

六、补丁分析

最新的补丁从侧面修复了这一漏洞。补丁没有检测拦截MashalledObject类,而是在wlclient.jar中加入拦截类FilteringObjectInputStream并设置了白名单,从而拦截包含恶意类的LinkedHashSet类型数据,如下。

白名单:

图片[33]-一步一步回顾分析攻防演习中的 WebLogic T3 反序列化 0day 漏洞 – 作者:奇安信代码卫士-安全小百科

调用链:

图片[34]-一步一步回顾分析攻防演习中的 WebLogic T3 反序列化 0day 漏洞 – 作者:奇安信代码卫士-安全小百科

可知,在 FilteringObjectInputStream.validateReturnType 方法处中断程序,此方法如下。

图片[35]-一步一步回顾分析攻防演习中的 WebLogic T3 反序列化 0day 漏洞 – 作者:奇安信代码卫士-安全小百科

当输入的数据类型不在 expectedTypes 白名单列表中时,会抛出异常,并打印出当前输入数据类型不符的信息,如下。

图片[36]-一步一步回顾分析攻防演习中的 WebLogic T3 反序列化 0day 漏洞 – 作者:奇安信代码卫士-安全小百科

题图:Pixabay License

转载请注明“转自奇安信代码卫士 https://codesafe.qianxin.com”。

来源:freebuf.com 2021-04-27 18:35:04 by: 奇安信代码卫士

© 版权声明
THE END
喜欢就支持一下吧
点赞0
分享
评论 抢沙发

请登录后发表评论