偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

xwork修補漏洞的悲劇

安全 應用安全
在漏洞發(fā)現(xiàn)者發(fā)布的POC中,并不能影響xwork 2.1.2之前的一些版本(這個版本之前的一些版本,下文會統(tǒng)稱為老版本,之后的叫做新版),例如struts 2.0.14(就是struts修補了N個高危漏洞后的第一個版本,最常用的版本)其實是不能打的,本文會分析這個漏洞的起因,和結果,也會給出通殺POC的思路。

在漏洞發(fā)現(xiàn)者發(fā)布的POC中,并不能影響xwork 2.1.2之前的一些版本(這個版本之前的一些版本,下文會統(tǒng)稱為老版本,之后的叫做新版),例如struts 2.0.14(就是struts修補了N個高危漏洞后的第一個版本,最常用的版本)其實是不能打的,本文會分析這個漏洞的起因,和結果,也會給出通殺POC的思路。

本文希望看懂文章的人,可以專注于分析思路,但是不希望大家拿著POC到處搞站,本文不提供任何黑客工具,所有的POC,都是已經(jīng)公布過,無數(shù)人都知道的。

xwork修補漏洞的悲劇(漏洞歷史):

xwork作為struts2和webwork的核心組件,曾經(jīng)在已經(jīng)修補過了“xwork參數(shù)攔截器允許ognl方法執(zhí)行”漏洞,并給出了漏洞公告

http://struts.apache.org/2.x/docs/s2-003.html

S2-003

第一次修補

但是這個修補,最終的結果是個悲劇。大家還記得我以前說過,在《Struts2框架安全缺陷》一文中,完全不懂web安全的開發(fā)人員,為了修補XSS,竟然僅僅針對POC,過濾了這段字符“〈script〉”,一旦用戶提交“〈script xxx〉”就繞過的傻X修補方式。

