1. 程式人生 > >struts2 漏洞分析 及解決辦法

struts2 漏洞分析 及解決辦法

1.討論關於struts 安全問題。

2.黑客文化。

3.如何降低安全漏洞的出現。

4.忠告建議。

題記:

這篇文章本來很早應該和大家見面的,中間由於個人原因調整了系列文章釋出時間,實屬罪過。為了不誤導大眾文章中間講述的經歷想法實戰,均屬個人看法個人行為不代表任何團體及組織。觀看者請保留自己的想法觀點!歡迎各位熱愛程式設計的技術人員交流。廢話不多,開始正文。

1.討論關於struts安全問題。

最近各位都看到了各種關於struts安全問題的文章,及實戰演練,安全問題波及到了各種大小的網際網路站點(京東,電信,IBM,其中後兩個網站都是筆者請自嘗試,只是做友情檢測,並未做任何非法過激動作)。各個論壇相繼出現各種詆譭,謾罵關於struts安全的回覆。

對於以上的問題,個人奔著還原問題的本質,通過友情檢測IBM報名網站做實戰講述+個人測試Test,講述關於我們應該如何看待struts安全問題。

對於IBM報名網站這裡做必要解釋,並非刻意測試,而是今日公司安排報名培訓,上去結果發現該網站亦是struts架構,遂友情檢測。截止文章釋出之時已經郵件通知IBM運維。如下截圖為證。

截圖04

