繞過WAF的相關技術研究是WAF***研究很是重要的一部分,也是最有趣的部分,因此我在寫WAF***時先寫***部分。仍是那句老話「不知攻焉知防」,若是連繞過WAF方法都不知道,怎麼保證WAF能保護後端服務的安全。在我看來,WAF的繞過技術的研究將不斷驅動防護水平提升。
php
之前一些WAF bypass的文章更像CASE的整理,都把焦點放在了規則對抗層面。繞過WAF規則,更像是正面對抗,屬於下策。一直關注規則層面的繞過,太侷限視野,看不到WAF在其餘方面問題。木桶原理,防護能力並不會有本質的提升。本文將從4個層次講解bypass WAF的技術,全方位提高WAF的防護能力。 講完相關***技術後,之後再探討WAF的設計架構、防護策略,這樣顯得每一處的考慮都是有意義的。nginx
從架構層Bypass WAF 。正則表達式
從資源限角度bypass WAF。sql
從協議層面bypass WAF。shell
從規則缺陷bypass WAF。數據庫
若是流量都沒有通過WAF,WAF固然沒法攔截***請求。當前多數雲WAF架構,例如百度雲加速、360安全衛士等,經過更改DNS解析,把流量引入WAF集羣,流量通過檢測後轉發請求到源站。如圖,liusscs.com接入接入WAF後,liusscs.comd的DNS解析結果指向WAF集羣,用戶的請求將發送給WAF集羣,WAF集羣通過檢測認爲非***請求再轉發給源站。後端
雲WAF流量路徑tomcat
假設咱們是***者,如何繞過WAF的安全檢測呢? 從雲WAF架構考慮,若是HTTP請求都沒有通過WAF集羣直接到達源站,瓜熟蒂落bypass WAF。因此關鍵在於發現源站的IP地址。經常使用方法以下,可能還有不少不少思路,歡迎補充:安全
1) 信息泄露發現源站IP。信息泄露的途徑不少,細心留言每每能發現。我經常使用的方法以下:服務器
網站頁面註銷是否包含源站IP。
GIHUB源代碼泄露是否包含源站IP。
未接入WAF前,真實IP地址是否被搜索引擎等服務收錄。
2) 窮舉IP地址,根據特徵發現服務器真實IP地址。對於國內的服務器,窮舉國內的IP,訪問每一個IP的HTTP服務,根據頁面特徵檢測響應頁面,判斷IP是否爲源站IP地址。曾經烏雲有人分享過,完成一次國內IP掃描只須要8-9小時,但是如今找不到那篇文章。
一些在雲服務商的站點,同時使用雲服務商提供的WAF服務。當流量不是經過DNS解析引流到WAF,流量必須通過WAF的檢測,這是不能經過發行源站進行繞過。能夠考慮在雲服務商買一臺VPS,經過VPS***目標站點,由於流量是局域網,可能不通過WAF檢測,實現繞過。能不能成功,關鍵在於雲服務商的網絡配置。
***機器與目標機器在同一局域網
若是未能發現源站IP,能夠嘗試尋找子站的×××F漏洞。若是子站訪問目標站不通過WAF集羣,能夠利用×××F漏洞來繞過WAF。
這是衆所周知、而又難以解決的問題。若是HTTP請求POST BODY太大,檢測全部的內容,WAF集羣消耗太大的CPU、內存資源。所以許多WAF只檢測前面的幾K字節、1M、或2M。對於***者而然,只須要在POST BODY前面添加許多無用數據,把***payload放在最後便可繞過WAF檢測。
即便流量都確保通過WAF,若是WAF的防護策略根本就沒有檢測payload,那麼也就能繞過WAF。協議層面繞過WAF,利用WAF解析協議的問題,使得payload被認爲不是請求的HTTP請求的內容。從我的經驗總結出WAF解析協議的常出現問題的三個方向。
協議覆蓋不全。
協議解析不正確。
協議解析與後WEB容器的協議解析不一致。
如下以實例說明利用協議繞過WAF的方法。經過CASE解析什麼是協議覆蓋不全、協議解析不正確、協議解析不一致。
POST 請求經常使用有2種參數提交方式:
Content-Type: application/x-www-form-urlencoded;
Content-Type: multipart/form-data;
Waf未能覆蓋Content-Type: multipart/form-data從而致使被繞過。或者WAF會認爲它是文件上傳請求,從而只檢測文件上傳,致使被繞過。如圖,加速樂的WAF就存在被繞過的狀況,是典型的協議未覆蓋。
普通***請求被攔截
協議未覆蓋致使繞過
之前發的文章《PHP DOS漏洞的新利用》,就是利用協議解析不一致進行繞過WAF。如圖中的payload,WAF解析出來上傳的文件名是test3.jpg,而PHP解析獲得的文件名是shell.php,從而繞過WAF的防護。當時這個方法幾乎通殺全部WAF,可見利用協議層繞過WAF的威力,詳情見:http://weibo.com/ttarticle/p/show?id=2309404002575157473609。就文件上傳而言,還有更多由於協議解析致使繞過,見3.3節。
WAF與PHP解析文件上傳協議不一致致使繞過
WAF的文件上傳規則使用正則表達式匹配上傳的文件名是否包含「0x00」等,因此正面繞過正則表達式匹配幾乎不可能。若是不從規則角度考慮,利用協議解析問題讓WAF沒法匹配到正確的文件名,就能繞過WAF實現文件上傳。
在multipart協議中,一個文件上傳塊存在多個Content-Disposition,將以最後一個Content-Disposition的filename值做爲上傳的文件名。許多WAF解析到第一個Content-Disposition就認爲協議解析完畢,得到上傳的文件名,從而致使被繞過。如圖,加速樂的WAF解析獲得文件名是」sp.pho」,但PHP解析結果是」sp.php」,致使被繞過。
在一個Content-Disposition 中,存在多個filename ,協議解析應該使用最後的filename值做爲文件名。若是WAF解析到filename="p3.txt"認爲解析到文件名,結束解析,將致使被繞過。由於後端容器解析到的文件名是t3.jsp。
Content-Disposition: form-data;name="myfile"; filename="p3.txt";filename="t3.jsp"
當WAF遇到「name=」myfile";;」時,認爲沒有解析到filename。然後端容器繼續解析到的文件名是t3.jsp,致使WAF被繞過。
Content-Disposition: form-data;name="myfile";; filename="t3.jsp"。
multipart協議中,一個POST請求能夠同時上傳多個文件。如圖,許多WAF只檢查第一個上傳文件,沒有檢查上傳的全部文件,而實際後端容器會解析全部上傳的文件名,***者只需把paylaod放在後面的文件PART,便可繞過。
multipart協議中,文件名的形式爲「filename="abc.php"」。可是Tomcat、PHP等容器解析協議時會作一些兼容,能正確解析 」filename="abc.php」、」filename=abc.php」、 」filename='abc.php’」。而WAF只按照協議標準去解析,沒法解析文件名,可是後端容器能正確得到文件名,從而致使被繞過。場景的繞過形式:
Content-Disposition: form-data; name="file"; filename=abc.php
Content-Disposition: form-data; name="file"; filename="abc.php
Content-Disposition: form-data; name="file"; filename='abc.php’
請求中包含2個參數名相同的參數typeid,第一個是正常參數的值正常,第二個參數纔是payload。若是WAF解析參數使用第一個值,沒檢查第二個值,將致使繞過。這是好久好久的一個CASE,如今幾乎沒有WAF存在這個問題。
/forum.php? typeid=644&typeid=if(now()%3dsysdate()%2csleep(19.844)%2c0)/*'XOR(if(now()%3dsysdate()%2csleep(19.844)%2c0))OR'%22XOR(if(now()%3dsysdate()%2csleep(19.844)%2c0))OR%22*/
當想到利用協議解析繞過WAF檢測時,並不敢肯定效果,通過實踐檢驗,協議解析繞過WAF的思路可行且有效。在研究利用協議繞過WAF時,須要大膽地猜想WAF解析協議時容易犯什麼錯誤,科學地一點點驗證。經過分析PHP、tomcat的協議解析源碼,找出它們與HTTP標準協議的差別是發現繞過WAF的快速有效方法。
本節利用multipart/form-data協議解析過問題文件上傳的思路,思路一樣可用於繞過multipart/form-data協議POST FROM表單提交參數的檢測。
對基於正則表達式的WAF,繞過WAF規則主要思考安全工程師寫WAF規則時在想什麼,容易忽略什麼,推斷一些可能繞過的方式,而後屢次嘗試進行驗證。比起完整羅列繞過CASE,我更喜歡分析繞過思路。此次以最受關注的SQL注入、文件包含爲例,分析一下繞過思路。
繞過SQL注入規則主要利用WAF規則自己的問題、未考慮到SQL語法變形、及後端數據庫SQL語句語法特性。不一樣的數據庫雖然遵照SQL標準,可是一般會加入特有的語法。WAF的防護策略要兼顧各類數據庫的特殊語法,容易遺漏,從而被利用繞過WAF。如下MySQL爲例,分析繞過SQL注入的一些思路。
/*xxx*/是註釋,也能夠充當空白符。由於 /**/可以使得MySQL對sql語句(union/**/select)詞法解析成功。事實上許多WAF都考慮到/**/能夠做爲空白分,可是waf檢測 「/\*.*\*/」很消耗性能,工程師會折中,可能在檢測中間引入一些特殊字符,例如:/*\w+*/。或者,WAF可能只中間檢查n個字符「/\*.{,n}\*/」。根據以上想法,能夠逐步測試繞過方法:
先測試最基本的:union/**/select
再測試中間引入特殊字:union/*aaaa%01bbs*/select
最後測試註釋長度:union/*aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa*/select
同理,對於/*!xxx*/,能夠採起相似的思路繞過WAF。
基於正則表達式的WAF, SQL注入規則使用正則表達式的「\s」匹配空格,例如」select\s+union」。利用正則表達式的空白符與MySQL空白符的不一樣可繞過WAF規則。如何這些MySQL的特性?經過fuzz,每次更改正常SQL語句的某部分,替換爲其餘字符,判斷語法是否正確,便可判斷出來MySQL語法特性。固然,也能夠經過分析MySQL詞法來發現語法特性,從而找到繞過方法。
利用空白符進行繞過,測試WAF時儘量減小其餘緣由的影響,例如」union select」被攔截,只需把中間空白符替換爲」%250C」, 「%25A0」進行繞過測試。
union%250Cselect
union%25A0select
對基於正則表達式的WAF,咱們猜想安全工程師寫WAF規則時,可能不知道函數名與左括號之間能夠存在特殊字符,或者遺漏能夠存在特殊字符。例如匹配函數」concat()」的規則寫法,「concat(」或者」concat\s*(」,就沒有考慮到一些特殊字符。相應的繞過方法,在特殊位置引入特殊的分隔符,逐個測試。這些特殊分隔符發現也是經過Fuzz出來的。
concat%2520(
concat/**/(
concat%250c(
concat%25a0(
觸類旁通,尋找相似的關鍵位置,Fuzz特殊字符,發現更多的繞過新方法。猜想工程師們寫規則由於各類緣由容易遺漏的點,進行繞過WAF檢測。
利用MySQL解析浮點數的特色,正則表達式沒法匹配出單詞union,可是MySQL詞法解析成功解析出浮點數、sql關鍵字union。
select * from users where id=8E0union select 1,2,3,4,5,6,7,8,9,0
select * from users where id=8.0union select 1,2,3,4,5,6,7,8,9,0
select * from users where id=\Nunion select 1,2,3,4,5,6,7,8,9,0
Error-based的SQL注入函數很是容易被忽略,致使WAF規則過濾不完整。隨着對MySQL研究愈來愈深,被發現可用於error-based SQL注入的函數愈來愈多,同時也給繞過WAF造就了更多機會。常見的函數:
extractvalue(1, concat(0x5c,md5(3)));
updatexml(1, concat(0x5d,md5(3)),1);
GeometryCollection((select*from(select*from(select@@version)f)x))
polygon((select*from(select name_const(version(),1))x))
linestring()
multipoint()
multilinestring()
multipolygon()
利用Error-based的SQL注入函數進行繞過期,能夠結合函數分隔符,或其餘方法靈活運用。
最有效的發現手段,仍是去讀讀MySQL詞法分析源代碼。和協議繞過相似,挖掘SQL標準與MySQL的詞法分析差別是發現WAF SQL注入繞過的有效手段。如下是MySQL語法的一個特寫(ps:不是我發現的):
select{x table_name}from{x information_schema.tables};
以上都是SQL注入繞過中的技術點,在實際***測試中,須要靈活綜合利用才能達到完整繞過,讀取數據數據。如下給出完整繞過WAF SQ注入檢測的實例。如圖,本例中綜合多個繞過技術點,最終實現完整繞過實現讀取數據。
利用浮點數詞法解析,繞過union select 的檢測。
一樣,函數分隔符思想集和浮點數詞法解析,繞過關鍵字from的檢測。
最後空白分分割繞過INFORMATION_SCHEMA.TABLES的檢查
文件包含分爲相對路徑、絕對路徑文件包含。在相對路徑文件包含中,最終根據Linux虛擬文件系統(vfs)的規則查找文件,經過分析vfs的文件路徑解析規則,提取其中規則特色,用這些特色去繞過WAF。在絕對文件路徑包含中,主要是根據***場景,WAF未過濾一些協議、未過濾某些特殊路徑。
寫WAF文件包含規則時,若是檢測單一的」../」,誤報會很是多,因此WAF文件包含規則一般會檢測連續的「../"。根據vfs解析路徑的語法,解析到「//」文件路徑不變,解析到「/./」文件路徑依然。 經過避免連續的"../",從而繞過WAF文件包含規則。Eg: ././..///./.././/../etc//passwd,它等價於../../../etc/passwd。如圖,一個實際的繞過WAF文件包含的 CASE
WAF沒有考慮到路徑中插入「/./」、「//」對於vfs解析路徑是等價的,致使可被繞過。例如 /etc/./passwd 與 /etc/passwd 是等價的。還能夠經過組合「/./」、「//」進行繞過,eg. /etc///.//././/passwd。
對於絕對路徑文件包含,WAF通常會攔截常見路徑,而不會防護全部的絕對路徑。所以,在***測試中,能夠包含其餘的路徑下一些文件,例如/usr/local/nginx/conf/nginx.conf。
若是WAF只檢測連續的../,檢查開始路徑爲Linux的目錄名,能夠採用/wtt/../繞過WAF文件包含檢測。 例如,「/wtt/../etc/passwd」, wtt不是Linux標準目錄,不會被規則匹配。WAF只檢測連續的../,可是隻使用一個../,不被攔截。最終讀取/etc/passwd文件。
利用WAF未檢測的協議。PHP 文件包含支持的協議,在***測試中,看環境選擇可行的方法
file:// Accessing local filesystem
http:// Accessing HTTP(s) URLs
ftp:// Accessing FTP(s) URLs
php:// Accessing various I/O streams
zlib:// Compression Streams data:// Data (RFC 2397)
glob:// Find pathnames matching pattern
phar:// PHP Archive
ssh2:// Secure Shell 2
rar:// RAR
ogg:// Audio streams
expect:// Process Interaction Streams
一個好WAF不是吹出來的,是實踐檢驗出來的。研究WAF的繞過手段,是爲了更好的提高WAF的防護能力。在研究突破的過程當中,不要僅僅停留在正則表達式,基本漏洞原理,須要對涉及並深刻更多的領域,例如HTTP協議理解和PHP、Tomcat對HTTP協議源碼分析,MySQL詞法分析,和Fuzz的思路等。在此過程當中,會有許多樂趣,也會有各方面能力的提高。
@破-見
http://weibo.com/ttarticle/p/show?id=2309404007261092631700