Bypass WAF Cookbook

wyzsk發表於2020-08-19
作者: MayIKissYou · 2015/08/13 11:59

PS.之前一直想把零零碎碎的知識整理下來,作為知識沉澱下來,正好藉著wooyun峰會的機會將之前的流程又梳理了一遍,於是就有了下文。也希望整理的內容能給甲方工作者或則白帽子帶來一些收穫。

0x00 概述


隨著網路安全越來越受到重視,發展越來越快。隨之也出現了越來越多的安全防護的軟體。例如有:

1.雲waf;[阿里雲盾,百度雲加速,360網站衛士,加速樂等]

2.傳統安全廠商的硬體waf以及一直存在的ips,ids裝置;[綠盟,啟明,深信服,安恆等]

3.主機防護軟體如安全狗,雲鎖;

4.軟waf如modsecurity,nginx-lua-waf等。

當然也有目前很火的sqlchop。

這些進行web攻擊的防護的軟體,我們先統稱他們為WAF,它們也是下文的主角了。

0x01 WAF 在哪裡


這裡我就用’WAF’來代替上面所說的一些防護軟體,我們需要知道這些WAF都在網路空間的哪些位置。

使用者從瀏覽器發出一個請求(http://www.miku.com/1.php?id=1%20and1=1)到最終請求轉發到伺服器上,中間經歷了多少裝置,這些工作在網路的第幾層(TCP/IP協議)?我們應用層的資料被哪些裝置處理了?

這是一個經典的數通問題,瞭解WAF在網路空間的位置,我們便可以更清楚的知道使用哪些知識來協助我們進行WAF bypass。

如下圖所示:

enter image description here

畫了一個簡單的拓撲圖。

圖中可以很清楚的看到,我們的雲waf,硬體ips/ids防護,硬體waf,主機防護,軟waf以及應用程式所在的位置。

0x02 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上發過一篇文章,文章連結是:/papers/?id=4323

在獲取HTTP資料之前會做TCP重組,重組主要目的是針對網際網路資料包在網路上傳輸的時候會出現亂序的情況,資料包被重組之後就會做協議解析,取出相關的值。如http_method=GET,http_payload=xxx等等。這些值就對應了IPS規則中相關規則的值。從而來判斷規則匹配與不匹配。

0x03 WAF BYPASS的理解


在我自己看來,所謂的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.思路是不是稍微清晰了一點。= =

0x04 Bypass WAF 姿勢


1 Web Server層 bypass

利用WEB伺服器的特性來進行WAF bypass,常見的組合就有asp+IIS aspx+IIS php+apache java+tomcat等。

這部分內容大多是用來做http的解析等相關事務的,因此這裡我理解的也就是尋找WAF對於http解析以及真實環境對於http解析的差異特性,利用差異特性來bypass WAF。

Ps.這部分待挖掘的地方還有很多,而且這部分挖掘出來的特性應該對於WAF的bypass是致命的。

1.1 IIS伺服器

執行在IIS上的程式一般為asp,aspx的。在IIS上我們可以利用的特性:

1 %特性

在asp+iis的環境中存在一個特性,就是特殊符號%,在該環境下當們我輸入s%elect的時候,在WAF層可能解析出來的結果就是s%elect,但是在iis+asp的環境的時候,解析出來的結果為select

本地搭建asp+iis環境測試,測試效果如下圖:

enter image description here

Ps.此處猜測可能是iis下asp.dll解析時候的問題,aspx+iis的環境就沒有這個特性。

2 %u特性

Iis伺服器支援對於unicode的解析,例如我們對於select中的字元進行unicode編碼,可以得到如下的s%u006c%u0006ect,這種字元在IIS接收到之後會被轉換為select,但是對於WAF層,可能接收到的內容還是s%u006c%u0006ect,這樣就會形成bypass的可能。

我們搭建asp+iisaspx+iis的環境:

(1)asp+iis的環境

測試效果如圖:

enter image description here

(2)aspx+iis的環境

測試效果如圖:

enter image description here

3 另類%u特性

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的環境

測試效果如圖:

enter image description here

Ps.該漏洞的利用場景可能有侷限性,但是挖掘思路是可以借鑑的。

1.2 apache伺服器

1 畸形method

某些apache版本在做GET請求的時候,無論method為何值均會取出GET的內容,如請求為的method為DOTA2,依然返回了aid為2的結果。

enter image description here

如果某些WAF在處理資料的時候嚴格按照GET,POST等方式來獲取資料,就會因為apache的寬鬆的請求方式導致bypass。 例項: WooYun: 安全寶SQL隱碼攻擊規則繞過

ps.測試的時候使用了apache2.4.7的版本。

2 php+apache畸形的boundary

Php在解析multipart data的時候有自己的特性,對於boundary的識別,只取了逗號前面的內容,例如我們設定的boundary為----aaaa,123456php解析的時候只識別了----aaaa,後面的內容均沒有識別。然而其他的如WAF在做解析的時候,有可能獲取的是整個字串,此時可能就會出現BYPASS。

參考:http://blog.phdays.com/2014/07/review-of-waf-bypass-tasks.html

enter image description here

如上圖,可能出現waf獲取的是一個圖片的內容,而在web端獲取的是aid=2的值。這樣的差別就有可能造成bypass。

2 Web應用程式層bypass

2.1 雙重url編碼

雙重url編碼,即對於瀏覽器傳送的資料進行了兩次urlencode操作,如s做一次url編碼是%73,再進行一次編碼是%25%37%33。一般情況下資料經過WAF裝置的時候只會做一次url解碼,這樣解碼之後的資料一般不會匹配到規則,達到了bypass的效果。

個人理解雙重url編碼,要求資料在最後被程式執行之前,進行了兩次url解碼,如果只進行了一次解碼,這樣在最後的結果也是不會被正確執行的。 例項: WooYun: 騰訊某分站SQL注射-直接繞過WAF

2.2 請求獲取方式

2.2.1 變換請求方式

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的方式提交,檢視發現提交的請求被阻斷了。

enter image description here

其次我們以form-data的方式提交,發現爆出了資料庫的版本。

enter image description here

2.2.2 畸形請求方式

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請求,發現已經被安全狗阻斷了:

enter image description here

此時我們提交畸形的請求,method為GET,但是內容為POST的內容,發現列印出來了內容。

enter image description here

2.3 hpp方式

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注射)

