【技术分享】详谈WAF与静态统计分析

http://p9.qhimg.com/t017ccbe4b1f02b50ae.png

译者:blueSky

预估稿费:200RMB

投稿方式:发送邮件至linwei#360.cn,或登陆网页版在线投稿

 

前言

虚拟补丁(VP)近年来一直是保护应用程序最受欢迎的方法之一,如果在Web应用程序防火墙层级添加VP功能,该功能可用于保护Web应用程序免遭已知漏洞的威胁攻击。简而言之,VP利用静态应用程序安全测试(SAST)的结果并使用它们来创建规则以用来过滤WAF上的HTTP请求。 但问题在于,SAST和WAF依赖于不同的应用程序模型和不同的决策方法。因此,目前可用的解决方案中没有一个能够将SAST与WAF完美的结合起来。SAST基于白盒模型,它采用公式方法来检测代码中的漏洞。然而,WAF将应用程序视为黑盒子,因此它使用启发式方式进行攻击检测。但是如果我们能让SAST和WAF完美的结合在一起使用,我们可以通过SAST获取有关应用程序内部结构的信息,并将这些信息提供给WAF,这样我们就可以以一种“优雅”的方式来检测网络攻击。 


传统VP

一般地,在Web应用程序传统自动化虚拟修补方法中,我们需要向WAF提供SAST检测到的每个漏洞信息,这些信息包括: 

漏洞分类

Web应用程序的脆弱点

攻击所需的HTTP请求参数值

构成攻击向量脆弱点参数的值

脆弱点参数中可用于漏洞利用的一组字符或一个单词。

一般地,我们可以通过定义某些函数来获取HTTP请求中的参数值,例如下面是一段易受XSS攻击的ASP.NET页面的代码片段:

 http://p8.qhimg.com/t016ed5ca7e7848906b.png

通过分析针对上面页面的攻击向量代码,我们可以生成一组攻击向量值的符号公式: 

{condition =“secret”⇒param∈{XSShtml-text}} ,其中XSShtml-text是TEXT上下文中用于XSS攻击的向量集合。在实际的应用场景中,WAF虚拟补丁的描述符可用于生成过滤规则,以阻止所有能够利用相关漏洞的HTTP请求。 

虽然这种做法肯定会导致某些攻击,但它有一些很大的缺点: 

为了表示任何给定的漏洞,SAST需要发现一个可能的攻击向量。 但为了确保能够真正消除一个漏洞,SAST有必要处理所有可能的攻击向量。但是SAST很难将这些信息传递给WAF,因为由于攻击向量语法的不规则性,矢量集不仅是无穷大的,甚至不能用正则表达式来表达。

对于漏洞利用所需的其他请求参数的值也是如此。

如果入侵点和脆弱执行点之间的攻击向量语法在其上下文中发生了变化,那么有关脆弱参数的信息将变得没有任何的价值。

由于这些设计上的缺陷,对于SAST检测到的漏洞,VP技术不能针对其提供可能的攻击保护。尝试创建这种“全面的”流量过滤规则通常会阻止合法HTTP请求并中断Web应用程序的操作,下面让我们稍微修改漏洞的代码: 

 http://p6.qhimg.com/t012a9db32797423dfb.png

与上一个例子的区别是:在对两个请求参数都做了Decode处理,针对该新代码的攻击向量公式如下所示:

(CustomDecode condition)⊃“secret”⇒param∈(CustomDecode {XSShtml-text})

。静态分析会在相关计算流程图(ConfiG)节点中为自定义解码函数导出一个公式,以描述Base64-URL-Base64转换链,如下所示:

(FromBase64Str (UrlDecodeStr (FromBase64Str argument)))

。 针对这样的公式,我们仍然有可能在其基础上构建一个漏洞,但是由于以下原因,生成虚拟补丁的方法不能应用于此: 

只有当请求中的“condition”参数包含“secret”子字符串时,才可能利用此漏洞。 然而,该参数的值集是非常大的,并且由于解码功能的不规则性,通过正则表达式表达该集合是不可行的。

