常見的WAF繞過方法 (從網絡架構層、HTTP協議層、第三方應用層分析)
本篇文章通過 網絡架構層、HTTP協議層、第三方應用層講解了繞過WAF的常見方法
一、網絡架構層
一般通過域名指向云WAF地址后反向實現代理,找到這些公司的服務器的真實IP即可實現繞過
具體方法如下:
1、查找相關的二級域名及同一域名注冊者的其他域名解析記錄。
2、通過查看郵件MX解析記錄來發現真實服務器的IP記錄或網段,例如:
windows可以執行命令:
nslookup -qt=mx baidu.com
Linux可以執行如下命令來查看baidu.com域名的MX解析IP地址
dig mx baidu.com
3、查看域名的歷史解析記錄。實現該操作的網站:
https://securitytrails.com/
4、使用zmap等快速掃描工具對全網IP進行掃描以找到網站真實IP。
5、利用SSRF漏洞反向連接的IP獲取網站真實IP。
二、HTTP協議層
可以利用WAF、web serverweb語言解析引警這三方對標準HTTP解析的差異來實現繞過
具體繞過的方法如下:
1、利用某些硬件WAF對SSL加密算法的支持不夠進行繞過。
參考文章:
通過濫用SSL/TLS繞過Web應用程序防火墻
https://blog.pwn.al/waf/bypass/ssl/2018/07/02/web-application-firewall-bypass.html
對應的測試腳本:
abuse-ss-bypass-waf
https://link.csdn.net/?target=https%3A%2F%2Fgithub.com%2FLandGrey%2Fabuse-ssl-bypass-waf
2、利用HTTP協議版本來進行繞過
HTTP發展至今,已由1991年的0.9版發展到2015年的2.0版,由于不支持相關協議的WAF在解析數據包時會出問題,因此通過發送不同版本協議的粘包即可繞過某些WAF。
3、利用URL編碼、charset編碼、MIME編碼等進行繞過。
ISASP支持類似Unicode%u0027的編碼,還會對不合法的URL編碼進行字符刪除。IISASP對s%elect 編碼的處理結果為select,而
Nginx的ngx_unescape_uri函數對它的解碼結果為slect。Nginx的ngx unescape_uri函數在處理%編碼時,如果%后面的第一個字符不在十六進制范圍內,則會丟棄%;否則判斷第二個字符是否在十六進制范圍內,如果不在則會丟棄%和 第一個字符。
HTTP請求頭Content-Type的charset編碼可以指定內容編碼,這個值一般都是UTF-8編碼的,但惡意攻擊者可以指定使用ibm037、 ibm500、cp875、ibm1026等不常用的編碼來進行繞過。例如,可以設置Content-Type頭的值為application/x-www-form-
urlencoded;charset=ibm500或 multipart/form-data;charset=ibm500,boundary=blah等。這里使用Burpsuite的HTTP Request Smuggler插件可以簡化數據包的修改操作。
在Spring中,如果上傳的文件名以=?開始并以?=結束,則調用MimeDelegate.decode來對文件名解碼。MIME是郵件協議中用到的編碼方式,這里我們可以將上傳文件名改為=2UTF-82B?YS5gc3A=?=UTF-8代表字符編碼,?B?代表后面的YS50c3A=是base64編碼的。經過
Sprina解碼得到的文件名是aisp,而一般的WAF如果之前沒有經過處理,那么就會出現在WAF中上傳文件名過濾被繞過的問題。
4、利用對上傳協議multipart/form-data的不規范解析進行繞過。
以PHP Web Server對multipart/form-data的解析作為例子。
由于該協議對PHP對解析存在缺陷、使得如果一行有多個filename字段值,則PHP Web Server會取最后一個filename值,如下所示:
Content-Disposition: form-data; name="file1"; filename="a.txt";filename="a.php";
PHP Web Server最終得到的文件名是aphp,而某些WAF只判新第一個filename的值,因此WAF對上傳的文件的過濾檢測功能會被黑客繞過,并且這里的form-data可有可無,將其去掉也不影響PHP Web Server獲取 filename .
此外,filename的編碼還受HTTP請求Content-Type頭中charset的影響,PHPWebServer可以根據這個值進行解碼處理。這些都有可能被一些人稍微做點手腳,便可以繞過不少WAF的文件上傳過濾檢測功能。
5、其他協議的繞過
URI解析繞過:
有些WAF可以處理對URI不兼容的繞過,如:
GET /xxx/a.isp?x= &id=union%20a11%20select%20adversion HTTP/1.1
將HTTP原始數據包的"x="后面設置為空格,某些硬件WAF就會忽略后面的&id=union%20al1%20select%200aversion參數從而繞過 WAF。
還可以利用一些較少用到的HTTP處理來繞過,例如在HTTP請求body chunked 編碼時進行注釋及變形。
利用HTTPHost頭也可以繞過一些基于域名防護的WAF,一般的Host頭字符串中不包含端口信息,如":80"或":443”,域名也可以用本地Host來代替,可以有如下寫法:
Host:localhost:80 Host:127.0.0.1:80
除此外,基于協議的繞過還有很多,如HPP復參繞過、參數名的特殊字符轉換繞過等。
三、第三方應用層
第三方應用層主要有數據庫、系統命令、第三方組件等組成部分。下面對這3部分的繞過進行具體說明。
1、數據庫的繞過
數據庫的繞過方式極多,有注釋繞過、編碼繞過、不同數據庫對空格的不同定義繞過等。
利用MySQL的版本號注釋(/*!)功能繞過WAF的情況最多,還有一些方法也可以繞過WAF,比如,利用0xA0代替空格也能繞過一些
WAF,利用\和e浮點等特殊用法繞過WAF(繞過一些如union的關鍵字),以及利用&&代替and等關鍵字和大括號注釋(如union select{x 1],xx)繞過WAF等。
在MySQL中,從0x01至0x0F的字符都可以代表空格。通過注釋加換行也可以繞過一些WAF過濾,比如。1%23%0AAND%23%0A1=1%23經過URL解碼后是#字符,#字符是MySQL中的注釋符,%0A經過URL解碼后是換行符);還有利用""和"。"特殊符號進行繞過的,如:
union select xx from.table union select:top 1 from and:xx
另外,利用exec編碼也可以繞過關鍵字,如:
and 1-0;declare @s varchar(4000) set @5=cast(0x44524f50205441424c4520544d505f44423b as varchar(4000));exec(@S);--
更多有關數據庫的繞過可以參考sglmap的temper插件,插件地址為:https://aithub.com/sglmapproject/salmap/tree/master/tamper
2、系統命令的繞過
以cat /etc/passwd命令為例,在Linux bash環境下去掉空格的寫法如下:
cat lcat,/etc/passwd] cat$IFS/etc/passwd X=$'cat\x20/etc/passwd'&&sx
以ping baidu.com為例,在windows中替換空格的寫法如下:
ping%CommonProgramFiles:10.-18%baidu.com ping%PROGRAMFILES:~10,-5%baidu.com
在Linux的bash環境下想要繞過關鍵字,則可以插入成對的單引號、雙引號或反引號,其中反引號必須連著寫,比如可以將cat/etc/passwd 寫為以下形式:
c'a't /etc/pass'"wd c""at /e't'c/pass""wd c""at /e't'c/pas~~s*wd
另外,也可以在shell命令的任意位置插入$,或者在單詞結尾處插入$x,這里的x可以是任意字母,例如可以寫成如下形式:
另外,也可以在shell命令的任意位置插入$@,或者在單詞結尾處插入$x,這里的x可以是任意字母,例如可以寫成如下形式
c$@at /e$@tc/pass@swd cat$x /etc$x/passwdsx cas@t /etc$x/passwd$x
若通過編碼繞過關鍵字,則可以將cat/etc/passwd進行base64編碼,寫法如下:
echo Y2F0IC91dGMvcGFzc3dklbase64 -dlsh
若通過通配符繞過關鍵字,則linuxbash的通配符與windows的類似,支持使用?代表單個字符和使用*代表多個字符的寫法.如/bin/cat/etc/passwd 命令可以有以下寫法:
/b??/ca? /e?c/pas?wd /b*/ca* /et*/pas*d /b??/can /e?c/pas*d
除此之外,還可以通過一些腳本執行引擎,如perl、python、nodejs、php、java等來繞過WAF關鍵字,相關寫法如下:
perl -e 'sa "ca" Sb="t /et".sc="c/pas".exec sa.sb.sou"swd"."
python -c 'import subprocess;subprocess.call(["ca"+"t","/et"+"c/pa"+"sswd"1);"3 php -r 'exec("ca"."t /et"."c/pa"."sswd");"
3、第三方組件的繞過
一般來說,WAF會用到的第三方組件有PCRE、ISAPI、Libinjection等。
PCRE在處理正則表達式時,為了防止ReDoS正則表達式拒絕服務攻擊,提供了PCRE EXTRA MATCH LIMIT 和
PCRE EXTRA MATCH LIMIT RECURSION選項來限制匹配次數。PCRE EXTRA MATCH LIMIT 的值默認為100萬, PCRE EXTRA MATCH LIMIT 可以限制匹配的總次數;而PCRE EXTRA MATCH LIMIT RECURSION主要限制匹配遞歸次數,并不是所有匹配都存在遞歸,所以該值在小于 PCRE EXTRA MATCH LIMIT 值時才有意義
有些WAF為了防止ReDoS都會將PCRE EXTRA MATCH LIMIT 設置為比默認值更小的值,加入將WAF過濾SQL語句的正則表達式寫成:
/UNION.+?SELECT/i
而此時PCRE EXTRA MATCH LIMIT的值為100萬,那么要繞過WAF過濾防護的SQL語句可以寫成:
union/*aaa..*/select
這里被注釋掉的字符a有100萬個,很容易滿足PCRE EXTRA MATCHLIMIT的值為100萬的限制條件,而且這些字符的數據量大小不到1MB,不會占用太多空間。根據此方法可以繞過很多類似的WAF正則規則。
SAPI是IIS提供的一套編寫API的插件,ISAPI filter可以對請求頭中的數據進行過濾,ISAPIextension可以獲取請求的body數據,對應的原型為HttpExtensionProc(EXTENSION CONTROL BLOCK*pECB)。這里可以通過pECB->lpbData獲取到post請求的body部分的數據,但最大只能存儲48kb的數據。總的大小可以通過pECB->cbTotalBytes獲取,超過48kb的數據的同步函數調用方式可以通過pECB->ReadClient(...)獲取,異步函數調用方式可以通過pECB->ServerSupportFunction(...,HSE REO ASYNC READ CLIENT....)獲取。
但是,這樣在SAP插件的WAF中讀取超過48kb的數據會導致后面的ASP獲取不了多干48kb的數據,因此很多基干ISAPI的IIS WAF都可以通過把攻擊數據放到48kb外而繞過WAF防護。如果某post參數id存在SQL注入,那么我們可以填充48kb的無用數據后再寫注入語句,如下所示:
x=aaa...a&id=1%20union%20a11%20select%201,1,1,1@dversion,1
其中,上面的a字符所占用的空間超過了48kb
ibiniection被應用于很多WAF中,知名的有modsecurity。因為Libiniection只是對SQL語句進行標簽化(token化),然后對被標簽化的字
符串進行匹配,所以同一種繞過方法通常可以繞過很多SQL注入語句的過濾規則。
利用不常用的SQL函數可以繞過Libinjection過濾,比如用mod(3.2)代替1的SQL語句可以寫為:
mod(3,2) union select mod(3,2),usr,pwd from user --
通過使用Fuzz測試技術也可以繞過Libinjection過濾,例如插入1<@到SQL語句中可以繞過Libinjection防護,此方法也可以繞過某些WAF的SQL注入語義檢測引擎。相關的Python腳本地址為:https//wafninja/libinjection-fuzz-to-bypass/
通過大括號可以繞過Libinjection過濾,MySQL支持(identifier expr)這種兼容ODBC的轉義寫法,對應的可繞過Libinjection過濾的 SQL語句如下所示:
1'<@=1 or {x (select 1)} --
1 and{`if`updatexml (1,concat (0x3a,(select /*!50000(/*!50000schema_name) from/*!50000information_schema*/.schemata limit 0,1)),1)} --
四、總結
總的來說,在WAF上只要善于挖掘,總能找出各式各樣的繞過方法。