在正式解讀struts安全問題之前我們先來了解一下struts,其實在命名的時候都不知道改用struts還是struts2?有人會問題?為什麼?看官且慢慢聽我講,現在apache官方稱謂struts2,為何筆者又命名為struts呢?因為我們這裡討論 大家對struts安全的誤解和盲區,struts作為apache眾多專案的一個頂級專案,而struts2的前身就是struts,漏洞也是從struts開始暴露出來的,想必老一輩的coder應該用過struts,開始的時候就用struts2 了,截止前不久apache 官方對struts已經終結其生命了。各位可以到這裡觀摩(

http://struts.apache.org/

早在沒有使用struts之前,玩駭客的應該都知道有struts漏洞檢測工具,不錯!這個就是struts第一次出現安全漏洞問題,截止目前struts已經出現兩次安全漏洞!最近一次的安全描述(http://struts.apache.org/release/2.3.x/docs/s2-016.html

看完各種網路文章,評論,有人說這個漏洞5月份就提交apache處理了,但是漏洞大面積鋪開的時候是7月中旬,也就是apache公開安全漏洞的不久後!而得知的是在7月14日有人在部落格園快閃記憶體多次釋出,而引起筆者注意,當天下午筆者邊看到apache公開漏洞滲透的方法。這裡apache的做法確實不對,因為按照國際慣例,漏洞發現後不能公開具體滲透方法,只能描述,等官方修復後才能!

過後幾天,各種網站類似於struts2安全漏洞做各種的評論文章分析,導致各種的批判詆譭的爭論不休的評論發生!確實如此筆者得知後第一時間google測試,結果發現確實如此,不幸的是google出來一個電信某積分分站,確實如此,之後突然想起來,交話費用的電信官網也是struts架構的,立刻友情檢測,確實中招!之後想通過email通知,結果發現電信網站木有email提交,神馬線上交流都是擺設,筆者隧到烏雲(我朝號稱為網際網路安全而戰的網站,上屬國家網際網路安全中心,自命白帽子)不行,忘記了賬號密碼,放棄!瀏覽網站,確實有人提交了,故放棄,看了看,發現烏雲很多人為了提交漏洞而提交漏洞!覺得實屬沒有意思,放棄了,本來想寫文章後來覺網上各種有,放棄!後來一想該漏洞確實不是出自struts,而是XWork,想必用過struts的人都知道,XWork才是struts的核心,早起這兩個不是一家,後來apache收入麾下將XWork和struts結婚了(正所謂不是一家人不進一家門),而XWork提供的ONGL表示式語言正是兩次struts漏洞的罪魁禍首!

ps:當我們發現安全問題的時候,而不是批判別人為我們做的不夠,也不是推卸責任的時候,及時有效的解決問題才是!當然,作為商業性的要另行討論,正如我下午在快閃記憶體和某兄討論:專案管理之風險合理規避問題一樣。說俗點就是推卸責任(但又在合理之中)。我們謾罵框架的不夠完美也罷,維護人員維護不及時也罷,要看問題的實質是不是我們想的那樣,正如Xwork的核心漏洞,struts維護人員怎能及時發現?儘管發現,輕而易舉的修改核心?這個看起來似乎不是那麼的簡單!想必大家都是程式設計師,寫程式比維護程式或者修改程式難的多!不管你有多麼的牛逼,網上後來也有人試過一些非官方推薦方法,有些失敗,因為表面對了,但是實質聰明的駭客還可以繞過他的過濾!

直到今日IBM亦出現該安全漏洞!故藉此一起講講個人的安全看法!廢話不講了,下面看實戰!

截圖00(圖1.1)

截圖01(圖1.2)

截圖03(圖1.3)

到此,再也沒有測試,因為測試也是意義不大,即使你可以遠端啟動也沒有意義,做一些遠端關閉伺服器的事情也沒意義!不過可以通過遠端構造上傳指令碼小子提權!

下面講講三幅圖的奧祕,圖1.1中只是採用redirect中定向baidu,也算是初步判斷是不是存在struts2的漏洞,到圖1.2可以證明一點,確實存在struts2漏洞!那麼接下來就是駭客常用的手法,小馬提權再通過大馬獲取伺服器(大小木馬後面講)。圖1.3就是我嘗試提交執行遠端伺服器的命令(開始calc,當然這個是windows下命令),response給我的jsp頁面,從圖中我們可以看出我的命令執行了,但是我們如何確定呢?因為我們通過這個無法判斷是否成功!由於為IBM伺服器,可能涉及法律相關問題,本人沒有進一步滲透!

接下來通過自己的Demo來演示 上面的構造是否成功!搭建了一個struts2的入門專案,struts2 core是2.1.8。為了驗證我們前面的猜想及準確性,我採用雙系統切換測試,一個windows 一個linux,兩個系統同時部署相同的專案,測試不同平臺下看看結果是神馬?客戶端我採用的是伺服器如果是linux,我就用windows客戶端訪問,反之同理。結果如下!

遊戲開始:只需要redirectAction:%25{(new+java.lang.ProcessBuilder(new+java.lang.String[]{'calc','goes','here'})).start()} 一句話就可以構造起來遠端伺服器windows。

第一:我們先測試windows伺服器下的結果(下面上圖)

截圖01(圖2.1.1)

從上面豐富的圖中可以看出遊戲的結果,圖中我們可以看出上面的那一句話確實開啟了windows 伺服器的calc(計算器)綠色框中的就是windows 下伺服器控制檯爆出來的bug,為什麼會出現bug呢?我們通過%{}構造了一個程序物件,而ONGL去執行了我們構造的程序物件,這個時候伺服器端的計算器被遠端開啟,到這裡漏洞就算是暴露的無疑了!那為什麼控制檯有那樣的bug呢?redirectAction我們為什麼要選用這個呢?見名知意,重定向去執行一個action,所以構造的程序物件被執行了,struts2的架構必須返回一個字串來跳轉到該action對映到的jsp頁面,而我們只指定了其執行邏輯沒有返回任何字串,這個時候在Map搜尋不到就返回一個沒有該對映(具體我們在後面詳細解釋)。

總結:windows 下如此構造出來的指令碼可以遠端啟動windows下的commnd。

第二:既然windows可以那我們不妨換到linux平臺再看看會發生神馬情況!

首先我們要明白windows上面的命令和linux上面的是不同的,所以我們需要切換命令執行。

redirectAction:%25{(new+java.lang.ProcessBuilder(new+java.lang.String[]{'shutdown –h now'})).start()}(這次有點邪惡哦,用的關機命令,linux用不多,這個絕對記得!)

遊戲開始:看下面圖

截圖00(圖2.2.1)

選區_004(圖2.2.2)

圖2.2.1中能看出來說明,執行成功了,圖2.2.2中可以看出來執行了,抱的錯誤還是跟windows平臺同理!有人會問了,為什麼,木有關機?呵呵!確實,為什麼呢?

其實道理很簡單,linux執行許可權規則審查比較嚴格.我們無權執行核心命令!所以執行無效!web正常返回!404page.那麼有人就說了,能不能讓其表現出我們所要看到的遠控漏洞呢?這個是可以的,我們稍微修改一下檢測的程式碼讓正在執行的web伺服器停機!通過啟動虛擬機器的關閉序列,終止當前正在執行的 Java 虛擬機器。

struts2為我們提供了動態方法執行的模式!我們只需要開啟,那麼再加上struts2的ONGL漏洞執行,這樣不就可以執行了嘛!(這裡說是struts2還不如說是XWork提供的機制)

公開部分程式碼:

?('\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

簡單解釋一下這句話,這句話的意思就是通過客戶的url位址列修改了XWork的動態方法執行許可權,然後藉助ONGL漏洞,讓其執行我們動態構造的終止當前正在執行的 Java 虛擬機器指令。而這句話也是轉義過的,否則Map裡面不會去存放我們的執行指令(當然XWork設計者考慮到了這一點,就是禁止啟用這一功能,但為什麼我們能執行呢?你如果能看明白我們的程式碼是通過轉義過的其實質程式碼就是:?('#_memberAccess['allowStaticMethodAccess']')(meh)=true&(aaa)(('#context['xwork.MethodAccessor.denyMethodExecution']=#foo')(#foo=new%20java.lang.Boolean("false")))&(asdf)(('#rt.exit(1)')(#[email protected]@getRuntime()))=1裡面的“#”就是ONGL表示式中需通過“#+物件的名稱”來訪問context中的物件,裡面的“@”就是呼叫靜態方法,需要在類名和變數名前面加上@來呼叫,對於例項方法,用"."來呼叫。)、到時候ONGL也是無法執行的、

官方的解析參考是如圖:這個是對動態方法執行的官方解釋(這個是struts2最新版的XWork裡面的描述,當然在我翻看API的時候發現struts2API和XWorkAPI依舊分開,雖然兩人日子過一起了,可是“錢”還是各賺各的。)、

截圖03

下圖就是通過struts配置檔案的形式啟動動態方法執行(true就是開啟,有些公司為了提高程式碼的高可用就是通過這個表示式來對映方法及jsp來執行的,當然這個相當危險專案的檢查機制必須做好。)。看圖很明顯的解釋。

截圖04

結果:

截圖08(圖3.1)

當我接到伺服器響應給我圖3.1的效果的時候,我肯定確實伺服器停止了!這個過程稍微延遲了幾秒,我心砰砰的,能感覺到伺服器正在關閉!之後立刻檢視伺服器,結果如下圖3.2!

選區_005(圖3.2)

總結:到這裡我的謎團打開了,就是為神馬我檢測IBM,中國電信,網站的時候給我一個404的原因了,原因就是這兩家的都是linux伺服器,電信的貌似是unix伺服器(曾經聽別人提起過!)IBM是linux伺服器。最起碼能斷定該伺服器不是windows,有過駭客經驗的都應該清楚攻擊伺服器,對了解該伺服器是那種平臺又很重要意義,通過實踐我們就能推理出來!而且確實執行了我的遠端指令,只不過我木有高階許可權,但是即使拿到高階許可權我覺得也沒多大意義,IBM伺服器也不是吃素的應該上面有防火牆,而且有防毒軟體!執行這些高危系統程序肯定會被攔截、但是絕對有方法可以繞過去、這裡就嘗試這麼多。

嘗試了這麼多,我們下面剖析ONGL漏洞,神馬是ONGL。這裡我給出官方的解釋:OGNL is the Object Graph Navigation Language (seehttp://www.opensymphony.com/ognl for the full documentation of OGNL).簡言之就是:物件圖導航語言。下面給出官方模型圖(具體訪問:http://struts.apache.org/release/2.3.x/docs/ognl.html)

演練了這麼就是OGNL物件地圖導航惹的禍,而且我知道的兩次struts漏洞都是出自這個,物件導航顧名思義,構造物件然後去找Map裡面存的地圖。響應給客戶jsp,所以struts的核心就是這個,其他的攔截過濾機制都是輔助ONGL來完成物件導航的、這裡不多講了,用過struts的都應該明白。我用圖來給大家解讀、

無標題

看圖吧,寫的都多了!最後總結一句話目前來看struts2將會伴隨這種機制一直修補下去,除非重構這種方式,顯然很難!我想struts2官方推薦升級版,也就是過濾防止不允許執高危構造方式,杜絕轉碼方式滲透。

如何預防:

1.網上有人通過

<interceptor-ref name="params"> 

<param name="excludeParams">.*\\u0023.*</param> 

</interceptor-ref> 

這個是struts提供的一種機制就是通過正則表示式過濾提交引數。

2.可以通過過濾器的方式初級過濾,然後再採用struts2提供validate來驗證提交的引數(提高驗證規則,比如:包括轉碼也需要考慮)。很多coder大多就是javascript矇騙驗證法,何謂矇騙驗證法?就是在頁面通過javascript驗證,後臺從來不做規則驗證。你要知道 駭客可是不吃這一套的。還有需要加入強制型別轉換機制,這個struts2也提供了,只是很多coder也無視其存在。

3.這種是我個人推薦的五星級方法:天空一聲巨響spring security 閃亮登場,關於安全的框架很少,但是這個東東絕對是一個好東西,可是國內對安全的不重視,導致該框架用的很少。網上資料也是很少。這個是spring 的一個頂級專案,本人用過spring security2,3沒有用過,基本變化不大,裡面有少數class做了修改。這裡不做過多介紹各位好好研究去吧,這個東西是一套許可權,安全,openID,cas單點登入,防止會話偽造等功能!對於未授權的action都是無法執行的、從整合ssh2的架構上來講,他是保護在struts2外面的一到防線、

          7月17日,世界知名開源軟體struts 2爆出了2個高危漏洞,這些漏洞可使黑客取得網站伺服器的“最高許可權”,從而使企業伺服器變成黑客手中的“肉雞”。

詳細漏洞資訊:
  http://struts.apache.org/release/2.3.x/docs/s2-016.html

  http://struts.apache.org/release/2.3.x/docs/s2-017.html
  http://struts.apache.org/release/2.3.x/docs/version-notes-23151.html

目前,官方已經發布高危安全漏洞補丁升級(最新版本為:2.3.15.1,下載地址:http://struts.apache.org/download.cgi#struts23151),升級修補了多個安全漏洞,其中包括這個遠端任意程式碼的高危安全漏洞。

關於此漏洞,最好的解決方法當然是將struts2的jar包更新到最新版本。不過對於不同struts2版本,升級會引起一些包衝突。

升級步驟:
1.下載到的更新包中主要用到以下幾個替換掉舊版本的:
commons-lang3-3.1.jar (保留原有的commons-lang.jar,因為升級後,org.apache.commons.lang.StringUtils類被 org.apache.commons.lang3.StringUtils替換了,所有要保留原有包)
javassist-3.4.GA.jar (新加包)
ognl-3.0.6.jar (替換舊版本)
struts2-core-2.3.15.1.jar (替換舊版本)
xwork-core-2.3.15.1.jar (替換舊版本)
struts2-spring-plugin-2.3.15.1.jar(替換舊版本)


2.如果原有spring包版本太低,如2.0,還需要升級spring包到2.5版本。
struts2.1以下版本,需要檢查struts的xml配置檔案,type="redirect" 改為 type="redirectAction"。


3.修改 web.xml檔案


struts-cleanup
org.apache.struts2.dispatcher.ActionContextCleanUp


struts-cleanup

public class SqlFilter implements Filter {
public static final Logger logger = Logger.getLogger(sun.reflect.Reflection.getCallerClass(1));
//需要過濾的post字元
private static String sqlStr="',<,>,and,exec,insert,select, ,delete,update,count,*,%,chr,mid,master,truncate,char,like,declare,&,#,(,),,=,script,