他們保持一貫的風格,利用正則“{\\p{Graph}&&[^,#:=]}*”修補此漏洞。并且又僅僅針對攻擊者給出的POC,做出修補,使用POC測試通過就發(fā)布了。

解析下xwork開發(fā)人員使用POC的幾個悲劇的測試用例。

為了讓ParametersInterceptor認為它是個合法ognl語句,變量中必須最終包含#。

這行無法通過驗證,java在做字符串運算時,\u0023會被轉義為#之后,才會做匹配,所以返回false。下圖可以看到,\u0023和#是完全相等的。

所以修補漏洞的開發(fā)人員,自作聰明,直接用正則把#干掉了。

攻擊者發(fā)來的雖然是\u0023,但是這段字符在內存中做字符串運算時,會先變成\\u0023然后才做運算。java在處理用戶提交的一段string包含\時,為了保證數(shù)據(jù)完整性,會自動多加一個\用做轉義,比如用戶提交了數(shù)據(jù)“\n”,在內存中作字符串運算時,不會真的用換行做運算,而是拿”\\n”這段字符做比較。那么用戶提交的\u0023被轉為\\u0023,就會繞過對#的檢查。

證據(jù)如圖:

這兩個case沒有通過代碼驗證原因同上。

悲劇就在這里,這里雖然是\\u0023,符合用戶提交的場景,悲劇是這段字符里面因為有空格,就在+兩邊,所以無法通過,而攻擊者如果去掉空格,就通過了。

官方就這樣發(fā)布了,其實發(fā)布的是個漏洞版。

這是第一次修補,這次修補其實是大家都知道,因為發(fā)了公告出來,官方雖然公告說是高危,但是官方只知道攻擊者可以通過ognl表達式修改server端的session等信息。這時官方還沒有意識到這其實是個遠程代碼執(zhí)行漏洞,ognl不僅僅支持修改,還支持執(zhí)行一些靜態(tài)方法,比如@Runtime@getRuntime().exec(“calc”)。 #p#

第二次修補

直到某天,可能是在版本xwork2.1.2時,官方偷偷修改安全配置,默認讓SecurityMemberAccess(管理ognl權限的類)的allowStaticMethodAccess為false,這導致靜態(tài)方法不能執(zhí)行,并且不知什么原因,偷偷修改正則,也同時放開了對參數(shù)名稱中空格字符的限制。

漏洞被爆

這次出了遠程代碼執(zhí)行(Struts2/XWork < 2.2.0 Remote Command Execution Vulnerability),漏洞的發(fā)現(xiàn)者就是看到了\u0023的限制其實無效,研究出了繞過默認安全配置的方法,并且利用ognl允許靜態(tài)方法執(zhí)行,達到了遠程代碼執(zhí)行的效果。

原理簡介:

1、 用戶提交了\u0023被轉義為\\u0023,通過了對參數(shù)名稱的驗證后,最終ognl處理之前,又變成了\u0023,也就是#,符合了ognl語法。

2、 通過Ognl語句執(zhí)行,可以在struts2和webwork運行起來時,把ognl上下文中的一些默認配置覆蓋掉,漏洞發(fā)現(xiàn)者給出了不少可以覆蓋的數(shù)值。

3、 雖然默認配置是禁止靜態(tài)方法執(zhí)行的,但是xwork的配置,其實是可以覆蓋的,一旦覆蓋掉“用于禁止靜態(tài)方法執(zhí)行”的value,當然又可以執(zhí)行了。

4、 Runtime.getRuntime().exec()這段,其實可以當做靜態(tài)方法調用,導致執(zhí)行系統(tǒng)命令。Ognl語句調用靜態(tài)方法:@Runtime@getRuntime().exec(“calc”)。

漏洞發(fā)現(xiàn)者給出了shellcode,但是經(jīng)過我的測試,shellcode并不能影響所有版本,而是僅僅針對xwork2.1.2及以上的版本有效,xwork2.1.2及以上核心被應用在struts2和webwork某些版本中,所以他們間接受到了影響,但是修補代碼,是xwork去做的。

漏洞發(fā)現(xiàn)者給出POC:

山寨的修補方式帶來的后果

我看到很多人對這個漏洞簡單分析了下,有一小撮不明真相的群眾認為,這是因為參數(shù)名稱\\u0023帶來的后果,官方自己上次修補的不完善,所以,可以過濾\\u0023,搞定這件事情。

如圖是我做見過的“其中一個”漏洞分析者,自己搞的山寨補丁,原理就是禁止\\u0023

摘自互聯(lián)網(wǎng)某篇文章,不點名了,第二點解決方案居然不符合XML規(guī)則-_-!。

這只是其中一種方案,很多人說只要禁止\\u0023就可以了,不得不說,這個人應該分析了漏洞,并且了解了原理。他知道雖然官方的補丁出來了,但是官方用的是白名單形式,對參數(shù)名稱限制太嚴厲,很多特殊符號不能使用,可能會導致部分應用出問題,這是典型的開發(fā)人員思維。

這是官方的補?。?/p>

http://svn.apache.org/viewvc/struts/struts2/trunk/xwork-core/src/main/java/com/opensymphony/xwork2/interceptor/ParametersInterceptor.java?view=markup&pathrev=956389

為了優(yōu)先保證業(yè)務,只要禁止了\\u0023就可以修補漏洞,所以以上山寨方案貌似是可行的,并且經(jīng)過測試POC打不了了。

我也看到了這個方法,這真是個悲劇,攔截\u0023能解決問題么?

為什么漏洞發(fā)現(xiàn)者,通過\u0023繞過了#限制?還有沒有其他編碼可以繞過?

答案是,還有其他編碼可以繞過,僅僅控制了\u0023,是個悲劇。經(jīng)過我實際測試,發(fā)現(xiàn)#號的8進制編碼\43,也是在這里使用的,并且\043也是可以的。于是我笑了:

這段新的POC,沒有任何一個\u0023,卻一樣可以執(zhí)行calc,經(jīng)過實際測試,繞過了所有僅僅過濾\u0023的防御。讓他們慢慢修補吧,我們不著急,等大家都打上了過濾\u0023的補丁,再把這個新的POC放出來。

我看到neeao就很謹慎,直接上官方補丁,這是他對這個漏洞的分析:

http://neeao.com/archives/59/#p#

老版本的struts和webwork的POC不通用問題

在推行修補方案時,開發(fā)人員總是從自己的角度和經(jīng)驗修補漏洞,他們采用過濾\u0023的方案也罷了,最起碼態(tài)度端正。不像有些互聯(lián)網(wǎng)公司的開發(fā)根本不去補,原因很簡單,他用的是老版本的struts和webwork。對xwork2.1.2以下核心的struts2和webwork,POC打下去沒有任何效果,所以認為這個安全級別不高,還是等等官方公告吧(現(xiàn)在為止,官方?jīng)]有發(fā)布任何公告,修補好代碼提交SVN,也沒有編譯后發(fā)布版本)。

