SQL注入最易懂教程

目前大多数网站都会考虑对网站做些防护措施,无论是在web程序的代码层面,还是在web服务器层面,或者是在网络层面,都有些手段对web应用进行防护。

我们把这些所有的防护手段都可以称为WAF,而web的全称就是

Web application firewall(网站应用防火墙)

对于攻防的对抗一刻也没有停歇,绕过WAF的相关技术研究是WAF攻防研究非常重要的一部分,也是最有趣的部分。

本文我们将从4个层次讲解waf的绕过技术。

从架构层绕过 WAF

从资源限角度绕过 WAF

从协议层面绕过 WAF

从规则缺陷绕过 WAF

1. 架构层绕过WAF

1.1 寻找源站

如果流量都没有经过WAF,WAF当然无法拦截攻击请求。当前多数云WAF架构,例如百度云加速、360安全卫士等,通过更改DNS解析,把流量引入WAF集群,流量经过检测后转发请求到源站。如图,liusscs.com接入接入WAF后,liusscs.comd的DNS解析结果指向WAF集群,用户的请求将发送给WAF集群,WAF集群经过检测认为非攻击请求再转发给源站。

云WAF流量路径

假设我们是攻击者,如何绕过WAF的安全检测呢? 从云WAF架构考虑,如果HTTP请求都没有经过WAF集群直接到达源站,顺理成章bypass WAF。所以关键在于发现源站的IP地址。常用方法如下,可能还有很多很多思路,欢迎补充:

1) 信息泄露发现源站IP。信息泄露的途径很多,细心留言往往能发现。我常用的方法如下:

网站页面注销是否包含源站IP

GIHUB源代码泄露是否包含源站IP

未接入WAF前,真实IP地址是否被搜索引擎等服务收录

2) 穷举IP地址,根据特征发现服务器真实IP地址。对于国内的服务器,穷举国内的IP,访问每个IP的HTTP服务,根据页面特征检测响应页面,判断IP是否为源站IP地址。曾经乌云有人分享过,完成一次国内IP扫描只需要8-9小时,可是现在找不到那篇文章。

1.2 利用同网段

一些在云服务商的站点,同时使用云服务商提供的WAF服务。当流量不是通过DNS解析引流到WAF,流量必须经过WAF的检测,这是不能通过发行源站进行绕过。可以考虑在云服务商买一台VPS,通过VPS攻击目标站点,因为流量是局域网,可能不经过WAF检测,实现绕过。能不能成功,关键在于云服务商的网络配置。

攻击机器与目标机器在同一局域网

1.3 利用边界漏洞

如果未能发现源站IP,可以尝试寻找子站的SSRF漏洞。如果子站访问目标站不经过WAF集群,可以利用SSRF漏洞来绕过WAF。

2. 资源限制角度绕过WAF

这是众所周知、而又难以解决的问题。如果HTTP请求POST BODY太大,检测所有的内容,WAF集群消耗太大的CPU、内存资源。因此许多WAF只检测前面的几K字节、1M、或2M。对于攻击者而然,只需要在POST BODY前面添加许多无用数据,把攻击payload放在最后即可绕过WAF检测。

3. 协议层面绕过WAF的检测

即使流量都确保经过WAF,如果WAF的防御策略根本就没有检测payload,那么也就能绕过WAF。协议层面绕过WAF,利用WAF解析协议的问题,使得payload被认为不是请求的HTTP请求的内容。从个人经验总结出WAF解析协议的常出现问题的三个方向。

协议覆盖不全

协议解析不正确

协议解析与后WEB容器的协议解析不一致

以下以实例说明利用协议绕过WAF的方法。通过CASE解析什么是协议覆盖不全、协议解析不正确、协议解析不一致。

3.1 协议未覆盖绕过WAF

POST 请求常用有2种参数提交方式:

Content-Type: application/x-www-form-urlencoded;

Content-Type: multipart/form-data;

Waf未能覆盖Content-Type: multipart/form-data从而导致被绕过。或者WAF会认为它是文件上传请求,从而只检测文件上传,导致被绕过。

3.2 利用协议解析不一致绕过WAF的典型例子

