103 lines
12 KiB
Markdown
103 lines
12 KiB
Markdown
# 22 | RASP:写规则写得烦了?尝试一下更底层的IDS
|
||
|
||
你好,我是何为舟。
|
||
|
||
在前面的课程中,我们已经介绍了防火墙、WAF和入侵检测。这些产品都有一个共同的特性,就是基于网络请求或者系统行为对攻击的特征进行检测,然后再采取相应的防控手段。这些安全产品基本都和应用本身解耦。也就是说,基本上我们不需要对应用做任何开发和改动,就能够部署这些安全产品。
|
||
|
||
尽管解耦在部署上能够节省很大的成本,但解耦同样意味着,安全产品和应用本身是通过接口、请求等形式来进行数据交换的。换一句话说,安全产品只能够看到应用输入和输出的数据,并不知道数据在应用内的流动情况。因此,这种工作模式不可避免会产生一定的误判和漏报。
|
||
|
||
我们来看一个关于WAF检测SQL注入的例子。下面是请求代码:
|
||
|
||
```
|
||
http://server.com/login?username=test&password=" or ""="
|
||
|
||
```
|
||
|
||
WAF可能会检测到password参数中的SQL注入痕迹进行拦截。如果应用采用的是安全的PreparedStatement方法,那这个SQL注入就不会生效,也就不需要拦截。但是WAF和应用解耦,让WAF不知道应用的逻辑,从而产生了误报。
|
||
|
||
所以,对于任何安全产品来说,能获取到的数据和信息越多,检测的能力就越强,误判和漏报的概率也就越低。因此,2012年,Gartner提出了RASP(Runtime Application Self Protection)的概念,就是希望将安全产品部署在应用的底层,完全站在应用的视角去发现攻击行为,从而实现更加完善的安全防护。
|
||
|
||
## RASP的原理
|
||
|
||
想要利用RASP实现更完善的安全防护,首先我们要知道,什么是RASP?以及如何实现RASP?
|
||
|
||
RASP的设计思路是通过监控应用的底层,来从根本上发现攻击行为的产生。
|
||
|
||
以Java为例,Java应用运行在JVM之上。因此,JVM就是一个底层,它能够看到所有的应用信息。我们可以通过[JavaAgent](https://www.jianshu.com/p/63c328ca208d)的形式将RASP运行在JVM上,然后借助[Instrumentation](https://www.ibm.com/developerworks/cn/java/j-lo-jse61/index.html)技术Hook关键的类和方法。关键类和方法具体有哪些,你可以参照OpenRASP的[Hook列表](https://rasp.baidu.com/doc/hacking/architect/hook.html)。这样一来,RASP就能关注到应用安全相关的信息和调用了。
|
||
![](https://static001.geekbang.org/resource/image/b5/b7/b5634e94b5607221dee2ed3680c0efb7.jpg)
|
||
|
||
同样的原理,在PHP中,我们可以通过PHP扩展库来实现RASP;在.Net中,我们可以通过HostingStartup来实现RASP。
|
||
|
||
如果你想要研究RASP产品,那我推荐你使用百度的[OpenRASP](https://rasp.baidu.com/#section-intro)。因为OpenRASP在开源市场中认可度比较高,也是目前各个公司用来研究RASP产品的一个主要对象。
|
||
|
||
## RASP的优势和劣势
|
||
|
||
我们经常会将RASP和WAF拿来做比较,因为它们主要关注的都是应用相关的Web安全问题。那么对比WAF,RASP有哪些优势和劣势呢?
|
||
|
||
首先我们来看优势。在开头我们就提到了,RASP对比于WAF最大的优势在于RASP运行在应用的底层,从而能够知道应用运行时的上下文(比如:用户、代码逻辑、SQL语句等)。在Web安全中,我们针对Web安全的攻击原理进行过总结:SQL注入、反序列化等漏洞其实都是通过输入数据,篡改应用的正常逻辑实现的攻击。
|
||
|
||
对于WAF来说,它只能够判断出输入的数据“可能”会篡改应用的正常逻辑,因此WAF的拦截决策都来源于这个可能性。而对于RASP来说,它知道应用的正常逻辑是什么,也知道应用接收输入后实际的逻辑是什么,如果实际逻辑和正常逻辑不一致,就必然发生了攻击。基于这种检测方式,RASP基本不会产生误报或者漏报。
|
||
|
||
我们以OpenRASP防止SQL注入的[检测逻辑](https://github.com/baidu/openrasp/blob/master/plugins/official/plugin.js)为例,来看一下RASP是如何进行检测的。算法描述如下:
|
||
![](https://static001.geekbang.org/resource/image/a2/19/a2230de2106ad352ef33bb838b0cf719.jpg)
|
||
第1步和第2步很好理解,都是SQL注入的基本特征。那第3步中的“导致SQL语句逻辑发生变化”,OpenRASP要如何去识别呢?假设用户的输入是万能密码"or""=",那么,应用实际执行的SQL语句就是:
|
||
|
||
SELECT \* FROM Users WHERE Username = “” AND Password = ““or””=""
|
||
|
||
在这个SQL语句中,最后的几个字符都是用户的输入。为了检测语句逻辑的变化,OpenRASP将这个SQL语句进行了Token化。所谓“Token化”,就是对SQL语句中的关键词进行拆解,拆解后分别是:SELECT、 \*、FROM、Users、WHER、Username、=、""、AND、Password、=、""、or、""、=、""。我们能够清楚地看到,用户的输入“"“or “”=”"”占据了5个Token。而正常情况下,用户的输入应该只占据1个Token。因此,只要用户的输入大于1个Token,就说明SQL语句逻辑存在变化,我们就可以断定存在SQL注入了。
|
||
|
||
其次,RASP能够防范未知的攻击。对于SQL注入来说,它的注入点可以是某个GET参数、某个POST的Body、某个Header字段等,具体的攻击方式也多种多样:盲注、基于Insert的注入等。
|
||
|
||
WAF的检测规则是一个一个去覆盖这些攻击点和攻击方式。如果黑客发现了某个新的攻击点或者使用了新的攻击方式,WAF根本无法检测出来。
|
||
|
||
对于RASP来说,它实际上不关注具体的攻击点和攻击方式是什么,因为SQL注入攻击,最终都会使SQL语句Token化后的长度发生改变。因此,RASP只需要判断执行的SQL语句Token化后的长度即可。所以我才说,RASP能够有效地防御未知的攻击。
|
||
|
||
最后,我认为RASP还有一个比较特别的好处,就是基本不用维护规则。我前面讲过的各类安全产品:防火墙、WAF和入侵检测,它们的本质都是检测攻击行为。而这些安全产品的检测方式不论是签名匹配、正则匹配还是行为分析,都包含了大量的规则和算法。这些规则和算法带来的最大问题,就是针对每一家公司我们都需要制定一套单独的规则和算法。因为每家公司的应用和网络环境都不一样,面临的攻击也不一样。
|
||
|
||
随着公司的发展以及黑客的对抗升级,我们还需要不停地更新和维护这套规则和算法,这就带来了极大的运营成本。而对于RASP来说,它当然也需要规则和算法来支持,但是它的规则和算法相对统一。
|
||
|
||
比如,在Java中,不论你是使用的哪种开发框架,最终执行SQL语句的都是底层的JDBC插件,在这个层次上,攻击的特征都是一致的。因此,RASP基本只需要维护一套统一的规则和策略,就能够适用于所有的公司和应用了。所以,百度在OpenRASP[覆盖面说明](https://rasp.baidu.com/doc/usage/web.html)中敢说“若发现不能拦截的攻击或者误报的情况,请联系我们”,就是这个原因。开源的WAF只会提供一个维护规则的入口,而不会帮助你进行维护。
|
||
|
||
尽管RASP存在许多明显的优势,但是目前来看,国内对于RASP的实际落地,普遍还在试验阶段,我很少见到RASP在公司范围内大规模推广落地案例。这是为什么呢?要搞清楚这个问题,就不得不提到RASP的劣势了。RASP的劣势主要有三方面,下面,我们一一来看。
|
||
|
||
我认为最大的劣势在于推广难度上。尽管我们一直在提安全,但是事实上,大部分的开发人员并不认可安全,他们也不接受任何可能对应用产生影响的安全产品。这是因为,这些安全产品增加了检测的逻辑,就必然会影响应用的正常运行。而且,WAF等拦截性安全产品产生的误报,会让正常的业务请求受到影响。
|
||
|
||
但是,防火墙、WAF和入侵检测,实际上都已经在各个公司很好地落地了。我认为这都归功于安全人员或者运维人员的“强推”。
|
||
|
||
在部署一款WAF的过程中,实际上是不需要开发人员参与的,运维人员在网关上直接部署就可以了。而RASP不一样,RASP和应用强耦合,它需要由开发人员去部署。比如,Java中需要通过命令java -javaagent:rasp.jar -jar app.jar来启动RASP,其中的参数javaagent只能由开发人员进行配置。因此,RASP的推广实际上是安全意识的推广,所以难度也比较高。
|
||
|
||
其次,RASP的解决方案并不通用。从语言支持上来看,目前RASP只在Java、PHP和.Net语言中具备成熟的产品。其他高级语言,如Python等,可能是因为没有很好的Hook方案,所以目前仍然局限于研究阶段。这也是RASP强耦合所带来的弊端:每一种开发语言,甚至是语言下不同的开发框架,都可能会需要一套独立的RASP产品。而WAF等安全产品,因为网络和系统都比较统一,则不受此限制。
|
||
|
||
最后,RASP在性能问题上也备受争议。尽管目前成熟的RASP产品宣称它的性能影响已经低于5%,甚至更低了,但在实际落地的过程中,确实会出现因为系统和应用的差异,而导致性能恶化比较严重的情况。这也是RASP在兼容性不足上所表现出来的缺陷。
|
||
|
||
## RASP的其他功能
|
||
|
||
除了针对应用的攻击行为进行检测和拦截,和WAF一样,RASP也能够提供很多额外的安全防护功能。
|
||
|
||
毫不夸张地说,WAF能实现的功能,RASP都能够实现。因此,WAF中的数据保护、虚拟补丁等功能,RASP也都能够提供,原理也是一致的:都是通过拦截并修改HTTP请求和响应,在HTTP内容中加入额外的安全特性,比如Cookie加密。
|
||
|
||
除此之外,因为RASP部署于应用的底层,知道应用的全部信息,所以它本身可以对应用的安全性进行评估。最简单的评估问题如下:
|
||
|
||
* 是否使用ROOT权限运行了应用;
|
||
* 在连接数据库的时候,是否使用了弱密码;
|
||
* 使用了哪些插件,插件是否包含漏洞。
|
||
|
||
RASP可以在应用运行的过程中对这些高危的进程操作进行检测,从而提醒你采取更安全的实现方式。
|
||
|
||
## 总结
|
||
|
||
好了,今天的内容差不多了,我们一起来总结一下,你需要掌握的重点内容。
|
||
|
||
RASP的功能确实能给应用的安全性带来一个质的提升。对比低耦合的WAF等安全产品,RASP的准确率、覆盖度都有较大优势。但是,正因为耦合度过高,RASP部署起来比较麻烦,实际推广落地的时候,经常出现开发人员不配合的情况。总的来说,推广的难度属于管理上的问题,需要你想办法说服开发人员。单纯从安全角度上来说,我认为RASP是一款提升应用安全性的最佳安全产品。
|
||
|
||
另外,我认为在实际工作中,我们也可以将RASP和其他安全产品进行适当 组合,以达到取长补短的目的。比如说,RASP推广比较难,我们可以只做局部的部署。这些局部的部署可以当作WAF的样本数据来源,只要RASP在底层发现了攻击行为,就将相应的表层特征输出到WAF。这样一来,我们就可以将RASP在局部上的防御能力拓展到整体的WAF上,从而实现全面的安全防护提升。
|
||
![](https://static001.geekbang.org/resource/image/7f/06/7fb30045c6ee01b1b281187e92d4dc06.jpg)
|
||
|
||
## 思考题
|
||
|
||
最后,给你留一道思考题。
|
||
|
||
在这一讲中,我们只是以SQL注入为例,讲述了RASP是如何进行攻击检测的。你可以思考一下,对于其他的攻击方式,如反序列化漏洞、命令执行和SSRF等,RASP又该如何防护呢?你可以先学习一下OpenRASP的说明文档,之后再来思考这个问题。
|
||
|
||
欢迎留言和我分享你的思考和疑惑,也欢迎你把文章分享给你的朋友。我们下一讲再见!
|
||
|