事实上,攻击向量的请求参数也被解码。因此,SAST无法将该组危险元素描述为WAF。

由于传统VP的所有问题都源于无法与基于白盒方法的WAF级别的应用程序进行交互,因此明显的解决方案是实现此功能并进一步改进,以便: 

SAST向WAF提供有关易受攻击的参数以及从进入点到易受攻击的执行点这整个过程中对攻击变量所做的所有转换信息。

对于攻击检测,启发式方法被公式方法所替换,并且包含任何漏洞的利用条件信息。

因此,运行时虚拟补丁应运而生。


运行时虚拟补丁

运行时虚拟修补(RVP)的原理是基于PT应用检查器(PT AI)中的计算流程图模型实现的。与公式符号计算的语义表示类似,该模型是使用应用程序代码的抽象解释构建出来的,模型中的图节点包含了目标语言的生成公式,并且公式产生与相关执行点上的所有数据流相关联的所有合法值的集合,具体如下图所示:

http://p4.qhimg.com/t015001dd1b82b12265.png

上图中的这些流被称为执行点参数。 由于CompFG是可评估的,因此我们可以根据输入参数的值,在任何执行点上计算所有参数的值。 通常情况下,RVP分为部署(D)和运行(R)两个阶段,这俩个阶段分别对应于应用程序生命周期,具体如下图所示: 

http://p4.qhimg.com/t0191e9b2b63f2bce8c.png


部署阶段

在部署新版本的应用程序之前,应用程序由PT AI分析,并且为那些易受攻击的执行点中的每个CompFG节点计算三个公式: 

获取脆弱执行点的条件

获取其所有参数值的条件

所有参数及其相应语法的值集

上述中的所有公式集都将按照应用程序的入口点进行分组,入口点定义于分析器的数据库中,并和PT AI支持的每个Web框架相关联。通过提取包含的漏洞信息以及从代码(基于S-expression语法的特殊语言编写的代码,编程语言使用不依赖于目标语言的形式来描述CompFG公式)中提取相关的公式列表形成一份报告,例如上述代码示例中描述脆弱点参数值的公式如下:

(+ (+ "Parameter value is `" (FromBase64Str (UrlDecodeStr (FromBase64Str (GetParameterData (param)))))) "`")

获取脆弱点的公式是: 

(Contains(FromBase64Str(UrlDecodeStr(FromBase64Str(GetParameterData(condition)))))“secret”)

。 然后将报告被上传到PT应用防火墙 (PT AF),在报告的基础上,PT WAF生成二进制模块,该模块可以计算报表中包含的所有公式。 例如,用于计算达到上述脆弱点的条件的反编译代码如下: 

 http://p0.qhimg.com/t0134874dd1a7da0b80.png

为了对公式进行计算操作,PT AF必须具有以下条件之一: 

预先计算可能在报告中出现的所有函数

具有沙箱运行环境,用于运行Web应用程序或其他平台(如CLR,JVM或PHP,Python或Ruby解释器)以及应用程序中使用的库

第一种方法在一定程度上能够保证速度很快,但WAF开发人员需要大量的手动工作来描述预计算数据库,即使开发人员将范围限制为标准库函数。第二种方法允许计算报告中可能出现的所有函数,但这种方法会增加处理每个HTTP请求所需的时间,因为WAF需要访问运行时环境来对每个函数执行计算操作。这里最合适的解决方案是使用第一种方法进行最常见函数的计算,而对其余函数使用第二种方法。 

公式中很可能会包含分析器无法处理的函数或者PT AF无法计算的函数,这些函数在公式中会被标记为“unknown”,并以如下所述的特殊方式进行处理。 


运行阶段

在运行阶段,WAF将每个HTTP请求的处理委托给二进制模块,该模块分析请求并检测Web应用程序中的相关入口点。为此,WAF会选择所有检测到的漏洞公式,然后以特定方式执行计算操作。 

首先,计算公式的两个条件为:1)到达脆弱点,2)获取其所有参数的值。 在每个公式中,变量用相关请求参数的值代替,之后计算公式值。 如果公式包含标记为“unknown”的表达式,则其处理如下: 