出于好奇,決定仔細研究下。我之前也不熟悉xwork源碼和ognl,以前僅僅研究過struts2的部分源碼,盲目的debug了好幾天,解決了N個問題,才搞定:

空格問題:

原POC中,會傳三個參數(shù),它們的作用,首先解析下。

1、第一個參數(shù)

在高版本的struts中,allowStaticMethodAccess(允許靜態(tài)方法訪問訪問,做權限判斷)默認是false的。但是低版本的本來就是true,所以傳不傳都一樣,可以省了。

2、第二個參數(shù)

這句必須在,否則也不會調用靜態(tài)方法。

3、第三個參數(shù)

這句是shellcode,不能沒有。

在老版本中,第二個參數(shù),是不能運行的,把它弄的好看點:

注意,new后面,有空格,在ParametersInterceptor的參數(shù)正則驗證中,根本過不去。 既然老版本不允許參數(shù)中出現(xiàn)空格,那么如果你的shell里如果有空格,會通過么?嘿嘿。。。只要你的shell,無法通過這段驗證,就不會執(zhí)行:

以上shellcode必須對空格和:符號,做16進制的轉義,才能執(zhí)行。

PS:大家都悄悄的,不要告訴那些“只拿poc,不看技術文章的那些不明真相群眾”。

所以,要必須先解決的第一個問題是,改這個空格為\u0020,才能進入ognl表達式的流程。

在比較新一點的版本的xwork中,允許空格,當然,也是允許\u0020的,所以\u0020替換空格,就通殺了第一個問題的新老版本struts正則驗證。

denyMethodExecution不能修改的問題:

改完之后,發(fā)現(xiàn)竟然還是不能賦值,經(jīng)過調試,在內存中,看到的xwork.MethodAccessor.denyMethodExecution還是true,這說明這個表達式,沒有執(zhí)行成功。原因是這里做了new對象操作。先定義了#foo變量為new java.lang.Boolean類型,默認為false,之后denyMethodExecution等于#foo。這是不允許的,原來的POC導致空指針異常(原因后面說),后來解決了。

總之用這個,可以通殺新老版本,也不會爆空指針:

提交后再次查看內存中的context,發(fā)現(xiàn)這個值被修改為false。

看看shellcode

Shellcode的原理是,利用ognl支持靜態(tài)方法執(zhí)行,調用java的執(zhí)行系統(tǒng)命令方法(其實完全可以調用任何java代碼,比如寫個文件等)。

Shellcode是可以做new操作的。

denyMethodExecution不能new操作,是因為這句執(zhí)行時的上下文中, denyMethodExecution還是true,執(zhí)行了這句,才是false,這時才可以new對象。

所以shellcode的上下文,是可以做new對象操作的。 #p#

Xwork的bug問題:

解決了這兩個問題,其實已經(jīng)給shellcode創(chuàng)造了完備的環(huán)境,按照xwork的邏輯,應該直接讓我們調用靜態(tài)方法才是,但是在shellcode運行時,居然爆出了空指針,這個問題我研究了好久才搞明白,原來是xwork自己出了bug,到了新版本時,才修補。

翻翻svn,看到在xwork2.1.2時,偷偷修改了一段代碼。

SecurityMemberAccess這個類原來有個這樣的方法

到了xwork2.1.2時,改為了:

注意標紅的,如果name==null,就返回true。

為什么會有這行代碼呢?

它調用isExcluded(name),進入isExcluded方法后,做正則表達式的驗證。

如果傳進來的是個paramName是null,并且excludeProperties是有值的,必然報錯。Xwork的bug就是,所有的版本,調用靜態(tài)方法時,都必然會傳進來一個null,并且excludeProperties也是默認有值的。

任何一個靜態(tài)方法的調用,這里傳進來的都是null。

