天天看點

CVE-2017-9805:Struts2 REST插件遠端執行指令漏洞(S2-052) 分析報告

CVE-2017-9805:Struts2 REST插件遠端執行指令漏洞(S2-052) 分析報告

一. 漏洞概述

2017年9月5日,Apache Struts 2官方釋出一個嚴重級别的安全漏洞公告,該漏洞由國外安全研究組織lgtm.com的安全研究人員發現,漏洞編号為CVE-2017-9805(S2-052),在一定條件下,攻擊者可以利用該漏洞遠端發送精心構造的惡意資料包,擷取業務資料或伺服器權限,存在高安全風險。

二. 漏洞基本資訊

漏洞編号:

CVE-2017-9805

漏洞名稱:

Struts2 REST插件遠端執行指令漏洞(S2-052)

官方評級: **

嚴重

**漏洞描述:

當Struts2使用REST插件使用XStream的執行個體xstreamhandler處理反序列化XML有效載荷時沒有進行任何過濾,可以導緻遠端執行代碼,攻擊者可以利用該漏洞構造惡意的XML内容擷取伺服器權限。

漏洞利用條件和方式:

利用條件:使用REST插件并在受影響版本範圍内。

利用方式:攻擊者建構惡意資料包遠端利用。

漏洞影響範圍:

Struts 2.3.x全系版本(根據實際測試,2.3版本也存在該漏洞)

Struts 2.5 - Struts 2.5.12

三. 漏洞詳細分析資訊

本次Struts2漏洞是因為它的一個REST插件struts2-rest-plugin.jar用到了XStreamHandler這個類,這個類對http請求中content-type是application/xml的,調用XStream進行處理,這裡先看一下污點傳入,如圖:

CVE-2017-9805:Struts2 REST插件遠端執行指令漏洞(S2-052) 分析報告
CVE-2017-9805:Struts2 REST插件遠端執行指令漏洞(S2-052) 分析報告

然而漏洞真正存在域XStream中,觸發的根本在于javax.imageio.spi.FilterIterator類的next()會調用FilterIteratorFilter的filter(),然後javax.imageio.ImageIOContainsFilter的filter()方法中會用反射調用java.lang.ProcessBuilder().start()

先說一下利用代碼, 如圖所示

CVE-2017-9805:Struts2 REST插件遠端執行指令漏洞(S2-052) 分析報告

之前github已經公開利用代碼,位址https://github.com/mbechler/marshalsec,上圖代碼隻不過是他的exp當中的一個payload而已,這裡我詳細分析一下,主要是利用javax.imageio.ImageIO$ContainsFilter這個内部類,我們先看下代碼,如圖:

CVE-2017-9805:Struts2 REST插件遠端執行指令漏洞(S2-052) 分析報告

然後我們再來看利用代碼,如圖

CVE-2017-9805:Struts2 REST插件遠端執行指令漏洞(S2-052) 分析報告
CVE-2017-9805:Struts2 REST插件遠端執行指令漏洞(S2-052) 分析報告

這裡用無參的constructor去newInstance對象,生成空對象,然後再用反射去填充對應屬性,實際上這裡就是對應xml中的每個dom屬性,根據代碼邏輯我們可以看出,這裡層層封裝最終放到nativeString對象的value屬性裡,然後繼續跟蹤代碼

CVE-2017-9805:Struts2 REST插件遠端執行指令漏洞(S2-052) 分析報告

最終将上面NativeString的對象放到了HashMap裡,

CVE-2017-9805:Struts2 REST插件遠端執行指令漏洞(S2-052) 分析報告

最後對上面return的那個hashMap做toXML序列化,然後就有了今天公開的exploit。

下面分析漏洞觸發流程,漏洞觸發就是fromXML重組對象的過程了,如圖

CVE-2017-9805:Struts2 REST插件遠端執行指令漏洞(S2-052) 分析報告