以前发的文章《PHP DOS漏洞的新利用》,就是利用协议解析不一致进行绕过WAF。如图中的payload,WAF解析出来上传的文件名是test3.jpg,而PHP解析得到的文件名是shell.php,从而绕过WAF的防御。当时这个方法几乎通杀所有WAF,可见利用协议层绕过WAF的威力,详情见:http://weibo.com/ttarticle/p/show?id=2309404002575157473609。就文件上传而言,还有更多因为协议解析导致绕过,见3.3节。

3.3 利用协议解析问题绕过WAF文件上传

WAF的文件上传规则使用正则表达式匹配上传的文件名是否包含“0x00”等,所以正面绕过正则表达式匹配几乎不可能。如果不从规则角度考虑,利用协议解析问题让WAF无法匹配到正确的文件名,就能绕过WAF实现文件上传。

3.3.1 协议解析不正确-文件名覆盖(一)

在multipart协议中,一个文件上传块存在多个Content-Disposition,将以最后一个Content-Disposition的filename值作为上传的文件名。许多WAF解析到第一个Content-Disposition就认为协议解析完毕,获得上传的文件名,从而导致被绕过。如图,加速乐的WAF解析得到文件名是”sp.pho”,但PHP解析结果是”sp.php”,导致被绕过。

3.3.2 协议解析不正确-文件名覆盖(二)

在一个Content-Disposition 中,存在多个filename ,协议解析应该使用最后的filename值作为文件名。如果WAF解析到filename=”p3.txt”认为解析到文件名,结束解析,将导致被绕过。因为后端容器解析到的文件名是t3.jsp。

Content-Disposition: form-data;name=”myfile”; filename=”p3.txt”;filename=”t3.jsp”

3.3.3 协议解析不正确-遗漏文件名

当WAF遇到“name=”myfile”;;”时,认为没有解析到filename。而后端容器继续解析到的文件名是t3.jsp,导致WAF被绕过。

Content-Disposition: form-data;name=”myfile”;; filename=”t3.jsp”。

3.3.4 协议解析不正确-未解析所有文件

multipart协议中,一个POST请求可以同时上传多个文件。如图,许多WAF只检查第一个上传文件,没有检查上传的所有文件,而实际后端容器会解析所有上传的文件名,攻击者只需把paylaod放在后面的文件PART,即可绕过。

3.3.5 协议解析不一致-文件名解析兼容性

multipart协议中,文件名的形式为“filename=”abc.php””。但是Tomcat、PHP等容器解析协议时会做一些兼容,能正确解析 ”filename=”abc.php”、”filename=abc.php”、 ”filename=’abc.php’”。而WAF只按照协议标准去解析,无法解析文件名,但是后端容器能正确获得文件名,从而导致被绕过。场景的绕过形式:

Content-Disposition: form-data; name=”file”; filename=abc.php

Content-Disposition: form-data; name=”file”; filename=”abc.php

Content-Disposition: form-data; name=”file”; filename=’abc.php’

3.4 参数污染

请求中包含2个参数名相同的参数typeid,第一个是正常参数的值正常,第二个参数才是payload。如果WAF解析参数使用第一个值,没检查第二个值,将导致绕过。这是很久很久的一个CASE,现在几乎没有WAF存在这个问题。

/forum.php? typeid=644&typeid=if(now()%3dsysdate()%2csleep(19.844)%2c0)/*'XOR(if(now()%3dsysdate()%2csleep(19.844)%2c0))OR'%22XOR(if(now()%3dsysdate()%2csleep(19.844)%2c0))OR%22*/3.5 小结

当想到利用协议解析绕过WAF检测时,并不敢确定效果,经过实践检验,协议解析绕过WAF的思路可行且有效。在研究利用协议绕过WAF时,需要大胆地猜测WAF解析协议时容易犯什么错误,科学地一点点验证。通过分析PHP、tomcat的协议解析源码,找出它们与HTTP标准协议的差异是发现绕过WAF的快速有效方法。

本节利用multipart/form-data协议解析过问题文件上传的思路,思路同样可用于绕过multipart/form-data协议POST FROM表单提交参数的检测。

4. 规则层面的绕过

