前言
WAF(Web Application Firewall?),網站應用級入侵防御系統,通過執行一系列針對 HTTP/HTTPS 的安全策略來專門為Web應用提供保護的一款產品。掌握繞過各類 WAF 可以說是滲透測試人員的一項基本技能。
WAF 分為云 WAF、硬件 WAF、軟件 WAF、代碼級 WAF 四類,本文將分別從各自的特性來談一些相關的繞過技巧,重點于針對基于規則類的 WAF 繞過技巧。
分類
1 云 WAF
Eg.:加速樂
目前 CDN 服務的功能越來越多,安全性也越加強悍,用戶的每個請求都會被發送到指定的 CDN 節點上,最后轉發給真實站點。這個過程就好像加了一道關卡,這個關卡提供了緩存、加速、防御的特點。
繞過關鍵:查詢真實 IP,若是直接訪問服務器的 IP 就不經過 CDN 了。
以下四點有助于繞過:
① 查詢歷史DNS(在2016年加入到了cnd節點里面,可以通過查詢2016年之前的dns記錄)
② 查看子域名解析地址是否和主域名的IP地址相近。(有些網站只會講主站加入到CDN節點里面,這時可以查看其二級、三級域名的IP地址信息,進而猜到主站的IP地址)
③ CDN節點分發缺陷。通過國外IP訪問網站可能會出現真實IP,因為有的CDN服務商可能只做了國內節點,沒做國外的,這樣訪問請求是直接被轉發到真實服務器地址上。
④ 讓服務器主動連接你。比如 rss 訂閱服務或則是向郵箱服務器發送個錯誤的郵件比如地址不存在 通過抓包觀察返回的頭來,查找 IP 地址信息。
2 硬件 WAF
Eg:綠盟WAF
3 軟件 WAF
Eg:安全狗
4 代碼級?WAF
所謂代碼級的 WAF 是指程序員在程序內部,借助自身編寫的過濾函數來保護應用程序的安全。以下是三種腳本語言通常會使用的過濾位置:
(1)PHP
在php.ini中設置
;?Automatically?add?files?before?PHP?document.
;?auto-prepend-fileauto_prepend_file?=
;?Automatically?add?files?after?PHP?document.
;?auto-append-fileauto_append_file?=
配置指令,這些指令指向那些在每個請求的PHP腳本執行"之前"和"之后"才執行的PHP文件。這樣就可以在各種HTTP請求集合(GET,POST,COOKIE)之前對數據進行一些前發處理。
(2)asp.net
通過ASP.NET的System.Web.IHttpModule接口來實現
(3)Java
通過filter來實現。比如tomcat會在web.xml的配置文件中配置過濾類。
繞過基于規則的 WAF
基于規則的WAF工作原理:
數據獲取(注意 get post 等方法以及 post 體方式)—數據清洗(去除多余數據比如編碼,mssql 支持 unicode 編碼)—規則匹配—二次校驗
目前市面的大部分 WAF 是通過規則來實現的,既然是規則,就一定存在不全面、不準確的情況。下面舉幾個例子幫助大家拓展一下思路:
1 封禁 IP
比如有些 WAF 會對重復的 IP 訪問進行封鎖,這時可以用在請求包體中加入? “X-Originating-IP:127.0.0.1”,因為 WAF 不會攔截他自己。
2 前端?WAF
針對于前端的 WAF,可以直接通過 burp 抓包繞過。
3 改變?USER-Agent
我們在寫網站防火墻規則的時候可能都會做一件事:永遠不屏蔽那些主流搜索引擎機器人的爬取(如 Google,Bing,Yahoo,Baidu 等),這時我們就可以在 USER-Agent 偽造自己是搜索引擎的爬蟲,繞過?WAF 。
4 緩沖區溢出
比如?WAF?只允許長度是 2M 的包體,而服務器則可以接受 8M 的包體,這種情況可以通過發送 2M-8M 的包體將 WAF 溢出死。
5 替換關鍵字
需要考慮?WAF?具體怎么攔截的,Seleselectct,倘若將中間的關鍵字刪掉,則可以繞過。
6 WebServer特性
iis 自動忽略%
我們知道 asp 有兩個特性:
? ? ? ? ① 會將 Request 中的不能編碼部分的 % 去掉,
? ? ? ? ② Request 中如果有unicode部分會將其進行解碼。
(1)IIS6.0 的解析缺陷:
如果目錄名包含 .asp、.asa、.cer,則該目錄下的所有文件都將按照 asp 解析。
(2)Apache1.X / 2.X 解析漏洞:
Apache 在以上版本中,解析文件名的方式是從后向前識別擴展名,直到遇見 Apache 可識別的擴展名為止。
(3)Nginx 解析漏洞:
Nginx 0.5.*、Nginx 0.6.*、Nginx 0.7 <= 0.7.65、Nginx 0.8 <= 0.8.37:以上 Nginx 容器的版本下,上傳一個在 WAF 白名單之內擴展名的文件 shell.jpg,然后以 shell.jpg.php 進行請求。
Nginx 0.8.41~1.5.6:以上 Nginx 容器的版本下,上傳一個在?WAF?白名單之內擴展名的文件 shell.jpg,然后以 shell.jpg%20.php 進行請求。
(4)PHP CGI 解析漏洞:
IIS 7.0/7.5 和 Nginx < 0.8.3 以上的容器版本中默認 php 配置文件 cgi.fix_pathinfo=1 時,上傳一個存在于白名單的擴展名文件 shell.jpg,在請求時以 shell.jpg/shell.php 請求,會將 shell.jpg 以 php 來解析。
(5)參數污染:
比如?WAF?只接受前一個參數這意味著,通過注入: id=7&id=[SQLi]WAF 的網絡層會解析 id=7 ,合法 PHP 應用層會解析 id=[SQLi] 注入語句成功執行。
具體服務器端處理方式如下
7 數據庫特性
MySQL 的特性如下:
(1)隱形類型轉換;
(2)為了便利性,犧牲安全性;
如 select * from admin where user=“Admin” 可以執行,MySQL 為了 使用的便利性會允許一些“錯誤”,比如?select * from admin where user=“àdmin” 依然可移執行。
(3)MySQL 文件讀取 。
5.5 以上的版本由于 secure_file_priv 這個變量為 null 因此無法使用文件讀取文件寫入的功能。
8 服務器特性
(1)Windows 特殊字符:
當我們上傳一個文件的 filename 為 shell.php{%80-%99} 時,WAF?可能識別為 .php{%80-%99},就會導致被繞過。
(2)NTFS ADS 特性:
ADS是NTFS磁盤格式的一個特性,用于NTFS交換數據流。在上傳文件時,如果waf對請求正文的filename匹配不當的話可能會導致繞過。
Windows 在創建文件時,在文件名末尾不管加多少點都會自動去除,那么上傳時 filename 可以這么寫 shell.php...... ,也可以這么寫 shell.php::$DATA.......。
繞過方法
接下來針對不同類型的漏洞,具體講解一下新的繞過方法:
1 繞注入
(1)關鍵字替換
原理:部分 WAF 是通過黑名單來起到攔截的作用,這種情況可以用關鍵字替換來實現繞過。
比如在 MySQL 中,?WAF?將 sleep() 函數列入了黑名單,可以通過具備相同功能的 benchmark() 函數來實現繞過。以下是部分相同功能的替代函數:
< > 等價于 BETWEEN
= 等價于 like
Hex() bin() 等價于 ascii()
Sleep() 等價于 benchmark()
Mid()substring() 等價于 substr()
@@user 等價于 User()
@@Version 等價于 version()
注:MySQL 支持 && ?|| ,oracle 不支持 && ||
過濾了 like 和 = 可以用 ?in between 來代替。
(2)特殊符號
原理:結合不同數據庫的特性來實現繞過,最好是可以找到 WAF 開發者都不了解的某些特性。
以下是兩個廣為流傳的小特性:
? ? ? ? ① “+”號=空格, 如select+password+from+mysql.user
? ? ? ? ②“`” 放在 MySQL 的末尾會起到注釋符的作用
(3)編碼
可以結合各種編碼方式來繞過,比如url編碼,url雙重編碼,十六進制編碼,unicode編碼,數據庫編碼等。
舉個栗子:MySQL 默認的字符集是 latin,因此在 php 代碼里面設置的字符集為 utf-8,這只是客戶端的字符集,因此存在字符集裝換的問題 utf-8—>latin。若傳進來的字符集不是完整的字符,則會導致不完整的字符自動會忽略的問題。
如 username=admin%c2 , ? 由于 %c2 不是一個完整的 utf-8 字符 ?因此傳到 MySQL 里面自動忽略了,導致查出的是 admin 用戶的數據,可以利用這個特性繞過。
(4)注釋符
/*xxx*/ 是注釋,也可以充當空白符。因為 /**/ 可使得 MySQL 對 SQL 語句 (union/**/select) 詞法解析成功。事實上許多 WAF 都考慮到 /**/ 可以作為空白分,但是 WAF 檢測 “/\*.*\*/” 很消耗性能,工程師會折中,可能在檢測中間引入一些特殊字符,例如:/*\w+*/。或者,WAF 可能只中間檢查 n 個字符 “/\*.{,n}\*/”。
根據以上想法,可以逐步測試繞過方法:
先測試最基本的:
union/**/select
再測試中間引入特殊字:
union/*aaaa%01bbs*/select
最后測試注釋長度:
union/*aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa*/select
(5)空白符繞過
基于正則表達式的 WAF, SQL 注入規則使用正則表達式的 “\s” 匹配空格,例如 “select\s+union”。
利用空白符進行繞過,測試 WAF 時盡可能減少其他原因的影響,例如 “union select” 被攔截,只需把中間空白符替換為 “%250C”, “%25A0” 進行繞過測試。
union%250Cselect
union%25A0select
函數分隔符對基于正則表達式的 WAF,我們猜測安全工程師寫 WAF 規則時,可能不知道函數名與左括號之間可以存在特殊字符,或者遺漏可以存在特殊字符。例如匹配函數“concat()”的規則寫法,“concat(”或者”concat\s*(”,就沒有考慮到一些特殊字符。
concat%2520(
concat/**/(
concat%250c(
concat%25a0(
(6)浮點數詞法解析
利用 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
(7)報錯注入
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()
2 繞上傳
關鍵是:WAF 與?WebServer?的差異( WAF?的局限性與?WebServer?的靈活性)。
(1)協議解析不一致-文件名解析兼容性
multipart 協議中,文件名的形式為 “filename=“abc.php””。但是 Tomcat、PHP 等容器解析協議時會做一些兼容,能正確解析 “filename=“abc.php”、“filename=abc.php”、 “filename=‘abc.php’”。而 WAF 只按照協議標準去解析,無法解析文件名,但是后端容器能正確獲得文件名,從而導致被繞過。場景的繞過形式:
Content-Disposition: form-data; name=”file”; filename=bc.php
Content-Disposition: form-data; name=”file”; filename=”abc.php
Content-Disposition: form-data; name=”file”; filename=’abc.php’
(2)協議解析不正確-未解析所有文件
multipart 協議中,一個 POST 請求可以同時上傳多個文件。如圖,許多 WAF 只檢查第一個上傳文件,沒有檢查上傳的所有文件,而實際后端容器會解析所有上傳的文件名,攻擊者只需把 paylaod 放在后面的文件 PART,即可繞過。
(3)協議解析不正確-文件名覆蓋
在 multipart 協議中,一個文件上傳塊存在多個 Content-Disposition,將以最后一個 Content-Disposition 的 filename 值作為上傳的文件名。許多WAF解析到第一個 Content-Disposition 就認為協議解析完畢,獲得上傳的文件名,從而導致被繞過。
(4)變換位置
因為 WebServer 獲取參數的靈活性,所以我嘗試把安全狗攔截的 filename=“test.asp” 換個位置。經過一番測試,發現 filename="test.asp" 位于 Content-Type: application/octet-stream
下一行時,安全狗的上傳攔截便會失效。
(5)文件名覆蓋
在一個 Content-Disposition 中,存在多個 filename ,協議解析應該使用最后的 filename 值作為文件名。如果 WAF 解析到 filename=“p3.txt” 認為解析到文件名,結束解析,將導致被繞過。因為后端容器解析到的文件名是 t3.jsp。
Content-Disposition: form-data;name=”myfile”; filename=”p3.txt”;filename=”t3.jsp”
(6)遺漏文件名
當 WAF 遇到 “name=”myfile”;;” 時,認為沒有解析到 filename。而后端容器繼續解析到的文件名是 t3.jsp,導致 WAF 被繞過。
Content-Disposition: form-data;name=”myfile”;; filename=”t3.jsp”
3 任意文件下載
(1)相對路徑:
WAF 文件包含規則通常會檢測連續的 “../”。根據 vfs 解析路徑的語法,解析到 “//” 文件路徑不變,解析到 “/./” 文件路徑依然。 通過避免連續的 “../”,從而繞過 WAF 文件包含規則。
如:././..///./.././/../etc//passwd,它等價于../../../etc/passwd。
(2)絕對路徑:
例如 /etc/./passwd 與 /etc/passwd 是等價的。還可以通過組合“/./”、“//”進行繞過。
/etc///.//././/passwd。
../../../
/etc/passwd ? /etc././././passwd
好消息
易寶 CTO 陳斌翻譯的新書《架構真經》正在京東和亞馬遜熱賣!
《架構真經》:《架構即未來》姊妹篇,硅谷大咖的干貨呈現,互聯網架構的50條軍規。唐彬、向江旭、葉亞明、段念、吳華鵬、張瑞海、韓軍、程炳皓、張云泉、余晨、李大學、霍泰穩聯袂力薦。