前言
WAF(Web Application Firewall?)郁妈,網(wǎng)站應(yīng)用級入侵防御系統(tǒng),通過執(zhí)行一系列針對 HTTP/HTTPS 的安全策略來專門為Web應(yīng)用提供保護(hù)的一款產(chǎn)品趾断。掌握繞過各類 WAF 可以說是滲透測試人員的一項基本技能拒名。
WAF 分為云 WAF、硬件 WAF芋酌、軟件 WAF增显、代碼級 WAF 四類,本文將分別從各自的特性來談一些相關(guān)的繞過技巧脐帝,重點于針對基于規(guī)則類的 WAF 繞過技巧同云。
分類
1 云 WAF
Eg.:加速樂
目前 CDN 服務(wù)的功能越來越多,安全性也越加強悍堵腹,用戶的每個請求都會被發(fā)送到指定的 CDN 節(jié)點上炸站,最后轉(zhuǎn)發(fā)給真實站點。這個過程就好像加了一道關(guān)卡疚顷,這個關(guān)卡提供了緩存旱易、加速、防御的特點腿堤。
繞過關(guān)鍵:查詢真實 IP咒唆,若是直接訪問服務(wù)器的 IP 就不經(jīng)過 CDN 了。
以下四點有助于繞過:
① 查詢歷史DNS(在2016年加入到了cnd節(jié)點里面释液,可以通過查詢2016年之前的dns記錄)
② 查看子域名解析地址是否和主域名的IP地址相近全释。(有些網(wǎng)站只會講主站加入到CDN節(jié)點里面,這時可以查看其二級误债、三級域名的IP地址信息浸船,進(jìn)而猜到主站的IP地址)
③ CDN節(jié)點分發(fā)缺陷。通過國外IP訪問網(wǎng)站可能會出現(xiàn)真實IP寝蹈,因為有的CDN服務(wù)商可能只做了國內(nèi)節(jié)點李命,沒做國外的,這樣訪問請求是直接被轉(zhuǎn)發(fā)到真實服務(wù)器地址上箫老。
④ 讓服務(wù)器主動連接你封字。比如 rss 訂閱服務(wù)或則是向郵箱服務(wù)器發(fā)送個錯誤的郵件比如地址不存在 通過抓包觀察返回的頭來,查找 IP 地址信息。
2 硬件 WAF
Eg:綠盟WAF
3 軟件 WAF
Eg:安全狗
4 代碼級?WAF
所謂代碼級的 WAF 是指程序員在程序內(nèi)部耍鬓,借助自身編寫的過濾函數(shù)來保護(hù)應(yīng)用程序的安全阔籽。以下是三種腳本語言通常會使用的過濾位置:
(1)PHP
在php.ini中設(shè)置
;?Automatically?add?files?before?PHP?document.
;?auto-prepend-fileauto_prepend_file?=
;?Automatically?add?files?after?PHP?document.
;?auto-append-fileauto_append_file?=
配置指令,這些指令指向那些在每個請求的PHP腳本執(zhí)行"之前"和"之后"才執(zhí)行的PHP文件牲蜀。這樣就可以在各種HTTP請求集合(GET,POST,COOKIE)之前對數(shù)據(jù)進(jìn)行一些前發(fā)處理笆制。
(2)asp.net
通過ASP.NET的System.Web.IHttpModule接口來實現(xiàn)
(3)Java
通過filter來實現(xiàn)。比如tomcat會在web.xml的配置文件中配置過濾類涣达。
繞過基于規(guī)則的 WAF
基于規(guī)則的WAF工作原理:
數(shù)據(jù)獲取(注意 get post 等方法以及 post 體方式)—數(shù)據(jù)清洗(去除多余數(shù)據(jù)比如編碼,mssql 支持 unicode 編碼)—規(guī)則匹配—二次校驗
目前市面的大部分 WAF 是通過規(guī)則來實現(xiàn)的在辆,既然是規(guī)則证薇,就一定存在不全面、不準(zhǔn)確的情況匆篓。下面舉幾個例子幫助大家拓展一下思路:
1 封禁 IP
比如有些 WAF 會對重復(fù)的 IP 訪問進(jìn)行封鎖浑度,這時可以用在請求包體中加入? “X-Originating-IP:127.0.0.1”,因為 WAF 不會攔截他自己鸦概。
2 前端?WAF
針對于前端的 WAF俺泣,可以直接通過 burp 抓包繞過。
3 改變?USER-Agent
我們在寫網(wǎng)站防火墻規(guī)則的時候可能都會做一件事:永遠(yuǎn)不屏蔽那些主流搜索引擎機器人的爬韧瓴小(如 Google伏钠,Bing,Yahoo谨设,Baidu 等)熟掂,這時我們就可以在 USER-Agent 偽造自己是搜索引擎的爬蟲,繞過?WAF 扎拣。
4 緩沖區(qū)溢出
比如?WAF?只允許長度是 2M 的包體赴肚,而服務(wù)器則可以接受 8M 的包體,這種情況可以通過發(fā)送 2M-8M 的包體將 WAF 溢出死二蓝。
5 替換關(guān)鍵字
需要考慮?WAF?具體怎么攔截的誉券,Seleselectct,倘若將中間的關(guān)鍵字刪掉刊愚,則可以繞過踊跟。
6 WebServer特性
iis 自動忽略%
我們知道 asp 有兩個特性:
? ? ? ? ① 會將 Request 中的不能編碼部分的 % 去掉,
? ? ? ? ② Request 中如果有unicode部分會將其進(jìn)行解碼鸥诽。
(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 白名單之內(nèi)擴展名的文件 shell.jpg并闲,然后以 shell.jpg.php 進(jìn)行請求细睡。
Nginx 0.8.41~1.5.6:以上 Nginx 容器的版本下,上傳一個在?WAF?白名單之內(nèi)擴展名的文件 shell.jpg帝火,然后以 shell.jpg%20.php 進(jìn)行請求溜徙。
(4)PHP CGI 解析漏洞:
IIS 7.0/7.5 和 Nginx < 0.8.3 以上的容器版本中默認(rèn) php 配置文件 cgi.fix_pathinfo=1 時,上傳一個存在于白名單的擴展名文件 shell.jpg犀填,在請求時以 shell.jpg/shell.php 請求蠢壹,會將 shell.jpg 以 php 來解析。
(5)參數(shù)污染:
比如?WAF?只接受前一個參數(shù)這意味著九巡,通過注入: id=7&id=[SQLi]WAF 的網(wǎng)絡(luò)層會解析 id=7 ,合法 PHP 應(yīng)用層會解析 id=[SQLi] 注入語句成功執(zhí)行图贸。
具體服務(wù)器端處理方式如下
7 數(shù)據(jù)庫特性
MySQL 的特性如下:
(1)隱形類型轉(zhuǎn)換;
(2)為了便利性冕广,犧牲安全性疏日;
如 select * from admin where user=“Admin” 可以執(zhí)行,MySQL 為了 使用的便利性會允許一些“錯誤”撒汉,比如?select * from admin where user=“àdmin” 依然可移執(zhí)行沟优。
(3)MySQL 文件讀取 。
5.5 以上的版本由于 secure_file_priv 這個變量為 null 因此無法使用文件讀取文件寫入的功能睬辐。
8 服務(wù)器特性
(1)Windows 特殊字符:
當(dāng)我們上傳一個文件的 filename 為 shell.php{%80-%99} 時挠阁,WAF?可能識別為 .php{%80-%99},就會導(dǎo)致被繞過溯饵。
(2)NTFS ADS 特性:
ADS是NTFS磁盤格式的一個特性侵俗,用于NTFS交換數(shù)據(jù)流。在上傳文件時丰刊,如果waf對請求正文的filename匹配不當(dāng)?shù)脑捒赡軙?dǎo)致繞過隘谣。
Windows 在創(chuàng)建文件時,在文件名末尾不管加多少點都會自動去除啄巧,那么上傳時 filename 可以這么寫 shell.php...... 洪橘,也可以這么寫 shell.php::$DATA.......。
繞過方法
接下來針對不同類型的漏洞棵帽,具體講解一下新的繞過方法:
1 繞注入
(1)關(guān)鍵字替換
原理:部分 WAF 是通過黑名單來起到攔截的作用熄求,這種情況可以用關(guān)鍵字替換來實現(xiàn)繞過。
比如在 MySQL 中逗概,?WAF?將 sleep() 函數(shù)列入了黑名單弟晚,可以通過具備相同功能的 benchmark() 函數(shù)來實現(xiàn)繞過。以下是部分相同功能的替代函數(shù):
< > 等價于 BETWEEN
= 等價于 like
Hex() bin() 等價于 ascii()
Sleep() 等價于 benchmark()
Mid()substring() 等價于 substr()
@@user 等價于 User()
@@Version 等價于 version()
注:MySQL 支持 && ?|| 逾苫,oracle 不支持 && ||
過濾了 like 和 = 可以用 ?in between 來代替卿城。
(2)特殊符號
原理:結(jié)合不同數(shù)據(jù)庫的特性來實現(xiàn)繞過,最好是可以找到 WAF 開發(fā)者都不了解的某些特性铅搓。
以下是兩個廣為流傳的小特性:
? ? ? ? ① “+”號=空格瑟押, 如select+password+from+mysql.user
? ? ? ? ②“`” 放在 MySQL 的末尾會起到注釋符的作用
(3)編碼
可以結(jié)合各種編碼方式來繞過,比如url編碼星掰,url雙重編碼,十六進(jìn)制編碼多望,unicode編碼嫩舟,數(shù)據(jù)庫編碼等。
舉個栗子:MySQL 默認(rèn)的字符集是 latin怀偷,因此在 php 代碼里面設(shè)置的字符集為 utf-8家厌,這只是客戶端的字符集,因此存在字符集裝換的問題 utf-8—>latin椎工。若傳進(jìn)來的字符集不是完整的字符饭于,則會導(dǎo)致不完整的字符自動會忽略的問題。
如 username=admin%c2 , ? 由于 %c2 不是一個完整的 utf-8 字符 ?因此傳到 MySQL 里面自動忽略了维蒙,導(dǎo)致查出的是 admin 用戶的數(shù)據(jù)掰吕,可以利用這個特性繞過。
(4)注釋符
/*xxx*/ 是注釋颅痊,也可以充當(dāng)空白符殖熟。因為 /**/ 可使得 MySQL 對 SQL 語句 (union/**/select) 詞法解析成功。事實上許多 WAF 都考慮到 /**/ 可以作為空白分八千,但是 WAF 檢測 “/\*.*\*/” 很消耗性能吗讶,工程師會折中,可能在檢測中間引入一些特殊字符恋捆,例如:/*\w+*/照皆。或者沸停,WAF 可能只中間檢查 n 個字符 “/\*.{,n}\*/”膜毁。
根據(jù)以上想法,可以逐步測試?yán)@過方法:
先測試最基本的:
union/**/select
再測試中間引入特殊字:
union/*aaaa%01bbs*/select
最后測試注釋長度:
union/*aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa*/select
(5)空白符繞過
基于正則表達(dá)式的 WAF愤钾, SQL 注入規(guī)則使用正則表達(dá)式的 “\s” 匹配空格瘟滨,例如 “select\s+union”。
利用空白符進(jìn)行繞過能颁,測試 WAF 時盡可能減少其他原因的影響杂瘸,例如 “union select” 被攔截,只需把中間空白符替換為 “%250C”, “%25A0” 進(jìn)行繞過測試伙菊。
union%250Cselect
union%25A0select
函數(shù)分隔符對基于正則表達(dá)式的 WAF败玉,我們猜測安全工程師寫 WAF 規(guī)則時,可能不知道函數(shù)名與左括號之間可以存在特殊字符镜硕,或者遺漏可以存在特殊字符运翼。例如匹配函數(shù)“concat()”的規(guī)則寫法,“concat(”或者”concat\s*(”兴枯,就沒有考慮到一些特殊字符血淌。
concat%2520(
concat/**/(
concat%250c(
concat%25a0(
(6)浮點數(shù)詞法解析
利用 MySQL 解析浮點數(shù)的特點,正則表達(dá)式無法匹配出單詞 union财剖,但是 MySQL 詞法解析成功解析出浮點數(shù)悠夯、SQL 關(guān)鍵字 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 注入函數(shù)非常容易被忽略,導(dǎo)致 WAF 規(guī)則過濾不完整疗疟。常見的函數(shù):
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 繞上傳
關(guān)鍵是:WAF 與?WebServer?的差異( WAF?的局限性與?WebServer?的靈活性)该默。
(1)協(xié)議解析不一致-文件名解析兼容性
multipart 協(xié)議中瞳氓,文件名的形式為 “filename=“abc.php””策彤。但是 Tomcat、PHP 等容器解析協(xié)議時會做一些兼容匣摘,能正確解析 “filename=“abc.php”店诗、“filename=abc.php”、 “filename=‘a(chǎn)bc.php’”音榜。而 WAF 只按照協(xié)議標(biāo)準(zhǔn)去解析庞瘸,無法解析文件名,但是后端容器能正確獲得文件名赠叼,從而導(dǎo)致被繞過擦囊。場景的繞過形式:
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)協(xié)議解析不正確-未解析所有文件
multipart 協(xié)議中,一個 POST 請求可以同時上傳多個文件嘴办。如圖瞬场,許多 WAF 只檢查第一個上傳文件,沒有檢查上傳的所有文件涧郊,而實際后端容器會解析所有上傳的文件名贯被,攻擊者只需把 paylaod 放在后面的文件 PART,即可繞過妆艘。
(3)協(xié)議解析不正確-文件名覆蓋
在 multipart 協(xié)議中彤灶,一個文件上傳塊存在多個 Content-Disposition,將以最后一個 Content-Disposition 的 filename 值作為上傳的文件名批旺。許多WAF解析到第一個 Content-Disposition 就認(rèn)為協(xié)議解析完畢幌陕,獲得上傳的文件名,從而導(dǎo)致被繞過汽煮。
(4)變換位置
因為 WebServer 獲取參數(shù)的靈活性搏熄,所以我嘗試把安全狗攔截的 filename=“test.asp” 換個位置。經(jīng)過一番測試逗物,發(fā)現(xiàn) filename="test.asp" 位于 Content-Type: application/octet-stream
下一行時搬卒,安全狗的上傳攔截便會失效。
(5)文件名覆蓋
在一個 Content-Disposition 中翎卓,存在多個 filename 契邀,協(xié)議解析應(yīng)該使用最后的 filename 值作為文件名。如果 WAF 解析到 filename=“p3.txt” 認(rèn)為解析到文件名失暴,結(jié)束解析坯门,將導(dǎo)致被繞過微饥。因為后端容器解析到的文件名是 t3.jsp。
Content-Disposition: form-data;name=”myfile”; filename=”p3.txt”;filename=”t3.jsp”
(6)遺漏文件名
當(dāng) WAF 遇到 “name=”myfile”;;” 時古戴,認(rèn)為沒有解析到 filename欠橘。而后端容器繼續(xù)解析到的文件名是 t3.jsp,導(dǎo)致 WAF 被繞過现恼。
Content-Disposition: form-data;name=”myfile”;; filename=”t3.jsp”
3 任意文件下載
(1)相對路徑:
WAF 文件包含規(guī)則通常會檢測連續(xù)的 “../”肃续。根據(jù) vfs 解析路徑的語法,解析到 “//” 文件路徑不變叉袍,解析到 “/./” 文件路徑依然始锚。 通過避免連續(xù)的 “../”,從而繞過 WAF 文件包含規(guī)則喳逛。
如:././..///./.././/../etc//passwd瞧捌,它等價于../../../etc/passwd。
(2)絕對路徑:
例如 /etc/./passwd 與 /etc/passwd 是等價的润文。還可以通過組合“/./”姐呐、“//”進(jìn)行繞過。
/etc///.//././/passwd典蝌。
../../../
/etc/passwd ? /etc././././passwd
好消息
易寶 CTO 陳斌翻譯的新書《架構(gòu)真經(jīng)》正在京東和亞馬遜熱賣曙砂!
《架構(gòu)真經(jīng)》:《架構(gòu)即未來》姊妹篇,硅谷大咖的干貨呈現(xiàn)赠法,互聯(lián)網(wǎng)架構(gòu)的50條軍規(guī)麦轰。唐彬、向江旭砖织、葉亞明款侵、段念、吳華鵬侧纯、張瑞海新锈、韓軍、程炳皓眶熬、張云泉妹笆、余晨、李大學(xué)娜氏、霍泰穩(wěn)聯(lián)袂力薦拳缠。