PS.之前一直想把零零碎碎的知識整理下來,作為知識沉淀下來,正好借著wooyun峰會的機會將之前的流程又梳理了一遍,于是就有了下文。也希望整理的內容能給甲方工作者或則白帽子帶來一些收獲。
隨著網絡安全越來越受到重視,發展越來越快。隨之也出現了越來越多的安全防護的軟件。例如有:
1.云waf;[阿里云盾,百度云加速,360網站衛士,加速樂等]
2.傳統安全廠商的硬件waf以及一直存在的ips,ids設備;[綠盟,啟明,深信服,安恒等]
3.主機防護軟件如安全狗,云鎖;
4.軟waf如modsecurity,nginx-lua-waf等。
當然也有目前很火的sqlchop。
這些進行web攻擊的防護的軟件,我們先統稱他們為WAF,它們也是下文的主角了。
這里我就用’WAF’來代替上面所說的一些防護軟件,我們需要知道這些WAF都在網絡空間的哪些位置。
用戶從瀏覽器發出一個請求(http://www.miku.com/1.php?id=1%20and1=1)到最終請求轉發到服務器上,中間經歷了多少設備,這些工作在網絡的第幾層(TCP/IP協議)?我們應用層的數據被哪些設備處理了?
這是一個經典的數通問題,了解WAF在網絡空間的位置,我們便可以更清楚的知道使用哪些知識來協助我們進行WAF bypass。
如下圖所示:
畫了一個簡單的拓撲圖。
圖中可以很清楚的看到,我們的云waf,硬件ips/ids防護,硬件waf,主機防護,軟waf以及應用程序所在的位置。
在明白了各種防護軟件在網絡環境下的拓撲之后,現在了解一下基礎數據的流量與相關設備的基本處理。
假設客戶端訪問url:http://www.miku.com/1.php?id=1’and’1’=’1,該請求請求的數據是服務器上數據庫中id為1的記錄。
假設這臺服務器使用了相關云waf。
1)一個完整的過程,首先會請求DNS,由于配置云waf的時候,會修改DNS的解析。我們發送DNS請求之后,域名會被解析到云WAF的ip上去。DNS解析完成之后,獲取到域名信息,然后進入下一個步驟。
2)HTTP協議是應用層協議,且是tcp協議,因此會首先去做TCP的三次握手,此處不去摳三次握手的細節,假設三次握手建立完畢。
3)發送HTTP請求過去,請求會依次經過云WAF,硬件IPS/IDS設備,硬件WAF設備,服務器,web服務器,主機防護軟件/軟WAF,WEB程序,數據庫。 云WAF,硬件IPS/IDS,硬件WAF均有自己處理數據的方式。云WAF與硬件WAF細節上不太清楚,對于硬件IPS有一定的了解。之前在drops上發過一篇文章,文章鏈接是:http://drops.wooyun.org/papers/4323。
在獲取HTTP數據之前會做TCP重組,重組主要目的是針對互聯網數據包在網絡上傳輸的時候會出現亂序的情況,數據包被重組之后就會做協議解析,取出相關的值。如http_method=GET
,http_payload=xxx
等等。這些值就對應了IPS規則中相關規則的值。從而來判斷規則匹配與不匹配。
在我自己看來,所謂的BYPASS WAF實際上是去尋找位于WAF設備之后處理應用層數據包的硬件/軟件的特性。利用特性構造WAF不能命中,但是在應用程序能夠執行成功的載荷,繞過防護。
那些特性就像是一個個特定的場景一樣,一些是已經被研究人員發現的,一些是還沒被發現,等待被研究人員發現的。當我們的程序滿足了這一個個的場景,倘若WAF沒有考慮到這些場景,我們就可以利用這些特性bypass掉WAF了。
例如我們現在需要bypass一個云WAF/IPS/硬件WAF,此處我們可以利用的點就是:
1.Web服務器層bypass
2.Web應用程序層bypass
3.數據庫層 bypass
4.WAF層bypass
由于各個層面可以利用的特性很多,而且WAF往往要考慮自身的性能等等方面,導致了WAF往往會留下一些軟肋。下面的文章來細細的總結下之前那些經常被用來做bypass的特性。
Ps.思路是不是稍微清晰了一點。= =
利用WEB服務器的特性來進行WAF bypass,常見的組合就有asp+IIS aspx+IIS php+apache java+tomcat
等。
這部分內容大多是用來做http的解析等相關事務的,因此這里我理解的也就是尋找WAF對于http解析以及真實環境對于http解析的差異特性,利用差異特性來bypass WAF。
Ps.這部分待挖掘的地方還有很多,而且這部分挖掘出來的特性應該對于WAF的bypass是致命的。
運行在IIS上的程序一般為asp,aspx的。在IIS上我們可以利用的特性:
在asp+iis的環境中存在一個特性,就是特殊符號%,在該環境下當們我輸入s%elect
的時候,在WAF層可能解析出來的結果就是s%elect
,但是在iis+asp
的環境的時候,解析出來的結果為select
。
本地搭建asp+iis
環境測試,測試效果如下圖:
Ps.此處猜測可能是iis下asp.dll
解析時候的問題,aspx+iis
的環境就沒有這個特性。
Iis服務器支持對于unicode的解析,例如我們對于select中的字符進行unicode編碼,可以得到如下的s%u006c%u0006ect
,這種字符在IIS接收到之后會被轉換為select,但是對于WAF層,可能接收到的內容還是s%u006c%u0006ect
,這樣就會形成bypass的可能。
我們搭建asp+iis
和aspx+iis
的環境:
測試效果如圖:
測試效果如圖:
Ps.需要注意的是,這個特性測試的時候發現aspx+iis
的環境是不支持的,有待做實驗考證,懷疑是后綴后面的內容是通過asp.net isapi
來出來的,導致了asp和aspx的不同。
上面寫到了iis支持unicode的格式的解析。這種iis解析,存在一個特性,之前在wooyun上報過一個漏洞: WooYun: 一個有意思的通用windows防火墻bypass(云鎖為例) 。
該漏洞主要利用的是unicode
在iis解析之后會被轉換成multibyte
,但是轉換的過程中可能出現: 多個widechar
會有可能轉換為同一個字符。
打個比方就是譬如select中的e對應的unicode為%u0065
,但是%u00f0
同樣會被轉換成為e。
s%u0065lect->select
s%u00f0lect->select
WAF層可能能識別s%u0065lect
的形式,但是很有可能識別不了s%u00f0lect
的形式。這樣就可以利用起來做WAF的繞過。
搭建asp+iis
的環境:
asp+iis
的環境
測試效果如圖:
Ps.該漏洞的利用場景可能有局限性,但是挖掘思路是可以借鑒的。
某些apache版本在做GET請求的時候,無論method為何值均會取出GET的內容,如請求為的method為DOTA2,依然返回了aid為2的結果。
如果某些WAF在處理數據的時候嚴格按照GET,POST等方式來獲取數據,就會因為apache的寬松的請求方式導致bypass。 實例: WooYun: 安全寶SQL注入規則繞過
ps.測試的時候使用了apache2.4.7的版本。
Php在解析multipart data
的時候有自己的特性,對于boundary
的識別,只取了逗號前面的內容,例如我們設置的boundary為----aaaa
,123456
,php
解析的時候只識別了----aaaa
,后面的內容均沒有識別。然而其他的如WAF在做解析的時候,有可能獲取的是整個字符串,此時可能就會出現BYPASS。
參考:http://blog.phdays.com/2014/07/review-of-waf-bypass-tasks.html
如上圖,可能出現waf獲取的是一個圖片的內容,而在web端獲取的是aid=2
的值。這樣的差別就有可能造成bypass。
雙重url編碼,即對于瀏覽器發送的數據進行了兩次urlencode
操作,如s做一次url編碼是%73,再進行一次編碼是%25%37%33
。一般情況下數據經過WAF設備的時候只會做一次url解碼,這樣解碼之后的數據一般不會匹配到規則,達到了bypass的效果。
個人理解雙重url編碼,要求數據在最后被程序執行之前,進行了兩次url解碼,如果只進行了一次解碼,這樣在最后的結果也是不會被正確執行的。 實例: WooYun: 騰訊某分站SQL注射-直接繞過WAF
1)GET,POST,COOKIE
在web環境下有時候會出現統一參數獲取的情況,主要目的就是對于獲取的參數進行統一過濾。例如我獲取的參數t=select 1 from 2
這個參數可以從get參數中獲取,可以從post參數獲取,也可以從cookie參數中獲取。
典型的dedecms,在之前測試的時候就發現了有些waf廠商進行過濾的時候過濾了get和post,但是cookie沒有過濾,直接更改cookie參數提交payload,即繞過。
實例: WooYun: 百度云加速防御規則繞過之三 一個dedecms的站,get,post
均過濾了,但是并沒有過濾cookie參數。
2)urlencode和form-data POST在提交數據的時候有兩種方式,第一種方式是使用urlencode
的方式提交,第二種方式是使用form-data
的方式提交。當我們在測試站點的時候,如果發現POST提交的數據被過濾掉了,此時可以考慮使用form-data
的方式去提交。
我們在阿里云ecs主機上搭建個環境,創建一個存在sql注入漏洞的頁面,獲取參數從POST上獲取,首先我以urlencode
的方式提交,查看發現提交的請求被阻斷了。
其次我們以form-data
的方式提交,發現爆出了數據庫的版本。
1)asp/asp.net request
解析
在asp和asp.net
中使用參數獲取用戶的提交的參數一般使用request包,譬如使用request['']
來獲取的時候可能就會出現問題。 資料文檔:http://www.80sec.com/%E6%B5%85%E8%B0%88%E7%BB%95%E8%BF%87WAF%E7%9A%84%E6%95%B0%E7%A7%8D%E6%96%B9%E6%B3%95.html
當使用request['']
的形式獲取包的時候,會出現GET,POST分不清的情況,譬如可以構造一個請求包,METHOD為GET,但是包中還帶有POST的內容和POST的content-type
。
我們搭建一個實例:
我們創建一個letmetest.aspx
的界面獲取用戶提交的內容,并且將request['t']
的內容打印出來。【在服務器上安裝了安全狗】 首先我們提交正常的POST請求,發現已經被安全狗阻斷了:
此時我們提交畸形的請求,method為GET,但是內容為POST的內容,發現打印出來了內容。
HPP是指HTTP參數污染。形如以下形式:
?id=1&id=2&id=3
的形式,此種形式在獲取id值的時候不同的web技術獲取的值是不一樣的。
假設提交的參數即為:
id=1&id=2&id=3
Asp.net + iis:id=1,2,3
Asp + iis:id=1,2,3
Php + apache:id=3
如此可以分析:當WAF獲取參數的形式與WEB程序獲取參數的形式不一致的時候,就可能出現WAF bypass的可能。
Ps.此處關鍵還是要分析WAF對于獲取參數的方式是如何處理的。這里也要再提一下的,hpp的靈活運用,譬如有些cms基于url的白名單,因此可以利用hpp的方式在參數一的位置添加白名單目錄,參數2的位置添加惡意的payload。形如index.php?a=[whitelist]&a=select 1 union select 2
實例參考: WooYun: 使用webscan360的cms廠商通過hpp可使其失效(附cmseasy新版sql注射)
數據庫層bypass常常是在bypass waf的sql注入防護規則。我們需要針對數據庫使用該數據庫的特性即可。如mysql,sqlserver等等。最近一直想整理下oracle的,這塊也是研究不多的,后續整理后添加到文檔里。
Ps.目前數據庫被暴露出來的特性很多很多,基本上很多特性綜合利用就已經夠用了,因此特性知不知道是一方面,能不能靈活運用就得看測試者自己了。
就目前來看mysql是使用最多的,也是研究人員研究最深的數據庫。在我自己測試的角度上我一般會去測試下面的過濾點,因為一般繞過了select from
就基本可以sql注入獲取數據了。
http://zone.wooyun.org/content/16772貼中有相關總結。
(1):\Nunion
的形式:
(2):浮點數的形式如1.1,8.0
(3):8e0
的形式:
(4): 利用/*!50000*/
的形式
(1)空白字符
Mysql中可以利用的空白字符有:%09,%0a,%0b,%0c,%0d,%a0
;
(2)注釋
使用空白注釋
MYSQL中可以利用的空白字符有:
/**/
/*letmetest*/
(3)使用括號
union select
后的位置(1)空白字符
Mysql中可以利用的空白字符有:%09,%0a,%0b,%0c,%0d,%a0
;
(2)注釋
使用空白注釋
MYSQL中可以利用的空白字符有:
/**/
/*letmetest*/
(3)其他方式:【這里需要考慮的是有時候union select
和select from
可能是兩個規則,這里先整理union select
的】
括號:select(1)from
運算符號:
減號
:
加號
:
~號
:
!號
:
@`形式`
*號
,利用/*!50000*/
的形式
單引號和雙引號
:
{括號
:
\N符號
:
select from
之間的位置(1)空白字符
Mysql中可以利用的空白字符有:%09,%0a,%0b,%0c,%0d,%a0
;
(2)注釋
使用空白注釋
MYSQL中可以利用的空白字符有:/**/ /*letmetest*/
(3)其他符號
``符號
+,-,!,~,’”
*號
{號
(號
(1)空白字符
Mysql中可以利用的空白字符有:%09,%0a,%0b,%0c,%0d,%a0
;
(2)注釋
使用空白注釋
MYSQL中可以利用的空白字符有:/**/ /*letmetest*/
(3)其他符號
``號
*號
{號
括號
Ps.空白符,注釋符,/!50000select*/,{x version},(),
在很多點都可以使用,某些點有自己特殊的地方,可以使用一些其他的符號。
實例:http://wooyun.org/bugs/wooyun-2010-0121291 實例就是利用靈活利用上面的特性,導致了bypass。
Mid(version(),1,1)
Substr(version(),1,1)
Substring(version(),1,1)
Lpad(version(),1,1)
Rpad(version(),1,1)
Left(version(),1)
reverse(right(reverse(version()),1)
concat(version(),'|',user());
concat_ws('|',1,2,3)
Ascii(1) 此函數之前測試某云waf的時候被過濾了,然后使用ascii (1)
即可
Char(49)
Hex(‘a’)
Unhex(61)
limit 1 offset 0
mid處的逗號:
mid(version() from 1 for 1)
通過join拼接。
空白符號:
01,02,03,04,05,06,07,08,09,0A,0B,0C,0D,0E,0F,10,11,12,13,14,15,16,17,18,19,1A,1B,1C,1D,1E,1F,20?
需要做urlencode
,sqlserver
中的表示空白字符比較多,靠黑名單去阻斷一般不合適。
注釋符號 Mssql也可以使用注釋符號/**/
其他符號: .符號
:號
空白符號:
01,02,03,04,05,06,07,08,09,0A,0B,0C,0D,0E,0F,10,11,12,13,14,15,16,17,18,19,1A,1B,1C,1D,1E,1F,20?
注釋符號 Mssql也可以使用注釋符號/**/
:號
空白符號:
01,02,03,04,05,06,07,08,09,0A,0B,0C,0D,0E,0F,10,11,12,13,14,15,16,17,18,19,1A,1B,1C,1D,1E,1F,20?
注釋符號
Mssql也可以使用注釋符號/**/
:號:
%2b號
:
Substring(@@version,1,1)
Left(@@version,1)
Right(@@version,1)
Ascii(‘a’) 這里的函數可以在括號之間添加空格的,一些waf過濾不嚴會導致bypass
Char(‘97’)
Mssql支持多語句查詢,因此可以使用;結束上面的查詢語句,然后執行自己構造的語句。動態執行。
使用exec的方式:
使用sp_executesql的方式:
使用這類可以對自己的參數進行拼接,可以繞過WAF防御。
如使用該類特性然后加上上面提到的:的特性就可以繞過安全狗的注入防御。
WAF在設計的時候都會考慮到性能問題,例如如果是基于數據包的話會考慮檢測數據包的包長,如果是基于數據流的話就會考慮檢測一條數據流的多少個字節。一般這類算檢測的性能,同時為了保證WAF的正常運行,往往還會做一個bypass設計,在性能如cpu高于80%或則內存使用率高于如80%是時候,會做檢測bypass,以保證設備的正常運行。
WAF等設備都是工作在應用層之上的,如HTTP,FTP,SMTP
等都是應用層的協議,這些數據要被處理都會被進行數據解析,協議分析。最終獲取應用層的數據。如HTTP的方法是什么,HTTP的querystring
是什么,以及HTTP的requestbody
是什么。然后將這些實時獲取的值與WAF設計的規則進行匹配,匹配上著命中規則做相應的處理。
現在問題就是檢測多長呢?例如我用HTTP POST上傳一個2G的文件,明顯不可能2G全做檢測不但耗CPU,同時也會耗內存。因此在設計WAF的時候可能就會設計一個默認值,有可能是默認多少個字節的流大小,可能是多少個數據包。
之前在zone發過個帖子,http://zone.wooyun.org/content/17331,是測試安全狗的,大致原理應該是一樣的,設計了一個腳本,不斷的向HTTP POST添加填充數據,當將填充數據添加到一定數目之后,發現POST中的sql注入惡意代碼沒有被檢測了。最終達到了bypass的目的。
在測試某家云WAF的時候使用此類方法也可以達到bypass的目的。
一些傳統硬件防護設備為了避免在高負載的時候影響用戶體驗,如延時等等問題,會考慮在高負載的時候bypass掉自己的防護功能,等到設備的負載低于門限值的時候又恢復正常工作。
一些高性能的WAF可能使用這種方法可能不能bypass,但是一些軟WAF使用這種方式還是可以bypass的。
http://wooyun.org/bugs/wooyun-2010-094367 一個bypass的例子,將請求并發同時發送多次,多次訪問的時候就有幾次漏掉了,沒有觸發waf的攔截。
Ps.作者自己在測試的時候曾經做了如下測試制造了一個payload,同時添加了大量的無效數據,使用腳本兵法發送該請求,發現請求的時候有些通過了WAF,有些被WAF所攔截了。應該就是性能問題導致了bypass。
使用腳本去探測WAF設備對于字符處理是否有異常,上面已經說過WAF在接收到網絡數據之后會做相應的數據包解析,一些WAF可能由于自身的解析問題,對于某些字符解析出錯,造成全局的bypass。 我測試的時候常常測試的位置:
1):get請求處
2):header請求處
3):post urlencode內容處
4):post form-data內容處
然后模糊測試的基礎內容有:
1)編碼過的0-255字符
2)進行編碼的0-255字符
3)utf gbk字符
實例1:http://wooyun.org/bugs/wooyun-2010-087545
在一次測試安全狗的過程中,使用post的方式提交數據,提交數據包括兩個參數,一個是正常的fuzz點,另一個參數包含一個sql注入語句。當在測試前面的fuzz點的時候,處理到\x00的字符的時候,沒有提示安全狗阻攔。應該是解析這個字符的時候不當,導致了bypass。
實例2:http://wooyun.org/bugs/wooyun-2015-091516
在一次測試云WAF中,使用get方式提交數據,提交內容包括一個參數,參數為字符+sql注入的語句。當在fuzz字符的時候,發現云waf在處理到&字符的時候,沒有提示云waf阻攔。由于&字符的特殊性,猜測是由于和url請求中的&沒有處理好導致的。由于mysql中&&同樣可以表示and,因此拼湊一下sql語句就達到了bypass的目的。
Ps.上面做模糊測試的時候僅僅是測試了一些各個位置的單個字符,應該還會有更復雜的測試,WAF并沒想象的那么完美,肯定還可以fuzz出其他地方的問題。
WAF在設計之初一般都會考慮白名單功能。如來自管理IP的訪問,來自cdn服務器的訪問等等。這些請求是可信任的,不必走WAF檢測流程。
獲取白名單的ip地址如果是從網絡層獲取的ip,這種一般bypass不了,如果采用應用層的數據作為白名單,這樣就可能造成bypass。
文章內容是通過修改http的header來bypass waf,這里我們截取文章中部分內容:
這些header常常用來獲取IP,可能還有其他的,例如nginx-lua-waf:
獲取clientip使用了X-Real-ip的header。
此種方法還可以用來繞過如登陸鎖ip,登陸多次驗證碼,后臺驗證等等的場景。
特性就像是一個個特定的場景一樣,一些是已經被研究人員發現的,一些是還沒被發現,等待被研究人員發現的。
隨著一個個特性的發現,WAF的防護能力在web對抗中逐漸增強,在我看來,當所有的特性場景均被WAF考慮到的時候,勢必就會有的新的發現。(如我們現在了解的mysql的場景)
因此我們不用擔心當所有的特性被WAF考慮到的時候我們無計可施,未知的特性那么多,我們還有很多地方可以去挖掘。
當你發現這些姿勢都不好使的時候,你就該去發現一些新的特性了,畢竟設計WAF的選手都是基于目前的認知下去設計的,當新的特性出現的時候,勢必又是一波bypass。