3 資料庫層bypass

資料庫層bypass常常是在bypass waf的sql注入防護規則。我們需要針對資料庫使用該資料庫的特性即可。如mysql,sqlserver等等。最近一直想整理下oracle的,這塊也是研究不多的,後續整理後新增到文件裡。

Ps.目前資料庫被暴露出來的特性很多很多,基本上很多特性綜合利用就已經夠用了,因此特性知不知道是一方面,能不能靈活運用就得看測試者自己了。

3.1 mysql資料庫

就目前來看mysql是使用最多的,也是研究人員研究最深的資料庫。在我自己測試的角度上我一般會去測試下面的過濾點,因為一般繞過了select from就基本可以sql注入獲取資料了。

1)常見過濾的位置
第一:引數和union之間的位置

http://zone.wooyun.org/content/16772貼中有相關總結。

(1):\Nunion的形式:

enter image description here

(2):浮點數的形式如1.1,8.0

enter image description here

(3):8e0的形式:

enter image description here

(4): 利用/*!50000*/的形式

enter image description here

第二:union和select之前的位置

(1)空白字元

Mysql中可以利用的空白字元有:%09,%0a,%0b,%0c,%0d,%a0

(2)註釋

使用空白註釋

MYSQL中可以利用的空白字元有:

/**/ 
/*letmetest*/

(3)使用括號

enter image description here

第三:union select後的位置

(1)空白字元

Mysql中可以利用的空白字元有:%09,%0a,%0b,%0c,%0d,%a0

(2)註釋

使用空白註釋

