Struts2漏洞分析之Ognl表达式特性引发的新思路
摘要
在Ognl表達式中,會將被括號“()”包含的變量內(nèi)容當(dāng)做Ognl表達式執(zhí)行。Ognl表達式的這一特性,引發(fā)出一種新的攻擊思路。通過將惡意代碼存儲到變量中,然后在調(diào)用Ognl表達式的函數(shù)中使用這個變量來執(zhí)行惡意的代碼,從而實現(xiàn)攻擊。
本文將會以CVE-2011-3923漏洞作為示例,描述這種利用思路的具體過程。但是,本文的內(nèi)容絕不僅僅局限于這個漏洞,在實際的審計過程中,這種思路可以用來發(fā)現(xiàn)很多類似的漏洞。
背景介紹與原理分析
這個漏洞和CVE-2010-1870很相似,都是是通過Ognl表達式執(zhí)行java,來達到遠程代碼執(zhí)行的效果。我們先來回顧下CVE-2010-1870漏洞,它是攻擊者通過get方法提交Ognl表達式,直接來調(diào)用java的靜態(tài)方法來實現(xiàn)代碼執(zhí)行。這個問題爆出來后,struts官方加強了對于用戶提交內(nèi)容的審核,禁止使用“#”、“\”等特殊字符作為參數(shù)提交。
那么這樣我們就沒有辦法遠程執(zhí)行Ognl表達式了嗎?當(dāng)然不,Ognl給我們提供了另一種執(zhí)行它的方法,我們來看下官方文檔中一部分的內(nèi)容:
Ognl表達式給我們提供了“#fack()”這樣調(diào)用上下文對象方法的功能,我們需要留意的是紅色文字,大概的意思如下:如果你想要調(diào)用上下文環(huán)境中對象的方法,可以使用“(fact)()”這種格式來書寫。
而在測試過程中發(fā)現(xiàn),(one)(two)這種形式的Ognl表達式,會先將one當(dāng)做另一個Ognl表達式先執(zhí)行一遍,然后再繼續(xù)他后面的工作。這樣的話,如果程序在調(diào)用某一可以執(zhí)行Ognl表達式的函數(shù)時,我們通過變量將惡意的表達式傳入,那么,struts所做的那些過濾便成為了一扇“透明的門”。
0x03 實例模擬與跟蹤
在正常的調(diào)用中,我們找到了setValue這個函數(shù),它的作用是根據(jù)Ognl表達式對目標進行賦值,在這個過程中Ognl表達式會執(zhí)行。而struts2中通過在繼承ActionSupport的類中,設(shè)置setter和getter方法,可以實現(xiàn)用戶通過get和post方法直接為私有成員變量賦值。這種方法便會用到setValue這個函數(shù)。下面我們來搭建一個這樣的類:
上面的這段代碼只是簡單的實現(xiàn)了接受參數(shù)“tang3”,并將它的內(nèi)容打印到控制臺中的功能。在跟蹤它的過程中發(fā)現(xiàn),用戶提交的參數(shù)時,會通過調(diào)用com.opensymphony.xwork2.interceptor.ParametersInterceptor這個類中的set Parameters方法來獲取參數(shù),而這個方法會調(diào)用setValue函數(shù),代碼如下:
if (acceptableName) {Object value = entry.getValue();try {[color=Red] stack.setValue(name, value);[/color]} catch (RuntimeException e) {注意紅色字體部分,name參數(shù)是Ognl表達式部分,value是被賦值的對象,而之前的CVE-2010-1870漏洞,也是通過這個函數(shù)執(zhí)行的Ognl表達式。下面我們來看下如何結(jié)合前面講到的內(nèi)容來讓這個函數(shù)執(zhí)行我們需要的Java代碼。
按照之前我們所說的Ognl表達式特性,我們應(yīng)該構(gòu)造這樣的url:
提交這樣的url后,web server將會做兩件事,第一,將Ognl表達式內(nèi)容存進了tang3變量中;第二,名為(tang3)(‘meh’)的http參數(shù)將會被當(dāng)做另一個Ognl表達式執(zhí)行,并且action屬性tang3將會從action中恢復(fù)內(nèi)容,即變成了()(‘meh’)。
因為http參數(shù)傳入到變量中會自動進行url解碼,那么我們便可以使用url編碼“#”這樣的特定字符,來繞過正則表達式的過濾。
在構(gòu)造語句中還需要注意的一點就是,我們要確保tang3屬性中的內(nèi)容先被執(zhí)行。所以這里需要一個小技巧,在提交參數(shù)時,使用z[(tang3)(‘meh’)]=1這種形式的參數(shù),可以確保tang3變量被首先執(zhí)行。下面我們構(gòu)造一條可以彈出計算器的url:
url編碼后:
/helloworld.action? tang3=%28%23context["xwork.MethodAccessor.denyMethodExecution"]%3D+new+java. lang.Boolean%28false%29,%20%23_memberAccess["allowStaticMethodAccess"]%3dtru e,% [email]20@java.lang.Runtime[/email]@getRuntime%28%29.exec%28%27calc%27%29%29 %28meh%29&z[%28tang3%29%28%27meh%27%29]=1效果如下圖:
從最下面的紅色框中,我們可以看出,控制臺打印出的tang3變量的內(nèi)容,就是我們剛才輸入的代碼。
總結(jié)
The regex pattern inside the ParameterInterceptor was changed to provide a more narrow space of acceptable parameter names.
Furthermore the new setParameter method provided by the value stack will allow no more eval expression inside the param names.
修復(fù)方法就是,進一步減少ParameterInterceptor中白名單包含的內(nèi)容,并且禁止參數(shù)名執(zhí)行正則表達式
【想學(xué)滲透嗎,想就點唄】
總結(jié)
以上是生活随笔為你收集整理的Struts2漏洞分析之Ognl表达式特性引发的新思路的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 渗透新手福利---xss到获取cooki
- 下一篇: 攻击面管理(ASM),企业攻击面管理实践