在进行sql注入测试中总会遇到各种厂商的waf,本篇文章将对waf的过滤机制,以及常见的绕过方法进行介绍,希望在以后的测试中会对大家有所帮助。


0x01 WAF的过滤机制

   WAF全称网站应用级***防御系统是Web Application Firewall的简称,主要有以下四个功能:
1. 审计设备--用来截获所有HTTP数据或者仅仅满足某些规则的会话 ;
2. 访问控制设备--用来控制对Web应用的访问既包括主动安全模式和被动安全模式 ;
3. 架构/网络设计工具--运行在反向代理模式用来分配职能集中控制虚拟基础结构等;
4. WEB应用加固工具--增强被保护Web应用的安全性它不仅能够屏蔽WEB应用固有弱点而且能够保护WEB应用编程错误导致的安全隐患等。


   WAF主要有以下过滤机制:
1.异常检测协议--拒绝不符合HTTP标准的请求;
2.增强的输入验证--代理和服务端的验证而不只是限于客户端验证;
3.白名单&黑名单机制--白名单适用于稳定的Web应用,黑名单适合处理已知问题;
4.基于规则和基于异常的保护--基于规则更多的依赖黑名单机制基于,基于异常根据系统异常更为灵活;
5.另外还有会话保护、Cookies保护、抗***规避技术、响应监视和信息泄露保护等。


0x02 WAF的绕过姿势


1、大小写绕过

大小写绕过用于只针对小写或大写的关键字匹配技术。正则表达式/express/i 匹配时大小写不敏感便无法绕过这是最简单的绕过技术,不过现在直接使用这种绕过技术成功的可能性已经不高了。
http://www.xx.com/index.php?page_id=-15 uNIoN sELecT 1,2,3,4


2、替换关键字

这种情况下大小写转化无法绕过而且正则表达式会替换或删除select、union这些关键字如果只匹配一次就很容易绕过
http://www.xx.com/index.php?page_id=-15 UNIunionON SELselectECT 1,2,3,4
替换关键字同样是很基础的技术也可以构造得更复杂SeLSeselectleCTecT关键要看正则表达式会进行几次匹配处理了。


3、编码绕过

(1)url编码绕过
浏览器会对链接的非保留字字符进行URL编码,如空格变为%20、单引号%27、左括号%28、右括号%29,普通的URL编码可能无法实现绕过,不过存在某种情况URL编码只进行了一次解码过滤可以使用两次编码绕过。
test.php?id=1%252f%252a*/UNION%252f%252a/SELECT


(2)十六进制编码绕过
使用16进制对某些敏感参数、方法等进行编码来绕过waf的检测.
http://www.xx.com/index.php?page_id=-15/*!u%6eion*//*!se%6cect*/1,2,3,4,SELECT(extractvalue(0x3C613E61646D696E3C2F613E,0x2f61))

示例代码中前面是对单个字符十六进制编码,后面则是对整个字符串编码。


(3)Unicode编码绕过
Unicode有所谓的标准编码和非标准编码假设我们用的utf-8为标准编码那么西欧语系所使用的就是非标准编码了


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


绕过举例:

示例中前者利用双字节绕过,比如对单引号转义操作变成\',那么就变成了%D6%5C',%D6%5C构成了一个宽字节即Unicode字节,转义符号直接被吃掉,单引号就可以正常使用了;第二个示例使用的是两种不同编码的字符的比较,它们比较的结果可能是True或者False,关键在于Unicode编码种类繁多,基于黑名单的过滤器存在无法处理的情况,从而实现绕过。


4、使用注释绕过

首先看一下常见的用于注释的符号:


(1)普通注释绕过
使用/**/在构造的查询语句中插入注释来规避对空格的依赖或关键字识别,#、--用于终结语句的查询。
http://www.xx.com/index.php?page_id=-15 %55nION/**/%53ElecT 1,2,3,4 'union%a0select pass from users#


(2)内联注释绕过
相比普通注释内联注释用的更多,/!content/只有MySQL会正常识别content的内容。

两个示例中前者使用内联注释后者还用到了普通注释。


5、等价函数字符替换绕过

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


(1)等价函数


举例substring()和substr()无法使用时:


或者:


上述这几个示例用于说明有时候当某个函数不能使用时还可以找到其他的函数替代其实现


(2)等价符号
and和or不能使用可以尝试下&&和||,还有=不能使用的情况可以考虑尝试<、>因为如果不小于又不大于那便是等于。
很多的空格可以使用如下符号代替其使用:


(3)生僻函数
各类数据库都有许多自己独有的函数和方法,WAF要想全部涵盖实际上不大可能,在某些情况下可以尝试一下生僻函数进行绕过。例如MySQL/PostgreSQL支持的XML函数:


6、使用特殊符号绕过

经常使用的特殊符号:
1.使用反引号`,例如select `version()`,可以用来过空格和正则,特殊情况下还可以将其做注释符用 ;
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; //绕过空格限制;
5.如果匹配sql注入的正则表达式中使用了多行匹配模式则可以使用%0a换行符进行绕过。
使用这些字符的能做很多事,下面是一些示例:
关键字拆分:

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

最后再给出一些和这些字符多少有点关系的操作符供参考

使用这些"特殊符号"实现绕过是一件很细微的事情,一方面各数据库对符号的处理是不尽相同,另一方面你得充分了解这些符号的特性和使用方法才能会考虑利用其实现绕过。


7、使用语言服务自身的特性绕过

(1)HPP(HTTP Parameter Polution)
举例:
/?id=1;select+1&id=2,3+from+users+where+id=1
/?id=1/**/union/*&id=*/select/*&id=*/pwd/*&id=*/from/*&id=*/users
HPP又称做重复参数污染最简单的就是?uid=1&uid=2&uid=3对于这种情况不同的Web服务器处理方式如下

具体WAF如何处理要看其设置的规则,不过就示例中最后一个来看有较大可能绕过。

(2)HPF(HTTP Parameter Fragment)
这种方法是HTTP分割注入同CRLF略有相似之处(使用控制字符%0a、%0d等换行)。
举例:
/?a=1+union/*&b=*/select+1,pass/*&c=*/from+users--
select * from table where a=1 union/* and b=*/select 1,pass/* limit */from users
看完上面两个示例发现和HPP最后一个示例很像,不同之处在于参数不一样,这里是在不同的参数之间进行分割结果到了数据库执行查询时再合并语句。

(3)HPC(HTTP Parameter Contamination)
这一概念见于Beyond SQLi: Obfuscate and Bypass这里Contamination意为污染。


RFC2396定义了如下一些字符:
Unreserved: a-z, A-Z, 0-9 and _ . ! ~ * ' () 
Reserved : ; / ? : @ & = + $ , 
Unwise : { } | \ ^ [ ] `


不同的Web服务器处理处理构造得特殊请求时有不同的逻辑


以魔术字符%为例Asp/Asp.net会受到影响 :


0x03 总结


       在实际情况中,各种单一的绕过技术可能无法绕过过滤机制,但是有时多种技术的配合使用成功的可能性就会增加不少了。本文中暂时先列举出这几种比较常见的绕过姿势供大家参考。


原文:https://security.yirendai.com/news/share/15