也就是說,要調用靜態(tài)方法,就必須讓excludeProperties這個家伙的值,是一個空的Set對象,否則對null對正則匹配,就會報錯。

excludeProperties是個Set,在shell執(zhí)行的上下文中,它的值是這樣來的:

xwork處理用戶發(fā)進來的ognl表達式時,會用xwork的SecurityMemberAccess做權限判斷,以保證靜態(tài)方法不會被人隨便調用。原理是傳給shell執(zhí)行的上下文中幾個默認配置,其中一個是默認的allowStaticMethodAccess=true,也會給excludeProperties這個Set對象會被添加一個value,結果就不是空的Set對象了。

所以,在shellcode上下文中,執(zhí)行靜態(tài)方法必然會出錯。

讓shellcode正常執(zhí)行,解決方法的思路就是new一個新的HashSet。

但是經(jīng)過我測試,這里還是不能做new的操作,因為new的時候,會調用構造方法,這實質上還是在調用方法,調用方法就會出錯。為了證明我的猜測,debug調用到這一步的時候,手工修改它為new HashSet(),立刻就通過了。不能new,又怎么能得到一個空的Set呢?這是最后一道關卡。為了搞定它,我甚至查了struts-default.xml在內存中的位置,考慮是不是使用ognl修改掉。

因為這個放棄了一段時間,很郁悶,當我再次拾起來,卻突然看到了這個值的默認值。

跟進emptySet();

這是個有意思的知識點,我也是第一次了解到,可以使用EMPTY_SET,取到一個空的set。

于是當我提交某些東西,讓

這一句覆蓋了默認的那個有了一個值的map,重新變成了空的map,這才真正的達到了靜態(tài)方法的終極調用條件。

其實我都快吐血了,明明是xwork自己代碼寫的不嚴謹,直到他們新的版本才發(fā)現(xiàn)這個bug,并修補,居然導致我研究漏洞的同時還順帶幫他們處理bug。

最后終于找到機會鄙視一下漏洞發(fā)現(xiàn)者的poc,他說老版本的struts2可以使用XXX的POC,經(jīng)過我測試,不可行,原理也很簡單,本文說了,POC中不能有空格。

這句話即使在新版本中,也是沒什么影響的,雖然會改變一個值,但是不受啥影響, shellcode中,有了這句話,就兼容新老版本,一切通殺了!

最后湊出通殺0DAY在這里:

被和諧了,沒辦法,畢竟在互聯(lián)網(wǎng)公司里,要考慮到其他互聯(lián)網(wǎng)公司同行的處境,雖然他們不一定都是漏洞公布的POC不能打的版本。

POC,不要找我要了,本文僅僅說下技術研究。

回顧下:

適合新版本繞過雙引號和\u0023防御的poc:

適合新版本繞過\u0023的poc

僅僅適用老版本(struts2.0.12)的POC

僅僅適用新版本的也就是漏洞發(fā)現(xiàn)者放出來的poc

【編輯推薦】

  1. DZ7.1 and 7.2 0遠程代碼執(zhí)行漏洞獲取Webshell
  2. 利用MS08067遠程溢出漏洞抓肉雞
責任編輯:許鳳麗 來源: IT專家網(wǎng)
相關推薦

2014-08-27 17:10:55

2023-10-21 00:20:16

2022-02-21 15:19:10

谷歌漏洞Linux

2023-08-02 09:59:51

2011-03-15 15:27:23

2023-06-27 11:19:28

2013-12-13 10:36:51

2009-07-06 15:05:23

2009-07-21 09:16:56

漏洞windows MobHTC

2009-12-29 14:25:14

phpXSS漏洞

2022-05-24 10:28:48

勒索軟件漏洞網(wǎng)絡攻擊

2021-09-26 10:24:42

Windows0 day漏洞

2024-05-06 12:54:27

2011-05-13 10:19:03

2012-06-19 10:01:10

2009-07-17 13:05:24

火狐3.5升級版Mozilla技術漏洞

2010-02-12 09:20:33

Windows 7系統(tǒng)漏洞

2009-02-18 15:09:49

2023-11-14 22:16:36

2023-06-05 18:19:44

點贊
收藏

51CTO技術棧公眾號