每个“unknown”标志通过公式表达式树自下而上扩展,直到找到布尔表达式。

在公式中,这样的表达式会被布尔变量替换,以用来解决布尔可满足性问题。

假设通过上一步骤生成了关于“unknown”的n个公式,那么计算每个公式的值。 如果至少有一个公式是可满足的,那么该假设也被认为是可以满足的。

如果计算显示假设为假,那么即使所有请求参数都有危险的值,HTTP请求也无法将应用程序引导到易受攻击的点。在这种情况下,RVP只需向WAF的核心模块返回请求处理即可。如果攻击条件满足,那么WAF会计算脆弱点的参数值,使用的算法取决于分析点所属的漏洞等级。这些算法之间的相似之处是用于处理包含未知节点公式的逻辑:与假设公式不同,在计算时参数公式不会被计算,而是立即被传达给WAF。为了更好地理解这一点,我们现在将回顾一下用于检测注入攻击的最复杂的算法。 


检测注入攻击

注入攻击通过将特定形成的输入数据传递给应用程序来执行恶意操作,当这些数据被“注入”到目标文本中(包括HTML, XML, JavaScript, SQL, URLs, 以及文件路径)时,文本中包含了应用程序逻辑不想要的句法结构。如果一个脆弱点属于这个攻击类,那么它的参数值是可以通过使用污点分析语义中抽象解释的增量计算来确定的。这种方法背后的思想是:从下到上分别计算每个表达式,同时获得每个步骤的计算结果、每个函数的语义以及传统污点检查的规则。例如,对于上述代码和以下HTTP请求参数:

condition=YzJWamNtVjA%3d&param=UEhOamNtbHdkRDVoYkdWeWRDZ3hLVHd2YzJOeWFYQjBQZyUzRCUzRA%3d%3d

,将此算法应用于弱点参数的公式的结果如下(污染参数标记为红色): 

 http://p4.qhimg.com/t01113ab7bbc2d28c88.png

然后根据脆弱点参数的语法对该值进行标记,如果任何污点的片段匹配多个令牌,那么就代表这是一次注入的攻击。 

 http://p0.qhimg.com/t01b7996b78eb4b93e6.png

一旦与当前入口点相关的所有漏洞的公式计算结束,请求处理将与检测结果一起传递给WAF的核心模块。 


RVP优点和具体功能

与传统VP相比,这种基于代码分析的应用程序保护方法具有很大的优势: 

得益于上述公式方法以及所有中间转换的能力,传统VP的缺点得到了解决。

公式方法也完全排除了假阳性的可能性,只要公式不包含未知节点

对Web应用程序功能没有不利影响,因为保护是建立在应用程序的功能上,而不是简单地试图解决它们。

为了测试该技术并确认其有效性,我们开发了一种用于PT应用程序检查器和PT应用程序防火墙的模块原型,实验结果表明大约十五个开源内容管理系统(CMS)的性能测试显示出很好的结果:使用RVP处理HTTP请求所需的时间与使用传统(启发式)WAF方法处理此类请求所需的时间相当。 Web应用程序的平均性能如下: 

对于那些非攻击的请求占比为0%

对于那些非攻击请求,但会导致脆弱点的占比为6-10%

对于那些是攻击请求的,且会导致脆弱点的占比为4-7%

尽管与传统VP相比有明显优势,但RVP仍有几个概念上的缺点: 

不可能在WAF(包括文件资源,数据库和服务器环境)上计算包含来自外部源的数据公式。

公式的质量直接取决于分析期间代码片段的质量(包括循环,递归和对外部库方法的调用)。

为了描述预计算数据库中函数的语义,需要开发人员加入到其中,该描述过程很难自动化,且容易出现人为错误。

然而,我们已经设法通过将一些RVP功能从应用程序中删除并使用RASP技术来缓解上述这些缺陷,该部分内容我们将会在新的文章中进行阐述,尽请期待吧~ 

(完)