MYSQL中可以利用的空白字元有:

/**/
/*letmetest*/

(3)其他方式:【這裡需要考慮的是有時候union selectselect from可能是兩個規則,這裡先整理union select的】

括號:select(1)from

enter image description here

運算子號:

減號

enter image description here

加號

enter image description here

~號

enter image description here

!號

enter image description here

@`形式`

enter image description here

*號,利用/*!50000*/的形式

enter image description here

單引號和雙引號

enter image description here

{括號

enter image description here

\N符號

enter image description here

第四:select from之間的位置

(1)空白字元

Mysql中可以利用的空白字元有:%09,%0a,%0b,%0c,%0d,%a0

(2)註釋

使用空白註釋

MYSQL中可以利用的空白字元有:/**/ /*letmetest*/

(3)其他符號

``符號

enter image description here

+,-,!,~,’”

enter image description here

*號

enter image description here

{號

enter image description here

(號

enter image description here

第五:select from之後的位置

(1)空白字元

Mysql中可以利用的空白字元有:%09,%0a,%0b,%0c,%0d,%a0

(2)註釋

使用空白註釋

MYSQL中可以利用的空白字元有:/**/ /*letmetest*/

(3)其他符號

``號

enter image description here

*號

enter image description here

{號

enter image description here

括號

enter image description here

Ps.空白符,註釋符,/!50000select*/,{x version},(),在很多點都可以使用,某些點有自己特殊的地方,可以使用一些其他的符號。

例項:http://wooyun.org/bugs/wooyun-2010-0121291 例項就是利用靈活利用上面的特性,導致了bypass。

2)常見過濾函式
(1)字串擷取函式
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)
(2)字串連線函式
concat(version(),'|',user());
concat_ws('|',1,2,3)
(3)字元轉換

Ascii(1) 此函式之前測試某雲waf的時候被過濾了,然後使用ascii (1)即可

Char(49)
Hex(‘a’)
Unhex(61)
3)過濾了逗號
(1)limit處的逗號:
limit 1 offset 0
(2)字串擷取處的逗號

mid處的逗號:

mid(version() from 1 for 1)
(3)union處的逗號:

透過join拼接。

enter image description here

5.3.2 sqlserver資料庫

1)常見過濾位置
(1) select from後的位置

空白符號:

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 

需要做urlencodesqlserver中的表示空白字元比較多,靠黑名單去阻斷一般不合適。

註釋符號 Mssql也可以使用註釋符號/**/

其他符號: .符號

enter image description here

:號

enter image description here

(2) select from之間的位置

空白符號:

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也可以使用註釋符號/**/

:號

enter image description here

(3) and之後的位置

空白符號:

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也可以使用註釋符號/**/

:號:

enter image description here

%2b號

enter image description here

2)常見過濾函式
(1)字串擷取函式
Substring(@@version,1,1)
Left(@@version,1)
Right(@@version,1)
(2)字串轉換函式
Ascii(‘a’) 這裡的函式可以在括號之間新增空格的,一些waf過濾不嚴會導致bypass
Char(‘97’)
(3) 其他方式

Mssql支援多語句查詢,因此可以使用;結束上面的查詢語句,然後執行自己構造的語句。動態執行。

使用exec的方式:

enter image description here

使用sp_executesql的方式:

enter image description here

使用這類可以對自己的引數進行拼接,可以繞過WAF防禦。

如使用該類特性然後加上上面提到的:的特性就可以繞過安全狗的注入防禦。

5.4 WAF層bypass

5.4.1 效能bypass

WAF在設計的時候都會考慮到效能問題,例如如果是基於資料包的話會考慮檢測資料包的包長,如果是基於資料流的話就會考慮檢測一條資料流的多少個位元組。一般這類算檢測的效能,同時為了保證WAF的正常執行,往往還會做一個bypass設計,在效能如cpu高於80%或則記憶體使用率高於如80%是時候,會做檢測bypass,以保證裝置的正常執行。

