本文作者:qiaoy(信安之路特约作者) 作者博客:https://www.qiaoyue.net
在企业架构中,安全体系同剥洋葱一般,由外及内是由一层层的安全产品和规范构成,越处于外层承重越大,WAF 属七层防护的第一道墙,随着互联网技术发展,业务对外提供服务的方式逐渐收拢,Web 接口与应用垄断流量,WAF成了安全战场中被炮火攻击最惨烈的前线。
虽然 WAF 属于较成熟的安全产品,但不同公司,不同场景都可能衍生出不同的部署方式,一个关键原因就是安全、效率、成本的不可能三角,互联网公司中,效率代表产品的易用性和响应时间,往往很难有较大牺牲,成本和安全的组合形式决定了安全产品架构的不同,即便在倾向选择中安全成为首位,WAF 产品本身也有痼疾:HTTP 协议和业务场景的复杂性导致很难有统一的策略规范,加之 WAF 抽离于业务代码逻辑以外,这些耦合上的瑕疵很容易成为绕过 WAF 防护的突破口。
再者,不管是基于正则匹配还是机器学习,考量 WAF 的指标永远是相互矛盾的:误报率,漏报率。在安全和效率(业务)的博弈中,没有完美,只有适配,这也就决定了 WAF 的定位。
WAF 的痼疾在越来越复杂的系统对接中存在耦合缺漏,不同类型的漏洞,在 WAF 的 Bypass 测试中关注点自然也不同,本文尝试找寻一些规则对抗以外的捷径进行 bypass,通过以下几个维度进行尝试:
1、架构层面
2、协议/中间件层面
3、系统/数据库/编程语言层面
在千奇百怪的 WAF 架构中,始终脱胎换骨于两种基础的架构:串联和旁路。
串联 WAF 一般权重较高,对攻击的请求和会话有优先于业务的一票否决权,是最为常见的 WAF 架构方式,不过串联接入业务意味着 WAF 系统会捆绑、分担业务指标,在日益追求高响应的复杂链路中强行增加了一个单点故障隐患,那考核运维健壮性的指标(可用性、响应耗时和故障率等)将是悬置 WAF 头顶的达摩克利斯之剑。
串联 WAF 根据产品形态又有多种变形,常见的区分方式看设备部署位置。
传统的硬件盒子设备一般放置在网关入口后,业务中间件之前,串联部署方式有透明模式、反向代理模式等,其前置于中间件,意味着 WAF 需预留很大一部分性能来处理 HTTP 拆解和封装的工作,尤其是当下 HTTPS 已成为普遍场景,设备处理性能急剧下降,使得此类架构的成本投入极大。
透明连接模式:
反向代理模式:
当下云厂商最常用修改域名 CNAME 做多维安全防护的架构同硬件类部署方式在应用场景视角是一致的,不过云厂商的设备和网络资源丰富,人才资源配备到位,又有大厂品牌背书,只要有足够的用户均摊成本,这种架构算在成本、效率、安全不可能三角中属协调最优的解决方案。
CNAME 架构:
对于此类前置串联架构的 ByPass 测试需找寻 WAF 与中间件、后端业务间的耦合性缺漏,比如:
1、在使用了 SSL 套接字的会话中,协商加密算法属请求方可控,WAF 和后端业务在算法支持上可能存在差异的一个切入点,遍历后端业务支持但 WAF 不支持的加密算法,便可直接绕过 WAF 了,相关工具见 Github:
https://github.com/LandGrey/abuse-ssl-bypass-waf
SSL Bypass
2、针对 CNAME 方式接入 WAF 的系统,能否绕过的关键在于后端的业务配置是否严谨,如果后端业务未限制访问源,很容易通过域名解析历史和 [ 大规模的扫描 ] 定位到真实的 IP 地址,修改本地 HOST 便可以绕过 WAF 直接对后端系统进行攻击;
3、WAF 与中间件的耦合缺漏在后续的中间件层面做详细讲解,此处不做赘述。
还有另一类串联的部署方式,即 WAF 设备位置后移,嵌套到中间件上,这样 WAF 的损耗将分摊到业务机器,这样的捆绑意味着一荣俱荣,一损皆损,又因位置后移到了业务侧,策略下发和管理都极其复杂,且中间件种类繁多,规模一大,这种架构堪称灾难,而随着业务架构的逐渐优化,一般的互联网业务架构会前置越来越轻的转发层,将 WAF 嵌到转发层,或在转发层通过 openresty 等方式将请求过一遍旁挂的 WAF 集群,这属对业务链路侵入最轻的一种方式,很多互联网公司自建的 WAF 采用该架构。
中间件部署:
OpenResty 部署:
对于此类嵌套于中间件的 WAF 架构测试需针对 WAF 模块的系统耗能和超时为切入点,当中间件或 WAF 模块达到一定的性能损耗指标,一般 WAF 系统会预留类似硬件设备断电 bypass 的功能来保障业务可用性的强指标,通过这种途径即可突破 WAF,比如:
1、针对中间件本身的漏洞(例如: CVE-2018-1336 )/配置错误来触发 DOS,当系统能耗达到阈值,自动关闭 WAF 模块;
2、针对 WAF 系统的正则策略进行攻击,通过 ReDoS:
https://www.owasp.org/index.php/Regular_expression_Denial_of_Service_-_ReDoS
使策略检测超时,单条会话跳过 WAF 集群响应,直接通联后端业务。
旁挂 WAF 一般不在会话链路以内,这意味着针对命令执行、Getshell 类的一条语句拿权限的攻击束手无策,满足业务性能,牺牲了较多的安全指标,做出这种妥协,一方面是业务/运维强势,可用性是相关部门较重的 KPI 指标,另一方面可能是 WAF 系统开发和运营人力资源紧张,旁路离线分析提供了一定的缓和空间。
旁路 WAF 可以理解为一套离线分析系统,在各类配置和参数设置上很难同业务机器同步,这导致两者之间的耦合缺漏会更大,且旁路部署的后置阻断措施也极具多样性:IP 维度(4 层封禁、7 封封禁),session 维度(业务路由基于登陆的 cookies 等),给绕过也提供了一些方法,常见的绕过方法有:
1、若系统是通过分光等方式旁挂,那针对前置串联 WAF 的 SSL 证书绕过方法在这里一样通用;
2、通过攻击测试,很容易判断出旁路 WAF 同阻断组件的通联时间,获取海量且廉价的代理 IP,控制好单 IP 的测试存活时间,较低成本便可绕过;
3、针对异常协议和中间件特效的攻击将在后续章节讲述,在旁挂 WAF 上均可实现绕过。
WAF 产品架构多样,除了串联和旁路外,基于业务特性还有各种各样的组合方式,之前所在公司基于业务架构单一的特点(系统、语言、中间件、数据库版本等相关信息全局一致),只需要关注固定版本的系统/应用漏洞情报,便可采用平日旁挂,漏洞爆发打开串联开关,漏洞批量修复后恢复旁挂的方式,在安全、效率、成本的博弈中发挥一点能动性。
HTTP 协议是一个渐进工程。
1991 初版草案 (HTTP/0.9) 仅有不足一页半的内容,在经历 5 年时间和若干版本的更替后,第一个正式版 HTTP/1.0 标准诞生,这时它已经变成一份密密麻麻长达 50 页的文档,期望能弥补过往标准里的诸多缺陷。很快到了 1999 年,HTTP/1.1 的 7 位署名作者显然指望该协议能涵盖到方方面面,导致的结果就是一份长达 150 页的大作。但这些越来越宏伟的文档里很大篇幅的内容和我们当下实际使用的 Web 并不特别相关,因为他们对新功能的追逐比修复旧有缺陷更感兴趣。—— 《Web 之困》
处于尚未完结的渐进工程中,强制的向下兼容,加之各类中间件对协议的解读和实现花样百出,导致整个协议骨干健壮清晰,细枝末节处却错综繁杂,越是复杂有异议的地方,越是存在安全隐患。
如《Web 之困》书中所描述,协议版本的升级,大多数精力都投入到了新花样和动人功能的开发上,缺陷的修补向来是不受人待见的,而协议侧的缺陷却往往是致命的。
DEFCON 24 会议上,regilero 有一篇名为《Hiding Wookiees In Http》的演讲,详细分析了 HTTP 协议中 Keepalives 和 Pipelines 组合使用上的缺漏,可导致会话注入和缓存投毒,在 WAF 绕过上也提供了一条路径。
Keepalives 虽然在 HTTP1.0 版本便可以使用,但并没有得到官方的确认,是浏览器爆炸发展阶段的民间战胜官方的胜利,HTTP1.1 版本后才开始作为默认参数参与到请求中,这条参数也属于新版本令人心动的崭新功能,引入的原因也是为了解决请求量级斗升,新建立连接带来的系统和网络损耗,功能大致如下所示:
HTTP Pipeline:
HTTP KeepAlive:
HTTP 1.0:
功能设计本身的意图是多请求单连接,但‘多请求’这个场景又有多般演绎,比如下图这种请求,在 WAF 端的识别上,这属于一个请求,逻辑也是通过拆解 Key、value 的模式以 Body 内容读取第二个请求的内容,当然是属于异常的 Key-Value 结构,这样第二个包的内容便很容易绕过 WAF 策略直接进行攻击了。
Keeplive 绕过:
关于 HTTP 协议特性的安全缺陷,还有一个值得说道的漏洞,2011 年 BlackHat 大会有一篇名为《Checkmate with Denial of Service》的演讲,阐述了一系列 DOS 漏洞,其中有部分是关于 HTTP 慢速攻击的分析,此后漫长的一段时间中,slowloris 都是诸多大型 DDOS 事件中的主角,关于慢速 DOS 的原理其实就是利用了 HTTP 的特性,通过 Keepalives 特性,发起大量请求,修改 Content-Length,Hold 住会话,在超时前定期发送小包,保持存活状态,使服务端线程数打满,又不得释放,服务便处于不可用状态,这种攻击在前文所述的针对中间件的 DOS 中不失为一种有效的攻击绕过方式。
除了协议特性以外,异变的 HTTP header 也有可能提供绕过 WAF 的捷径,2018 年的 AppSec 大会上,有一篇《hacker WAF bypass techniques》的演讲,通过以下几个方式进行 WAF 绕过:
1、字符集编码;Content-Type 头中使用 charset 定义字符集的应用场景不只有在 responses 中,request 中同样可以使用,而变换字符编码集以后,基于规则引擎的 WAF 则彻底失控。
1、内容类型格式;在特定中间件版本下 Key-value 可以通过文件上传的类型 multipart/form-data 进行提交,而 WAF 针对此类型侧检测一般是只针对上传漏洞,导致常规的 xss、sqli 便可以通过该方式进行 bypass,即使存在各通用类型的漏洞检测,也可通过 Fuzz 异变上传类型的格式,达到 WAF 无法识别,后端中间件可以解析的目的:
当然以上 Bypass 的路径并非通用的,很大情况与不同中间件对 HTTP 的理解和运用有关,详细中间件系统和版本测试情况可参见表格:
https://drive.google.com/file/d/0B5Tqp73kQStQU1diV1Y0dzd1QU0/view
基于协议/中间件的安全缺陷并不全然是功能带来的,有时带业务特性的配置也会有缺漏,且这种缺漏是前端 WAF 和后端业务中间件功能差异所必然存在的,也是大多数通用 WAF 产品很难和业务适配的死角,突出的例子如:
1、请求包大小限制;很多后端业务存在上传功能,所以请求数据限制上往往会较大,而前置 WAF 系统,需要有较高的响应时间,请求包较大时往往超过内置的性能和耗时阈值,所以可直接发送大量无意义的参数,尾端带攻击参数便可直接绕过 WAF 系统。
系统、数据库和编程语言层面,属于对抗 WAF 策略的正面战场,这类文章网上佳作不胜枚举,但其达成绕过的功效并不具通用性,比如系统级别的绕过可能围绕命令执行、LFI 之类的漏洞,数据库相关的绕过是围绕 Sqli 类漏洞,且两者的绕过思路大致相同,即利用系统/数据库特性或不常用函数绕过 WAF 策略特征,至于编程语言的绕过方式则相对灵活,这也是动态语言的特性决定的,本文主旨是 WAF 绕过的捷径,正面对抗策略内容便不多做赘述(正面硬刚 WAF 规则也有成熟工具,详细内容参见参考文档中 2016 blackhat 大会上的《Another Brick off The Wall: Deconstructing Web Application Firewalls Using Automata Learning》一文),每个类型各介绍一类比较有代表性的 Bypass 方法:
1、系统层面,利用 Linux 通配符特性绕过 WAF 策略;在 bash 语法中,可以使用与系统文件相同数量的 "?", "/" 来匹配该文件;用未初始化的变量隔离特征字符;用 ' 字符拆解再拼贴,绕过字符匹配。
1、数据库层面,利用 mysql 注释和注释特性绕过 WAF 策略;在 ModSecurity (最常见的开源 WAF 框架)默认策略中,union select 这类 Sqli 注入语法一般是贪婪匹配 union 和 select 之间的字符、数字、下划线、左括号,很容易通过插入 /* */
注释绕过;当变更规则过滤掉注释,依然可以通过在注释中使用 ! 加版本号包裹关键词来绕过检测,因为只要 mysql 的当前版本等于或大于该版本号,则该注释中的 sql 语句将被 mysql 执行;
1、编程语言层面,利用 PHP 数组特性绕过 WAF 策略;在 PHP 中每个字符串都可以当作数组,这样基于字符串的正则匹配就很容易被绕过了。
限于文章篇幅,简单描述了 WAF Bypass 测试的整体框架,相当一部分绕过方法未能展示,由于议题宽泛,时间紧迫,故仓促收尾,算理清框架脉络,避免后来者按图索骥的浪费时间。
Abuse-ssl-bypass-waf:
https://github.com/LandGrey/abuse-ssl-bypass-waf
Bypassing Web-Application Firewalls by abusing SSL/TLS:
https://0x09al.github.io/waf/bypass/ssl/2018/07/02/web-application-firewall-bypass.html
WAF Bypass Techniques - Using HTTP Standard and Web Servers’ Behaviour:
基于 Openresty 的云 WAF 工作原理:
https://www.yqfy.net/base-on-openresty-waf
Regular expression Denial of Service - ReDoS:
https://www.owasp.org/index.php/Regular_expression_Denial_of_Service_-_ReDoS
《Web之困》:
https://book.douban.com/subject/25733421/
DEFCON 24 《Hiding Wookiees In Http》:
Checkmate with Denial of Service:
https://media.blackhat.com/bh-dc-11/Brennan/BlackHat_DC_2011_Brennan_Denial_Service-Slides.pdf
Web Application Firewall (WAF) Evasion Techniques:
https://medium.com/secjuice/waf-evasion-techniques-718026d693d8
Web Application Firewall (WAF) Evasion Techniques #2:
https://medium.com/secjuice/web-application-firewall-waf-evasion-techniques-2-125995f3e7b0
Web Application Firewall (WAF) Evasion Techniques #3:
https://www.secjuice.com/web-application-firewall-waf-evasion/
Another Brick off The Wall: Deconstructing Web Application Firewalls Using Automata Learning: