作者:Skay@QAX A-TEAM
原文鏈接:https://mp.weixin.qq.com/s/m7WLwJX-566WQ29Tuv7dtg

一、調試環境

https://archive.apache.org/dist/druid/0.20.1/

這里嘗試了幾種常規的調試方法都不行,然后看到conf目錄下存在jvm.config,一搜好多,因為我們的啟動腳本為start-micro-quickstart,所以最后范圍鎖定在這幾個

圖片

一開始踩了一個坑,D:\java\druid\druid run\apache-druid-0.20.0\conf\druid\single-server\micro-quickstart\router\runtime.properties 中我看到了8888端口,這恰恰也是我們的web服務端口,下意識就改了這個jvm.config

圖片

某些斷點可以停住,但是我們漏洞出發點并不行,后來經過Smi1e師傅的提示,需要我改錯了

圖片

在此感謝~

二、漏洞分析

往上分析文章就只有阿里發出的,拿出上學的時候做閱讀理解的本事,使勁看吧....

1.定位JavaScriptDimFIlter

阿里爸爸文章一開始就提出了利用的關鍵類JavaScriptDimFilter,反思一下,因為對Java相關的JavaScript知識儲備幾乎是0,看到fasterxml就一心想著反序列化了.........

這里簡單提一下Javascript,Druid支持在運行時動態注入JavaScript,且不會在沙箱中執行Java腳本,因此它們具有對計算機的完全訪問權限。因此,JavaScript函數允許用戶在druid進程內執行任意代碼。因此,默認情況下,JavaScript是禁用的。但是,在開發/登臺環境或受保護的生產環境中,可以通過設置configuration屬性 來啟用它們druid.javascript.enabled = true。

這里提到了關于漏洞的關鍵點:druid.javascript.enabled,留個坑,稍后提到。

2.關于JsonCreator注解、JsonProperty注解、以及CreatorProperty類型

文章中提到了兩個注解,以及一個類(參數類型),這里需要去補一下Jackson的一些知識了

@JasonCreator

該注解用在對象的反序列時指定特定的構造函數或者工廠方法。在反序列化時,Jackson默認會調用對象的無參構造函數,如果我們不定義任何構造函數,Jvm會負責生成默認的無參構造函數。但是如果我們定義了構造函數,并且沒有提供無參構造函數時,Jackson會報錯 再回到@JsonCreator注解,其作用就是,指定對象反序列化時的構造函數或者工廠方法,如果默認構造函數無法滿足需求,或者說我們需要在構造對象時做一些特殊邏輯,可以使用該注解。該注解需要搭配@JsonProperty使用

@JsonProperty

此注解作用于屬性上,作用是把該屬性的名稱序列化成另一個自己想要的名稱 對屬性名進行重命名,在java里我們墨守規定駝峰命名,但是在一些特殊的場合下,比如數據庫是下劃線等,再此我們就可以進行映射 對屬性名稱重命名,比如在很多場景下Java對象的屬性是按照規范的駝峰書寫,但在數據庫設計時使用的是下劃線連接方式,此處在進行映射的時候

有了對注解的理解,再來看這句話,以及JavaScriptDimFilter的構造函數

圖片

圖片

JavaScriptDimFilter的構造函數是用JasonCreator修飾的,也就說JavaScriptDimFilter這個類在反序列化(這里指的是從Json數據轉化為對象)時,Jackson會調用這個構造方法,且由于dimesion、function、extractionFn、filterTuning都有@JasonProperty注解修飾,Jackson在在反序列化處理解析到JavaScriptDimFilter時,都會被封裝為CreatorProterty類型,而對于沒有被標記@JasonProperty的config參數,會創建一個name為””的CreatorProperty

圖片

跟到這里提出了一個疑問,Jackson是怎樣將org.apache.druid.js.JavaScriptConfig注入到里面的?留坑,稍后回答。

圖片

3.Jackson解析用戶輸入

(1) Jersey的初始配置注入部分

1.HTTP Server端采用的是Jersey框架,所有的配置信息都由Guice框架在啟動的時候進行綁定注入,比如利用的JavaScriptConfig,初始化的時候讀取配置文件中的druid.javascript.enabled綁定到JavaScriptConfig的enabled field,這部分是非本地用戶不可控的。

對應了上文提到的druid.javascript.enabled,我嘗試在druid中的配置文件找這個開關的配置,反編譯后全局搜javascript關鍵字都沒找到,后來請教了下Litch1師傅,說這個是默認配置,沒有具體去跟,具體可以看下有個test測試里有這部分:

