绕过WAF的相关技术研究是WAF***研究很是重要的一部分,也是最有趣的部分,因此我在写WAF***时先写***部分。仍是那句老话“不知攻焉知防”,若是连绕过WAF方法都不知道,怎么保证WAF能保护后端服务的安全。在我看来,WAF的绕过技术的研究将不断驱动防护水平提升。
php
之前一些WAF bypass的文章更像CASE的整理,都把焦点放在了规则对抗层面。绕过WAF规则,更像是正面对抗,属于下策。一直关注规则层面的绕过,太局限视野,看不到WAF在其余方面问题。木桶原理,防护能力并不会有本质的提升。本文将从4个层次讲解bypass WAF的技术,全方位提高WAF的防护能力。 讲完相关***技术后,之后再探讨WAF的设计架构、防护策略,这样显得每一处的考虑都是有意义的。nginx
从架构层Bypass WAF 。正则表达式
从资源限角度bypass WAF。sql
从协议层面bypass WAF。shell
从规则缺陷bypass WAF。数据库
若是流量都没有通过WAF,WAF固然没法拦截***请求。当前多数云WAF架构,例如百度云加速、360安全卫士等,经过更改DNS解析,把流量引入WAF集群,流量通过检测后转发请求到源站。如图,liusscs.com接入接入WAF后,liusscs.comd的DNS解析结果指向WAF集群,用户的请求将发送给WAF集群,WAF集群通过检测认为非***请求再转发给源站。后端
云WAF流量路径tomcat
假设咱们是***者,如何绕过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小时,但是如今找不到那篇文章。
一些在云服务商的站点,同时使用云服务商提供的WAF服务。当流量不是经过DNS解析引流到WAF,流量必须通过WAF的检测,这是不能经过发行源站进行绕过。能够考虑在云服务商买一台VPS,经过VPS***目标站点,由于流量是局域网,可能不通过WAF检测,实现绕过。能不能成功,关键在于云服务商的网络配置。
***机器与目标机器在同一局域网
若是未能发现源站IP,能够尝试寻找子站的×××F漏洞。若是子站访问目标站不通过WAF集群,能够利用×××F漏洞来绕过WAF。
这是众所周知、而又难以解决的问题。若是HTTP请求POST BODY太大,检测全部的内容,WAF集群消耗太大的CPU、内存资源。所以许多WAF只检测前面的几K字节、1M、或2M。对于***者而然,只须要在POST BODY前面添加许多无用数据,把***payload放在最后便可绕过WAF检测。
即便流量都确保通过WAF,若是WAF的防护策略根本就没有检测payload,那么也就能绕过WAF。协议层面绕过WAF,利用WAF解析协议的问题,使得payload被认为不是请求的HTTP请求的内容。从我的经验总结出WAF解析协议的常出现问题的三个方向。
协议覆盖不全。
协议解析不正确。
协议解析与后WEB容器的协议解析不一致。
如下以实例说明利用协议绕过WAF的方法。经过CASE解析什么是协议覆盖不全、协议解析不正确、协议解析不一致。
POST 请求经常使用有2种参数提交方式:
Content-Type: application/x-www-form-urlencoded;
Content-Type: multipart/form-data;
Waf未能覆盖Content-Type: multipart/form-data从而致使被绕过。或者WAF会认为它是文件上传请求,从而只检测文件上传,致使被绕过。如图,加速乐的WAF就存在被绕过的状况,是典型的协议未覆盖。
普通***请求被拦截
协议未覆盖致使绕过
之前发的文章《PHP DOS漏洞的新利用》,就是利用协议解析不一致进行绕过WAF。如图中的payload,WAF解析出来上传的文件名是test3.jpg,而PHP解析获得的文件名是shell.php,从而绕过WAF的防护。当时这个方法几乎通杀全部WAF,可见利用协议层绕过WAF的威力,详情见:http://weibo.com/ttarticle/p/show?id=2309404002575157473609。就文件上传而言,还有更多由于协议解析致使绕过,见3.3节。
WAF与PHP解析文件上传协议不一致致使绕过
WAF的文件上传规则使用正则表达式匹配上传的文件名是否包含“0x00”等,因此正面绕过正则表达式匹配几乎不可能。若是不从规则角度考虑,利用协议解析问题让WAF没法匹配到正确的文件名,就能绕过WAF实现文件上传。
在multipart协议中,一个文件上传块存在多个Content-Disposition,将以最后一个Content-Disposition的filename值做为上传的文件名。许多WAF解析到第一个Content-Disposition就认为协议解析完毕,得到上传的文件名,从而致使被绕过。如图,加速乐的WAF解析获得文件名是”sp.pho”,但PHP解析结果是”sp.php”,致使被绕过。
在一个Content-Disposition 中,存在多个filename ,协议解析应该使用最后的filename值做为文件名。若是WAF解析到filename="p3.txt"认为解析到文件名,结束解析,将致使被绕过。由于后端容器解析到的文件名是t3.jsp。
Content-Disposition: form-data;name="myfile"; filename="p3.txt";filename="t3.jsp"
当WAF遇到“name=”myfile";;”时,认为没有解析到filename。然后端容器继续解析到的文件名是t3.jsp,致使WAF被绕过。
Content-Disposition: form-data;name="myfile";; filename="t3.jsp"。
multipart协议中,一个POST请求能够同时上传多个文件。如图,许多WAF只检查第一个上传文件,没有检查上传的全部文件,而实际后端容器会解析全部上传的文件名,***者只需把paylaod放在后面的文件PART,便可绕过。
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’
请求中包含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*/
当想到利用协议解析绕过WAF检测时,并不敢肯定效果,通过实践检验,协议解析绕过WAF的思路可行且有效。在研究利用协议绕过WAF时,须要大胆地猜想WAF解析协议时容易犯什么错误,科学地一点点验证。经过分析PHP、tomcat的协议解析源码,找出它们与HTTP标准协议的差别是发现绕过WAF的快速有效方法。
本节利用multipart/form-data协议解析过问题文件上传的思路,思路一样可用于绕过multipart/form-data协议POST FROM表单提交参数的检测。
对基于正则表达式的WAF,绕过WAF规则主要思考安全工程师写WAF规则时在想什么,容易忽略什么,推断一些可能绕过的方式,而后屡次尝试进行验证。比起完整罗列绕过CASE,我更喜欢分析绕过思路。此次以最受关注的SQL注入、文件包含为例,分析一下绕过思路。
绕过SQL注入规则主要利用WAF规则自己的问题、未考虑到SQL语法变形、及后端数据库SQL语句语法特性。不一样的数据库虽然遵照SQL标准,可是一般会加入特有的语法。WAF的防护策略要兼顾各类数据库的特殊语法,容易遗漏,从而被利用绕过WAF。如下MySQL为例,分析绕过SQL注入的一些思路。
/*xxx*/是注释,也能够充当空白符。由于 /**/可以使得MySQL对sql语句(union/**/select)词法解析成功。事实上许多WAF都考虑到/**/能够做为空白分,可是waf检测 “/\*.*\*/”很消耗性能,工程师会折中,可能在检测中间引入一些特殊字符,例如:/*\w+*/。或者,WAF可能只中间检查n个字符“/\*.{,n}\*/”。根据以上想法,能够逐步测试绕过方法:
先测试最基本的:union/**/select
再测试中间引入特殊字:union/*aaaa%01bbs*/select
最后测试注释长度:union/*aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa*/select
同理,对于/*!xxx*/,能够采起相似的思路绕过WAF。
基于正则表达式的WAF, SQL注入规则使用正则表达式的“\s”匹配空格,例如”select\s+union”。利用正则表达式的空白符与MySQL空白符的不一样可绕过WAF规则。如何这些MySQL的特性?经过fuzz,每次更改正常SQL语句的某部分,替换为其余字符,判断语法是否正确,便可判断出来MySQL语法特性。固然,也能够经过分析MySQL词法来发现语法特性,从而找到绕过方法。
利用空白符进行绕过,测试WAF时尽量减小其余缘由的影响,例如”union select”被拦截,只需把中间空白符替换为”%250C”, “%25A0”进行绕过测试。
union%250Cselect
union%25A0select
对基于正则表达式的WAF,咱们猜想安全工程师写WAF规则时,可能不知道函数名与左括号之间能够存在特殊字符,或者遗漏能够存在特殊字符。例如匹配函数”concat()”的规则写法,“concat(”或者”concat\s*(”,就没有考虑到一些特殊字符。相应的绕过方法,在特殊位置引入特殊的分隔符,逐个测试。这些特殊分隔符发现也是经过Fuzz出来的。
concat%2520(
concat/**/(
concat%250c(
concat%25a0(
触类旁通,寻找相似的关键位置,Fuzz特殊字符,发现更多的绕过新方法。猜想工程师们写规则由于各类缘由容易遗漏的点,进行绕过WAF检测。
利用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
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注入函数进行绕过期,能够结合函数分隔符,或其余方法灵活运用。
最有效的发现手段,仍是去读读MySQL词法分析源代码。和协议绕过相似,挖掘SQL标准与MySQL的词法分析差别是发现WAF SQL注入绕过的有效手段。如下是MySQL语法的一个特写(ps:不是我发现的):
select{x table_name}from{x information_schema.tables};
以上都是SQL注入绕过中的技术点,在实际***测试中,须要灵活综合利用才能达到完整绕过,读取数据数据。如下给出完整绕过WAF SQ注入检测的实例。如图,本例中综合多个绕过技术点,最终实现完整绕过实现读取数据。
利用浮点数词法解析,绕过union select 的检测。
一样,函数分隔符思想集和浮点数词法解析,绕过关键字from的检测。
最后空白分分割绕过INFORMATION_SCHEMA.TABLES的检查
文件包含分为相对路径、绝对路径文件包含。在相对路径文件包含中,最终根据Linux虚拟文件系统(vfs)的规则查找文件,经过分析vfs的文件路径解析规则,提取其中规则特色,用这些特色去绕过WAF。在绝对文件路径包含中,主要是根据***场景,WAF未过滤一些协议、未过滤某些特殊路径。
写WAF文件包含规则时,若是检测单一的”../”,误报会很是多,因此WAF文件包含规则一般会检测连续的“../"。根据vfs解析路径的语法,解析到“//”文件路径不变,解析到“/./”文件路径依然。 经过避免连续的"../",从而绕过WAF文件包含规则。Eg: ././..///./.././/../etc//passwd,它等价于../../../etc/passwd。如图,一个实际的绕过WAF文件包含的 CASE
WAF没有考虑到路径中插入“/./”、“//”对于vfs解析路径是等价的,致使可被绕过。例如 /etc/./passwd 与 /etc/passwd 是等价的。还能够经过组合“/./”、“//”进行绕过,eg. /etc///.//././/passwd。
对于绝对路径文件包含,WAF通常会拦截常见路径,而不会防护全部的绝对路径。所以,在***测试中,能够包含其余的路径下一些文件,例如/usr/local/nginx/conf/nginx.conf。
若是WAF只检测连续的../,检查开始路径为Linux的目录名,能够采用/wtt/../绕过WAF文件包含检测。 例如,“/wtt/../etc/passwd”, wtt不是Linux标准目录,不会被规则匹配。WAF只检测连续的../,可是只使用一个../,不被拦截。最终读取/etc/passwd文件。
利用WAF未检测的协议。PHP 文件包含支持的协议,在***测试中,看环境选择可行的方法
file:// Accessing local filesystem
http:// Accessing HTTP(s) URLs
ftp:// Accessing FTP(s) URLs
php:// Accessing various I/O streams
zlib:// Compression Streams data:// Data (RFC 2397)
glob:// Find pathnames matching pattern
phar:// PHP Archive
ssh2:// Secure Shell 2
rar:// RAR
ogg:// Audio streams
expect:// Process Interaction Streams
一个好WAF不是吹出来的,是实践检验出来的。研究WAF的绕过手段,是为了更好的提高WAF的防护能力。在研究突破的过程当中,不要仅仅停留在正则表达式,基本漏洞原理,须要对涉及并深刻更多的领域,例如HTTP协议理解和PHP、Tomcat对HTTP协议源码分析,MySQL词法分析,和Fuzz的思路等。在此过程当中,会有许多乐趣,也会有各方面能力的提高。
@破-见
http://weibo.com/ttarticle/p/show?id=2309404007261092631700