一. 漏洞概述
2017年9月5日,Apache Struts 2官方發(fā)布一個(gè)嚴(yán)重級(jí)別的安全漏洞公告,該漏洞由國外安全研究組織lgtm.com的安全研究人員發(fā)現(xiàn),漏洞編號(hào)為CVE-2017-9805(S2-052),在一定條件下,攻擊者可以利用該漏洞遠(yuǎn)程發(fā)送精心構(gòu)造的惡意數(shù)據(jù)包,獲取業(yè)務(wù)數(shù)據(jù)或服務(wù)器權(quán)限,存在高安全風(fēng)險(xiǎn)。
二. 漏洞基本信息
漏洞編號(hào):
CVE-2017-9805
漏洞名稱:
Struts2 REST插件遠(yuǎn)程執(zhí)行命令漏洞(S2-052)
官方評(píng)級(jí): **
嚴(yán)重
**漏洞描述:
當(dāng)Struts2使用REST插件使用XStream的實(shí)例xstreamhandler處理反序列化XML有效載荷時(shí)沒有進(jìn)行任何過濾,可以導(dǎo)致遠(yuǎn)程執(zhí)行代碼,攻擊者可以利用該漏洞構(gòu)造惡意的XML內(nèi)容獲取服務(wù)器權(quán)限。
漏洞利用條件和方式:
利用條件:使用REST插件并在受影響版本范圍內(nèi)。
利用方式:攻擊者構(gòu)建惡意數(shù)據(jù)包遠(yuǎn)程利用。
漏洞影響范圍:
Struts 2.3.x全系版本(根據(jù)實(shí)際測(cè)試,2.3版本也存在該漏洞)
Struts 2.5 - Struts 2.5.12
三. 漏洞詳細(xì)分析信息
本次Struts2漏洞是因?yàn)樗囊粋€(gè)REST插件struts2-rest-plugin.jar用到了XStreamHandler這個(gè)類,這個(gè)類對(duì)http請(qǐng)求中content-type是application/xml的,調(diào)用XStream進(jìn)行處理,這里先看一下污點(diǎn)傳入,如圖:
然而漏洞真正存在域XStream中,觸發(fā)的根本在于javax.imageio.spi.FilterIterator類的next()會(huì)調(diào)用FilterIterator$Filter的filter(),然后javax.imageio.ImageIO$ContainsFilter的filter()方法中會(huì)用反射調(diào)用java.lang.ProcessBuilder().start()
先說一下利用代碼, 如圖所示
之前github已經(jīng)公開利用代碼,地址https://github.com/mbechler/marshalsec,上圖代碼只不過是他的exp當(dāng)中的一個(gè)payload而已,這里我詳細(xì)分析一下,主要是利用javax.imageio.ImageIO$ContainsFilter這個(gè)內(nèi)部類,我們先看下代碼,如圖:
然后我們?cè)賮砜蠢么a,如圖
這里用反射將java.lang.ProcessBuilder().start()設(shè)置進(jìn)入ContainsFilter對(duì)象里,以待后面漏洞觸發(fā)時(shí)調(diào)用
這里用無參的constructor去newInstance對(duì)象,生成空對(duì)象,然后再用反射去填充對(duì)應(yīng)屬性,實(shí)際上這里就是對(duì)應(yīng)xml中的每個(gè)dom屬性,根據(jù)代碼邏輯我們可以看出,這里層層封裝最終放到nativeString對(duì)象的value屬性里,然后繼續(xù)跟蹤代碼
最終將上面NativeString的對(duì)象放到了HashMap里,
最后對(duì)上面return的那個(gè)hashMap做toXML序列化,然后就有了今天公開的exploit。
下面分析漏洞觸發(fā)流程,漏洞觸發(fā)就是fromXML重組對(duì)象的過程了,如圖
XStream反序列化的邏輯,實(shí)際上是解析XML DOM重組對(duì)象的一個(gè)過程,如圖:
當(dāng)解析到j(luò)dk.nashorn.internal.objects.NativeString這個(gè)類的時(shí)候,漏洞觸發(fā),先看下此時(shí)的調(diào)用棧,如圖
這里我們看到了熟悉的hashCode,這根groovy的反序列化利用類觸發(fā)邏輯類似。因?yàn)閑xp代碼中我們最終將NativeString對(duì)象最終放到了hashMap里然后對(duì)hashMap進(jìn)行序列化,所以當(dāng)反序列化重組對(duì)象的時(shí)候,肯定會(huì)觸發(fā)hashCode邏輯。繼續(xù)跟蹤,這里NativeString和Base64Data都屬于java未公開的代碼,官方未提供源碼,不過我們可以參考o(jì)penjdk的源碼,如圖,先看NativeString,如圖
這里value是前面封裝的Base64Data的對(duì)象,后面進(jìn)入Base64Data的邏輯,如圖:
這里對(duì)應(yīng)依次解析xml中的dataHandler、XmlDataSource的對(duì)象,從中取出CipherInputStream的對(duì)象,同理依次解析,最終在重組javax.imageio.spi.FilterIterator對(duì)象的時(shí)候觸發(fā)漏洞,這里看一下利用代碼,如圖:
這里cfCons.newInstance(ProcessBuilder.class.getMethod("start"), "foo")被設(shè)置為FilterIterator的filter,因?yàn)閖avax.imageio.spi.FilterIterator類的next()會(huì)調(diào)用FilterIterator$Filter的filter()函數(shù),而此時(shí)FilterIterator$Filter正是javax.imageio.ImageIO$ContainsFilter,這里我們?cè)趈avax.imageio.ImageIO$ContainsFilter的filter()下斷,代碼如圖
這里的method是正是ProcessBuilder().start()方法,此時(shí)調(diào)用棧如圖:
最終觸發(fā)成功,漏洞復(fù)現(xiàn)如下圖:
四. 分析總結(jié)
我們回顧Struts2 發(fā)布的安全公告,應(yīng)該來說是當(dāng)前Java web框架里面存在安全最多的,運(yùn)維人員和開發(fā)人員已經(jīng)“見怪不怪”,本次官方漏洞公告對(duì)外發(fā)出受影響版本為2.5.X全系,但是我們?cè)趯?shí)際測(cè)試過程發(fā)現(xiàn)。2.3.X全系版本同樣存在此漏洞。
作為安全運(yùn)維人員和開發(fā)人員,我們需要做的就是快速獲取漏洞情報(bào),快速響應(yīng)和處置,把業(yè)務(wù)風(fēng)險(xiǎn)降到最低。
五. 如何檢測(cè)漏洞?
如果您是運(yùn)維人員或開發(fā)人員,建議您盡快關(guān)注并資產(chǎn),您可以檢查使用了REST插件Struts版本是否在受影響范圍內(nèi),如果存在建議您盡快按照以下方式修復(fù)漏洞。
六. 如何規(guī)避漏洞風(fēng)險(xiǎn)?
目前官方已經(jīng)發(fā)布補(bǔ)丁,建議升級(jí)到 Apache Struts2.5.13版本;
阿里云云盾WAF已發(fā)布該漏洞規(guī)則,您也可以選用WAF對(duì)利用該漏洞的攻擊行為進(jìn)行檢測(cè)和防御,以規(guī)避安全風(fēng)險(xiǎn)。
六. 參考信息
https://cwiki.apache.org/confluence/display/WW/S2-052
https://struts.apache.org/docs/s2-052.html
七. 技術(shù)支持
最后感謝阿里巴巴安全專家柏通的詳細(xì)的漏洞分析工作。