内容简介:这个漏洞最先由某厂商报给某银行,某银行再将该信息报给CNVD,后CNVD通告:国家信息安全漏洞共享平台(CNVD)收录了由中国民生银行股份有限公司报送的Oracle WebLogic wls9-async反序列化远程命令执行漏洞(CNVD-C-2019-48814),详情见链接:对于该漏洞,Oracle官方也破例了一回,提前发了某天接到工程线同事反馈的时候,说wls9-async存在远程代码执行漏洞,可能跟xmldecoder相关,因为一年前分析过该漏洞,详情
这个漏洞最先由某厂商报给某银行,某银行再将该信息报给CNVD,后CNVD通告:国家信息安全漏洞共享平台(CNVD)收录了由中国民生银行股份有限公司报送的Oracle WebLogic wls9-async反序列化远程命令执行漏洞(CNVD-C-2019-48814),详情见链接: cnvd
对于该漏洞,Oracle官方也破例了一回,提前发了 补丁 ,但是这个补丁只是针对10.3.6系列的,对于12版本系列还未披露补丁。所以还是请各位谨慎对待,勒索大军跃跃欲试。
分析
某天接到工程线同事反馈的时候,说wls9-async存在远程代码执行漏洞,可能跟xmldecoder相关,因为一年前分析过该漏洞,详情
:当时第一直觉判断不应该是这个地方再出问题,查了一下相关接口,怀疑是SOAPInvokeState.getClonedSOAPMessage
的问题,后来进一步分析把这个地方排除了。一天后另一个同事给了一个非常模糊的poc,也看不到利用链。隐隐约约看到class,void,这就确定了是xmldecoder的问题,于是聚焦于xmldecoder的补丁。仔细一对比WorkContextXmlInputAdapter的validate接口,还真是能被绕过。
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."); }
核心问题在判断void标签和array标签的时候不是遇到这两个标签就抛出异常,而是做了一个for循环遍历,当属性为空的就不会进这个遍历循环,也就不会抛出异常,当然就能直接绕过。像网上一大堆使用类似 <void class="xxx">
的假poc,假分析文章的时候,就感觉安全圈还真是个娱乐圈。此处笑脸。虽然能过了这个验证环节,但还是需要结合xml的知识来完成完整利用,比如父类,比如Soap定义等等。这也就是有些开发人员更容易构造出绕过的PoC。
知道了漏洞点,构造出PoC还是有挺多拦路虎的,我这里简单列列。
前置知识
-Dweblogic.webservice.verbose=* -Dweblogic.wsee.verbose=*
第一步打开调试开关。
weblogic 处理SOAP的方式:
有了这个SOAP请求处理框架图和日志,在发送测试请求的时候就能看出整个处理流程。部分日志如下:
| <WSEE>/_async/AsyncResponseService | -------------------------------------- <WSEE:23>Created<SoapMessageContext.<init>:48> <WSEE:23>Processing MessageContextInitHandler... <HandlerIterator.handleRequest:131> <WSEE:23>Processing ConnectionHandler... <HandlerIterator.handleRequest:131> ** S T A R T R E Q U E S T ** <WSEE:23>HTTP REQUEST POST /_async/AsyncResponseService ............................ <WSEE:23> from Header, got serverName='AdminServer'<ForwardingHandler.handleRequest:321> <WSEE:23>from LocalServerIdentity.getIdentity() got serverName='AdminServer'<ForwardingHandler.handleRequest:338> <WSEE:23>Processing SoapFaultHandler... <HandlerIterator.handleRequest:131> <WSEE:23>Processing AsyncResponseWsrmWsscHandler... <HandlerIterator.handleRequest:131> <WSEE:23>AsyncResponseWsrmWsscHandler.handleRequest<AsyncResponseWsrmWsscHandler.handleRequest:82> <WSEE:23>Processing InterceptionHandler... <HandlerIterator.handleRequest:131> <WSEE:23>Processing VersionRedirectHandler... <HandlerIterator.handleRequest:131> ...................
从上述日志就可以看出,所有的请求都会经过webservice注册的21个Handler来处理,我们把断点下在HandlerIterator.handleRequest,就能截取每一个handler。这种通用的责任链模式在web容器中还是很普遍的。具体的handler如下:
过程分析
第一步,针对于这个_async入口,我们把重点放在AsyncResponseHandler上,通过其handleRequest的代码
public boolean handleRequest(MessageContext var1){ if (var1 == null) { return true; } else if (!(var1 instanceof SOAPMessageContext)) { return true; } else { if (verbose) { Verbose.log("AsyncResponseHandler.handleRequest"); } String var2 = (String)var1.getProperty("weblogic.wsee.addressing.RelatesTo"); if (var2 == null) { return false; } else {
可以看出来必须设置RelatesTo属性,不然就直接返回了,不会进入后面反序列化的流程了。
ws
-address
,其格式为<wsa:MessageID> xs:anyURI </wsa:MessageID> <wsa:RelatesToRelationshipType="..."?>xs:anyURI</wsa:RelatesTo> <wsa:To>xs:anyURI</wsa:To> <wsa:Action>xs:anyURI</wsa:Action> <wsa:From>endpoint-reference</wsa:From> <wsa:ReplyTo>endpoint-reference</wsa:ReplyTo> <wsa:FaultTo>endpoint-reference</wsa:FaultTo>
所以poc中的第一步就是要加上ws-address的相关字段。
第二步就是在处理这个xml的过程中,必须删除多余的空格和换行,这是由于xmldecoder处理string标签的差异导致的。根据 StringElementHandler 的提示,可以看到
<string>description</string>is equivalent to {@code "description"} in Java code. The value of inner element is calculated before adding to the string using String#valueOf(Object) . Note that all characters are used including whitespaces (' ', '\t', '\n', '\r'). So the value of the element <string><true></string> is not equal to the value of the element <string> <true> </string>
也就是说紧凑和不紧凑是有本质区别的。不紧凑的话获取的内容是带换行和空格,这是我当时调试的时候死活找不到类的原因,坑了我不少时间。
第三步,过了前面那个坑就是找相应的payload去执行了,我给oracle提交了 com.bea.core.repackaged.springframework.context.support.FileSystemXmlApplicationContext
,无视jdk版本限制,目前公开的还有 oracle.toplink.internal.sessions.UnitOfWorkChangeSet
,这个类就是利用二次反序列化,二次反序列找的对象可包括
org.springframework.transaction.support.AbstractPlatformTransactionManager
,详情可见我以前的分析文档,二次反序列还可以包括jdk7u21,rmi等等gadget,其实第一层的入口也还有挺多类,鉴于这个漏洞的严重性和急迫性,这里不做详细阐述,所以在添加规则的时候一定不能依据利用类来添加规则,说不定明天就被绕过了。下面在ProcessBuilder上下一个断点,调用栈如下:
这个漏洞以前跟过,这里就不再详细阐述。详细跟踪过程参考以前的分析文档
修复方式
新的补丁将class加入了黑名单
} else if (qName.equalsIgnoreCase("class")) { throw new IllegalStateException("Invalid element qName:class");
这种方式对于漏洞研究人员来说还是挺好玩的。
详细的补丁如下:
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("class")) { throw new IllegalStateException("Invalid element qName:class"); } 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 i = 0; i < attributes.getLength(); ++i) { if (!"index".equalsIgnoreCase(attributes.getQName(i))) { throw new IllegalStateException("Invalid attribute for element void:" + attributes.getQName(i)); } } } if (qName.equalsIgnoreCase("array")) { String attClass = attributes.getValue("class"); if (attClass != null && !attClass.equalsIgnoreCase("byte")) { throw new IllegalStateException("The value of class attribute is not valid for array element."); } String lengthString = attributes.getValue("length"); if (lengthString != null) { try { int length = Integer.valueOf(lengthString); if (length >= WorkContextXmlInputAdapter.MAXARRAYLENGTH) { throw new IllegalStateException("Exceed array length limitation"); } this.overallarraylength += length; if (this.overallarraylength >= WorkContextXmlInputAdapter.OVERALLMAXARRAYLENGTH) { throw new IllegalStateException("Exceed over all array limitation."); } } catch (NumberFormatException var8) {
以上所述就是小编给大家介绍的《CVE-2019-2725 分析》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 使用动态分析技术分析 Java
- 使用动态分析技术分析 Java
- 案例分析:如何进行需求分析?
- 深度分析ConcurrentHashMap原理分析
- 如何分析“数据分析师”的岗位?
- EOS源码分析(3)案例分析
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
C语言名题精选百则技巧篇
冼镜光 / 机械工业出版社 / 2005-7 / 44.00元
《C语言名题精选百则》(技巧篇)收集了100则C语言程序设计题,共分9类。第一类比较简单,主要希望读者了解到《C语言名题精选百则》(技巧篇)的题目、解法与其他书籍之间的差异;第二至六类分别是关于数字、组合数学或离散数学、查找、排序、字符串等方面的题目;第七类列出了一些不太容易归类的题目,如Buffon丢针问题、Dijkstra的三色旗问题等;第八类则收录了一些有趣的、娱乐性的题目,如魔方阵等;第九......一起来看看 《C语言名题精选百则技巧篇》 这本书的介绍吧!