对基于正则表达式的WAF,绕过WAF规则主要思考安全工程师写WAF规则时在想什么,容易忽略什么,推断一些可能绕过的方式,然后多次尝试进行验证。比起完整罗列绕过CASE,我更喜欢分析绕过思路。这次以最受关注的SQL注入、分析一下绕过思路。

绕过SQL注入规则主要利用WAF规则本身的问题、未考虑到SQL语法变形、及后端数据库SQL语句语法特性。不同的数据库虽然遵守SQL标准,但是通常会加入特有的语法。WAF的防御策略要兼顾各种数据库的特殊语法,容易遗漏,从而被利用绕过WAF。以下MySQL为例,分析绕过SQL注入的一些思路

4.1 注释符绕过

/*xxx*/是注释,也可以充当空白符。因为 /**/可使得MySQL对sql语句(union/**/select)词法解析成功。事实上许多WAF都考虑到/**/可以作为空白分,但是waf检测 “/\*.*\*/”很消耗性能,工程师会折中,可能在检测中间引入一些特殊字符,例如:/*\w+*/。或者,WAF可能只中间检查n个字符“/\*.{,n}\*/”。根据以上想法,可以逐步测试绕过方法:

先测试最基本的:union/**/select

再测试中间引入特殊字:union/*aaaa%01bbs*/select

最后测试注释长度:union/*aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa*/select

内联注释:/*!xxx*/

4.2 空白符绕过

基于正则表达式的WAF, SQL注入规则使用正则表达式的“\s”匹配空格,例如”select\s+union”。利用正则表达式的空白符与MySQL空白符的不同可绕过WAF规则。如何这些MySQL的特性?通过fuzz,每次更改正常SQL语句的某部分,替换为其他字符,判断语法是否正确,即可判断出来MySQL语法特性。当然,也可以通过分析MySQL词法来发现语法特性,从而找到绕过方法。

利用空白符进行绕过,测试WAF时尽可能减少其他原因的影响,例如”union select”被拦截,只需把中间空白符替换为”%250C”, “%25A0”进行绕过测试。

union%250Cselect

union%25A0select

4.3 函数分隔符

对基于正则表达式的WAF,我们猜测安全工程师写WAF规则时,可能不知道函数名与左括号之间可以存在特殊字符,或者遗漏可以存在特殊字符。例如匹配函数”concat()”的规则写法,“concat(”或者”concat\s*(”,就没有考虑到一些特殊字符。相应的绕过方法,在特殊位置引入特殊的分隔符,逐个测试。这些特殊分隔符发现也是通过Fuzz出来的。

concat%2520(

concat/**/(

concat%250c(

concat%25a0(

举一反三,寻找类似的关键位置,Fuzz特殊字符,发现更多的绕过新方法。猜测工程师们写规则因为各种原因容易遗漏的点,进行绕过WAF检测。

4.4浮点数词法解析

利用MySQL解析浮点数的特点,正则表达式无法匹配出单词union,但是MySQL词法解析成功解析出浮点数、sql关键字union。

select * from users where id=8E0union select 1,2,3,4,5,6,7,8,9,0

select * from users where id=8.0union select 1,2,3,4,5,6,7,8,9,0

select * from users where id=\Nunion select 1,2,3,4,5,6,7,8,9,0

4.5 利用error-based进行SQL注入

Error-based的SQL注入函数非常容易被忽略,导致WAF规则过滤不完整。随着对MySQL研究越来越深,被发现可用于error-based SQL注入的函数越来越多,同时也给绕过WAF造就了更多机会。常见的函数:

extractvalue(1, concat(0x5c,md5(3)));

updatexml(1, concat(0x5d,md5(3)),1);

GeometryCollection((select*from(select*from(select@@version)f)x))

polygon((select*from(select name_const(version(),1))x))

linestring()

multipoint()

multilinestring()

multipolygon()

利用Error-based的SQL注入函数进行绕过时,可以结合函数分隔符,或其他方法灵活运用。

4.6 Mysql特殊语法

最有效的发现手段,还是去读读MySQL词法分析源代码。和协议绕过类似,挖掘SQL标准与MySQL的词法分析差异是发现WAF SQL注入绕过的有效手段。以下是MySQL语法的一个特写(ps:不是我发现的):

selectfrom;

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180718G0B0S900?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。

扫码关注云+社区

领取腾讯云代金券