XStream反序列化的邏輯,實際上是解析XML DOM重組對象的一個過程,如圖:

CVE-2017-9805:Struts2 REST插件遠端執行指令漏洞(S2-052) 分析報告

當解析到jdk.nashorn.internal.objects.NativeString這個類的時候,漏洞觸發,先看下此時的調用棧,如圖

CVE-2017-9805:Struts2 REST插件遠端執行指令漏洞(S2-052) 分析報告

這裡我們看到了熟悉的hashCode,這根groovy的反序列化利用類觸發邏輯類似。因為exp代碼中我們最終将NativeString對象最終放到了hashMap裡然後對hashMap進行序列化,是以當反序列化重組對象的時候,肯定會觸發hashCode邏輯。繼續跟蹤,這裡NativeString和Base64Data都屬于java未公開的代碼,官方未提供源碼,不過我們可以參考openjdk的源碼,如圖,先看NativeString,如圖

CVE-2017-9805:Struts2 REST插件遠端執行指令漏洞(S2-052) 分析報告

這裡value是前面封裝的Base64Data的對象,後面進入Base64Data的邏輯,如圖:

CVE-2017-9805:Struts2 REST插件遠端執行指令漏洞(S2-052) 分析報告

這裡對應依次解析xml中的dataHandler、XmlDataSource的對象,從中取出CipherInputStream的對象,同理依次解析,最終在重組javax.imageio.spi.FilterIterator對象的時候觸發漏洞,這裡看一下利用代碼,如圖:

CVE-2017-9805:Struts2 REST插件遠端執行指令漏洞(S2-052) 分析報告
CVE-2017-9805:Struts2 REST插件遠端執行指令漏洞(S2-052) 分析報告

這裡cfCons.newInstance(ProcessBuilder.class.getMethod(“start”), “foo”)被設定為FilterIterator的filter,因為javax.imageio.spi.FilterIterator類的next()會調用FilterIteratorFilter的filter()函數,而此時FilterIteratorFilter正是javax.imageio.ImageIOContainsFilter,這裡我們在javax.imageio.ImageIOContainsFilter的filter()下斷,代碼如圖

CVE-2017-9805:Struts2 REST插件遠端執行指令漏洞(S2-052) 分析報告

這裡的method是正是ProcessBuilder().start()方法,此時調用棧如圖:

CVE-2017-9805:Struts2 REST插件遠端執行指令漏洞(S2-052) 分析報告

最終觸發成功,漏洞複現如下圖:

CVE-2017-9805:Struts2 REST插件遠端執行指令漏洞(S2-052) 分析報告

四. 分析總結

我們回顧Struts2 釋出的安全公告,應該來說是目前Java web架構裡面存在安全最多的,運維人員和開發人員已經“見怪不怪”,本次官方漏洞公告對外發出受影響版本為2.5.X全系,但是我們在實際測試過程發現。2.3.X全系版本同樣存在此漏洞。

CVE-2017-9805:Struts2 REST插件遠端執行指令漏洞(S2-052) 分析報告

作為安全運維人員和開發人員,我們需要做的就是快速擷取漏洞情報,快速響應和處置,把業務風險降到最低。

五. 如何檢測漏洞?

如果您是運維人員或開發人員,建議您盡快關注并資産,您可以檢查使用了REST插件Struts版本是否在受影響範圍内,如果存在建議您盡快按照以下方式修複漏洞。

六. 如何規避漏洞風險?

1. 目前官方已經釋出更新檔,建議更新到 Apache Struts2.5.13、Apache Struts 2.3.34版本;

2. 阿裡雲雲盾WAF已釋出該漏洞規則,您也可以選用WAF對利用該漏洞的攻擊行為進行檢測和防禦,以規避安全風險。

七. 技術支援

最後感謝阿裡巴巴安全專家柏通的詳細的漏洞分析工作。

本文為雲栖社群原創内容,未經允許不得轉載,如需轉載請發送郵件至[email protected]