圖片

(2) Jackson獲取對應的creatorProperty(JavaScriptConfig)

文中直接定位到了com.fasterxml.jackson.databind.deser.BeanDeserializer#_deserializeUsingPropertyBased方法

會拿解析到的json串中的“鍵名”去查找當前解析對象中對應的creatorProperty,這步對應的是findCreatorProperty方法,findCreatorProperty方法會去_propertyLookup 這個HashMap中查找”鍵名”對應的屬性,在_propertyLookup中可以看到其中沒有用JsonProperty注釋修飾的JavaScriptConfig的鍵為””,要是json串中的鍵也為””,就能匹配上,取出JavaScriptConfig對應的creatorProperty

跟著文章將視線集中到com.fasterxml.jackson.databind.deser.impl.PropertyBasedCreator#findCreatorProperty(java.lang.String)

圖片

可以看到它在一個for循環中,for循環遍歷了p(JsonParser,這里稍微不準確的理解為存儲了待處理的Json數據),按照Json層級結構一層一層的處理Json數據,因為payload較長,快進到“”處理邏輯,從P中取到propName,然后進入findCreatorProperty

圖片

this._propertyLookup是個數組,直接取到我們想要的JavaScriptConfig對應的creatorProperty

圖片

還是之前留的坑,這個Hashmap是怎么初始化的?Jackson是怎樣將org.apache.druid.js.JavaScriptConfig注入到里面的?這里仔細跟一下

圖片

這個this,也就是creator

圖片

圖片

這里仔細跟下調用棧跳到上一步

deserializeFromObjectUsingNonDefault:1287, BeanDeserializerBase,Hashmap被存在了((BeanDeserializer)this)._propertyBasedCreator中

圖片

再往上,deserializeFromObject:326, BeanDeserializer 還是this._propertyBasedCreator,也就是BeanDeserializer的屬性

圖片

一直向上跟進,看到了BeanDeserializer調用deserialize方法

可以看到這里的deser中已經初始化完畢了_propertyLookup Hashmap

圖片

再去看deser的初始化情況

圖片

其實跟到這里就想停了,因為payload里我們給的type是javascript,反序列化時會Jackson會解析到相應的實體類也就是JavaScriptDimFilter

圖片

繼續走跟到com.fasterxml.jackson.databind.jsontype.impl.TypeDeserializerBase#_findDeserializer中

圖片

經過一層層的變量傳遞,來到了deserializeTypedFromObject:97, AsPropertyTypeDeserializer

圖片

deserialize:527, SettableBeanProperty 這時這個hashmap 被賦值到了SettableBeanProperty的_valueTypeDeserializer參數上

圖片

然后向前追蹤SettableBeanProperty,最終又回到了BeanDeserializer

圖片

可以看到creatorProp通過findCreatorProperty中獲得

圖片

又回來了.....這時候就懵逼了一會兒,不過感謝idea

圖片

_deserializeUsingPropertyBased:417, BeanDeserializer 被調用了四次,回頭看下我們的payload Json數據是四層,嗯,對上了....大概是這個樣子的吧.....這里有點懵

這里放一下部分調用棧吧,

_findDeserializer:198, TypeDeserializerBase (com.fasterxml.jackson.databind.jsontype.impl)
_deserializeTypedForId:113, AsPropertyTypeDeserializer (com.fasterxml.jackson.databind.jsontype.impl)
deserializeTypedFromObject:97, AsPropertyTypeDeserializer (com.fasterxml.jackson.databind.jsontype.impl)
deserializeWithType:254, AbstractDeserializer (com.fasterxml.jackson.databind.deser)
deserialize:527, SettableBeanProperty (com.fasterxml.jackson.databind.deser)
_deserializeWithErrorWrapping:528, BeanDeserializer (com.fasterxml.jackson.databind.deser)
_deserializeUsingPropertyBased:417, BeanDeserializer (com.fasterxml.jackson.databind.deser) [4]
deserializeFromObjectUsingNonDefault:1287, BeanDeserializerBase (com.fasterxml.jackson.databind.deser)
deserializeFromObject:326, BeanDeserializer (com.fasterxml.jackson.databind.deser)
deserialize:159, BeanDeserializer (com.fasterxml.jackson.databind.deser)
deserialize:530, SettableBeanProperty (com.fasterxml.jackson.databind.deser)
_deserializeWithErrorWrapping:528, BeanDeserializer (com.fasterxml.jackson.databind.deser)
_deserializeUsingPropertyBased:417, BeanDeserializer (com.fasterxml.jackson.databind.deser) [3]
deserializeFromObjectUsingNonDefault:1287, BeanDeserializerBase (com.fasterxml.jackson.databind.deser)
deserializeFromObject:326, BeanDeserializer (com.fasterxml.jackson.databind.deser)
deserialize:159, BeanDeserializer (com.fasterxml.jackson.databind.deser)
deserialize:530, SettableBeanProperty (com.fasterxml.jackson.databind.deser)
_deserializeWithErrorWrapping:528, BeanDeserializer (com.fasterxml.jackson.databind.deser)
_deserializeUsingPropertyBased:417, BeanDeserializer (com.fasterxml.jackson.databind.deser) [2]
deserializeFromObjectUsingNonDefault:1287, BeanDeserializerBase (com.fasterxml.jackson.databind.deser)
deserializeFromObject:326, BeanDeserializer (com.fasterxml.jackson.databind.deser)
deserialize:159, BeanDeserializer (com.fasterxml.jackson.databind.deser)
deserialize:530, SettableBeanProperty (com.fasterxml.jackson.databind.deser)
_deserializeWithErrorWrapping:528, BeanDeserializer (com.fasterxml.jackson.databind.deser)
_deserializeUsingPropertyBased:417, BeanDeserializer (com.fasterxml.jackson.databind.deser) [1]
deserializeFromObjectUsingNonDefault:1287, BeanDeserializerBase (com.fasterxml.jackson.databind.deser)
deserializeFromObject:326, BeanDeserializer (com.fasterxml.jackson.databind.deser)
_deserializeOther:194, BeanDeserializer (com.fasterxml.jackson.databind.deser)
deserialize:161, BeanDeserializer (com.fasterxml.jackson.databind.deser)
_deserializeTypedForId:130, AsPropertyTypeDeserializer (com.fasterxml.jackson.databind.jsontype.impl)
deserializeTypedFromObject:97, AsPropertyTypeDeserializer (com.fasterxml.jackson.databind.jsontype.impl)
deserializeWithType:254, AbstractDeserializer (com.fasterxml.jackson.databind.deser)
deserialize:68, TypeWrappedDeserializer (com.fasterxml.jackson.databind.deser.impl)
_bind:1682, ObjectReader (com.fasterxml.jackson.databind)
readValue:977, ObjectReader (com.fasterxml.jackson.databind)
readFrom:814, ProviderBase (com.fasterxml.jackson.jaxrs.base)
getEntity:490, ContainerRequest (com.sun.jersey.spi.container)
getValue:123, EntityParamDispatchProvider$EntityInjectable (com.sun.jersey.server.impl.model.method.dispatch)
getInjectableValues:86, InjectableValuesProvider 

(3) 反序列化相應參數

拿到對應的creatorProperty之后就會將用戶輸入的json串中這個鍵對應的根據類型去反序列相應的參數,

圖片

(4) 觸發漏洞

最后漏洞的利用點就是利用config為true之后繞過了對于config的檢查

圖片

然后進行JavaScript的執行。

三、總結一下

這個漏洞主要就是根據Jackson解析特性(解析name為""時)會將value值綁定到對象(JavaScriptDimFilter,type為javascript時指定的)的對應參數(config)上,造成JavaScriptDimFilter中function屬性中的javascript代碼被執行。

四、補丁分析

最新版本payload會報錯

圖片

官方修復

圖片

看下調試過程this._propertyLookup hashmap中只剩下了四個

圖片

直接干掉了""對應的解析,這就阻斷了JavaScriptConfig對應的creatorProperty生成,hashmap中將不存在JavaScriptConfig,后面的鏈也就斷了.....無法打開JavaScript執行開關。

其實問了下洞主,說實際上還應該跟下具體Jackson執行邏輯具體是怎么修復的,但是那個遞歸搞得我太頭疼了,暫時先這樣吧....

五、參考鏈接

https://mp.weixin.qq.com/s/McAoLfyf_tgFIfGTAoRCiw

https://druid.apache.org/docs/0.19.0/tutorials/index.html

https://blog.csdn.net/u010900754/article/details/105859959

PS:感謝Litch1 和 Smi1e 指點....wtcl


Paper 本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.bjnorthway.com/1481/