WAF等裝置都是工作在應用層之上的,如HTTP,FTP,SMTP等都是應用層的協議,這些資料要被處理都會被進行資料解析,協議分析。最終獲取應用層的資料。如HTTP的方法是什麼,HTTP的querystring是什麼,以及HTTP的requestbody是什麼。然後將這些實時獲取的值與WAF設計的規則進行匹配,匹配上著命中規則做相應的處理。

5.4.1.1 效能檢測bypass

enter image description here

現在問題就是檢測多長呢?例如我用HTTP POST上傳一個2G的檔案,明顯不可能2G全做檢測不但耗CPU,同時也會耗記憶體。因此在設計WAF的時候可能就會設計一個預設值,有可能是預設多少個位元組的流大小,可能是多少個資料包。

之前在zone發過個帖子,http://zone.wooyun.org/content/17331,是測試安全狗的,大致原理應該是一樣的,設計了一個指令碼,不斷的向HTTP POST新增填充資料,當將填充資料新增到一定數目之後,發現POST中的sql注入惡意程式碼沒有被檢測了。最終達到了bypass的目的。

在測試某家雲WAF的時候使用此類方法也可以達到bypass的目的。

5.4.1.2 效能負載bypass

enter image description here

一些傳統硬體防護裝置為了避免在高負載的時候影響使用者體驗,如延時等等問題,會考慮在高負載的時候bypass掉自己的防護功能,等到裝置的負載低於門限值的時候又恢復正常工作。

一些高效能的WAF可能使用這種方法可能不能bypass,但是一些軟WAF使用這種方式還是可以bypass的。

http://wooyun.org/bugs/wooyun-2010-094367 一個bypass的例子,將請求併發同時傳送多次,多次訪問的時候就有幾次漏掉了,沒有觸發waf的攔截。

Ps.作者自己在測試的時候曾經做了如下測試製造了一個payload,同時新增了大量的無效資料,使用指令碼兵法傳送該請求,發現請求的時候有些透過了WAF,有些被WAF所攔截了。應該就是效能問題導致了bypass。

4.2 fuzz bypass

enter image description here

使用指令碼去探測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出其他地方的問題。

5.4.3 白名單bypass

enter image description here

WAF在設計之初一般都會考慮白名單功能。如來自管理IP的訪問,來自cdn伺服器的訪問等等。這些請求是可信任的,不必走WAF檢測流程。

獲取白名單的ip地址如果是從網路層獲取的ip,這種一般bypass不了,如果採用應用層的資料作為白名單,這樣就可能造成bypass。

之前有一篇文章: http://h30499.www3.hp.com/t5/Fortify-Application-Security/Bypassing-web-application-firewalls-using-HTTP-headers/ba-p/6418366#.VGmhx9Yi5Mu

文章內容是透過修改http的header來bypass waf,這裡我們擷取文章中部分內容:

enter image description here

這些header常常用來獲取IP,可能還有其他的,例如nginx-lua-waf:

enter image description here

獲取clientip使用了X-Real-ip的header。

此種方法還可以用來繞過如登陸鎖ip,登陸多次驗證碼,後臺驗證等等的場景。

0x05 結束語


特性就像是一個個特定的場景一樣,一些是已經被研究人員發現的,一些是還沒被發現,等待被研究人員發現的。

隨著一個個特性的發現,WAF的防護能力在web對抗中逐漸增強,在我看來,當所有的特性場景均被WAF考慮到的時候,勢必就會有的新的發現。(如我們現在瞭解的mysql的場景)

因此我們不用擔心當所有的特性被WAF考慮到的時候我們無計可施,未知的特性那麼多,我們還有很多地方可以去挖掘。

當你發現這些姿勢都不好使的時候,你就該去發現一些新的特性了,畢竟設計WAF的選手都是基於目前的認知下去設計的,當新的特性出現的時候,勢必又是一波bypass。

本文章來源於烏雲知識庫,此映象為了方便大家學習研究,文章版權歸烏雲知識庫!

相關文章