如何将OWASP Top 10应用到无服务器中以增加安全性

无服务器模型

无服务器计算,有时也被称为“功能即服务”(Function as a Service,FaaS),它能够让您编写出一些能够独立运行的自包含函数。其基本模型如下:

如何将OWASP Top 10应用到无服务器中以增加安全性

也就是说,您的函数(Function)接收到一些输入后,根据各种输入、存储、以及获取到的状态进行计算,然后产生相应的输出。当然,普通的代码也能如此运作,那么它们的新颖之处又体现在哪里呢?

FaaS架构最大的创新之处在于:将一些安全责任从您的后端转向了您对应的FaaS平台提供商处。你们各自的责任分工如下图所示:

如何将OWASP Top 10应用到无服务器中以增加安全性

蓝色部分是您应用程序的“辖区”,而黄色部分则属于FaaS平台。这显然起到了极大的减负效果,即您只需编写某个函数,而由他人来负责剩下的繁琐工作,包括:找到运行它的各种服务器;保持这些服务器的更新;当服务器被攻击时,执行清理;当负载过高时自动增加服务器;判断一台服务器上能够运行多少个函数;按需重新分配负载;为各个函数及其支持的所有服务之间构建通信网络。

当然,这种转变也会带来安全之上的繁琐,即:您现在必须重点关注、并保护您自己的程序代码。也就是说,由于不同的开发人员可以将某个函数与其他函数相关联,而那些未经严格“消毒”的输入数据很可能就来自于某些攻击者,因此您的各种函数需要有一定的自保能力。而事实上,向无服务器应用程序提供的输入数据会更加广泛。除了那些定义良好的函数链之外,您可能还需要应对REST over HTTP、不同类型的消息队列、和每一次发布所引入的可扩展协议。

新的风险

无服务器计算模型会带来新的风险,而传统的工具并不能保证有效地处置这些风险及其扩展。被业界常用的OWASP top 10是保护各种应用程序的绝佳参考框架,当然它所针对的攻击,主要是基于运行在服务器上的应用程序,同时您的责任不仅限于自己的代码,而且会包括整个运行平台。

各种风险总是有着相似之处。攻击者要么试图将恶意数据注入到您应用程序本身的代码里(如:SQL/数据库注入攻击),要么直接将数据注入某个函数之中。而这些函数往往是被赋予了过多的权限,或是没有实施足够的强认证。和其他类型的代码一样,函数的脆弱性取决于那些易攻击的组件、不当的设计。

各种API、队列中的事件、甚至是存储系统中的事件所触发的某些函数,都会给无服务器体系结构增加新的风险。因此,这就会造成了:无服务器应用程序的执行流程不够清晰,而攻击面则较为复杂和多样。同时,现有的安全工具尚未适应函数的多种按需输入的特性。各种静态、动态和交互式的应用安全测试(Static/Dynamic/ Interactive Application Security Testing,SAST/DAST/IAST),常被大家运用在对于一些公认的、经典的HTTP接口的测试中。

其实,当各种事件能够相互触发、和调用彼此的各种无服务器函数时,使用分析工具来对每一种处理流程进行安全分析变成了所谓的NP-hard难题(译者注:非确定性多项式的数论难题,如著名的推销员旅行问题)。

作为分析安全性的一个视角,让我们来看看如何将OWASP top 10应用到无服务器的计算中。

1. 注入

通常,攻击者会向应用程序发送不可信的数据,通过在无服务器架构里运行,并过于频繁地调用其函数,以达到对应用程序的攻击效果。从概念上说,虽然使用API​​网关能够明确地处置对于某个函数的请求,但是无服务器平台却能允许存储事件(如:新建、或修改某些文件、或数据库的字段)、或消息队列去直接启动它们所请求的函数。可见,由于任何一种事件的触发,都可能包含攻击者的输入代码,因此,注入攻击是无服务器计算的一个首要安全问题。

2. 失效的身份认证

根据前面提到的漏洞,认证失效在无服务器函数中的“曝光率”则更高。传统应用程序的认证授权机制,通常能够作用到整个应用之中。例如:在应用程序中的所有函数,都统一使用一个令牌。即使是在微服务的环境中,我们也能通过统一的认证架构来对应用程序、及其所有函数进行控制访问。而当微服务被进一步分解成为具有更多函数模块的纳服务(nanoservice)时,它们就有了自己的一套访问控制机制。因此,当用户经由多个服务、去访问某个API端点、并写入存储的时候,该访问链上的每个环节,都会需要具有自己的认证机制。

3. 敏感数据泄漏

无服务器应用程序也可能会暴露一些受到薄弱保护的敏感数据。因此,我们在保护无服务器应用程序的安全性时,可能面对的一种挑战是:由于需要确保敏感数据对于多种函数是可用的,因此我们必须在横跨多个函数的情况下,共享不同的API密钥、加密密钥、或对外部服务的信任凭证,而它们的安全性显然难以得到保证。虽然,如今一些云服务供应商能够通过提供“密钥库(key vault)”系统,并实现在整个应用程序的范围内共享密钥,但是此概念尚属新潮,且不一定能被广大开发团队所理解。

4. 外部实体(XXE)

在许多无服务器应用程序的构建中,它们使用的是比XML更简单的数据格式(如JSON),因此,对于新的应用程序而言,OWASP top 10在此的风险倒没有那么显著。

5. 失效的访问控制 和 6 安全配置错误

与OWASP top 10的其他项相比,这两点威胁在无服务器计算中,比传统应用更为突出。一个典型的无服务器应用程序,一般是由一“串”函数所构成。某个函数的一个输入数据,往往会与若干外部数据的存储进行交互,进而产生相应的输出。这就是前面我们提到过的模型图。如果我们在FaaS平台上去构建一个完整的应用程序,那么它的流程图就应该是如下所示:

如何将OWASP Top 10应用到无服务器中以增加安全性

可见,由于每一种函数与所有的服务之间都存在着交互关系,因此要想根据安全部署的原则,正确地为每一个方面配置出函数,是非常困难的!几年前,Rapid7(译者注:全球领先的安全风险信息解决方案提供商)曾发文声称他们发现了近2000个开放的S3 buckets,而且每个都可能包含有某个函数链的输出(请参见:https://blog.rapid7.com/2013/03/27/open-s3-buckets/)。这就意味着攻击者可以潜入到某个函数之中,获取其输出数据。显然,您需要通过限制每个函数的使用权限,并配置为最低权限,以完成各种复杂的任务。

6. 跨站脚本

由于普通攻击者的目标仍然是那些最终用户、和他们的浏览器,因此就算是建立在无服务器的平台上,那些基于Web的应用程序仍然可能遭受到XSS攻击(请参见https://blog.tcell.io/2017/08/why-is-cross-site-scripting-so-hard)。因此,我们在无服务器上的部署、实施应用程序时,不可擅自修改、或未经测试地予以发布,以免带来XSS攻击的隐患。

7. 不安全的反序列化

和XXE(外部实体)攻击类似,反序列化攻击是通过在有效载荷中嵌入代码,以实施攻击。由于无服务器的函数可以按照任意顺序被调用,而且我们也无法“消毒”用户的输入,因此我们应当在无服务器的应用中,采取更加广泛的数据“消毒”方式,毕竟任何函数都无法信任它的任意输入。

8. 使用含有已知漏洞的组件

在这一项上,无服务器与传统应用的做法相同,即:只有了解您的应用程序会依赖到哪些软件包,才能更好地管理各种潜在的风险。

9. 不足的日志记录和监控