建议专门为Serverless应用开发一个子账号
这个账号只有函数计算的FullAccess并且只能编程访问。创建之后就会得到AccessKey和Secret,给账号授权:发布、更新函数、管理计费服务的权限。更安全点让这个AK只管理某个服务或服务下的某个函数。
这个时候就可以使用自定义策略。
自定义策略
允许该服务下的所有函数的所有操作。
有些开发框架允许你通过YAML去配置其他云服务,并且在你部署时会自动帮你创建或更新这些服务,这个时候就需要Serverless开发账号也需要具体云服务的权限。
如何使用日志服务存储函数的日志
本质上如何让函数访问日志服务,也就是前面所提到的云服务授权。
首先需要创建一个角色。
ARN是角色的唯一标识,角色扮演的时候就会使用到ARN。
在A账号的函数中访问B账号的OSS文件,可以通过角色扮演来实现第三个场景。
- • 账号A 扮演角色RoleForServerlessApp
- • 账号访问凭证 token1
- • 将token1 注入到函数上下文
- • 扮演角色RoleForAccountA
- • 访问凭证token2
- • 使用token2访问账号B的对象存储
从上下文context当中获取临时访问凭证token1
小结
云厂商主要通过主账号、角色、权限策略等方式来实现云上资源的访问控制,通过访问控制,能实现分权、云服务授权、跨账号授权等云上资源管控需求。实际工作中,对于用户访问权限要遵循最小授权原则。
Servreless安全问题
Serverless安全面临的挑战
软件开发者专注产品功能的实现;完全不用考了底层服务器操作系统以及软件运行环境;无须为服务和操作系统安全安全补丁。
- • 应用所有者负责云内部的安全性
包括客户端、存储在云中的数据、传输中的数据、应用(函数)、身份认证、访问控制、云服务配置
- • Serverless提供商负责云本身的安全性
操作系统、虚拟机、容器、计算、存储、数据库、网络、地域、可用区、边缘节点
- • 攻击面越来越广
由于Serverless中函数的数据来自多种数据源,这就极大增加了攻击面,特别是当数据源消息结构非常复杂时,传统的Web防火墙方式就很难对数据进行校验。
- • 攻击方式越来越复杂
除了传统的DDos攻击、数据注入等攻击方式,Serverless还面临着事件注入,流程劫持等新的攻击方式。
- • 可观测性不足
日志、监控指标、链路追踪等方式。
因为Serverless对开发者来说是屏蔽了底层基础设施且应用是由分布式的函数组成,所以Serverless应用的可观测性比传统应用更复杂
- • 传统安全测试方法不适用
当Serverless应用依赖了第三方服务或云服务,虽然在单元测试时这些依赖可以被模拟,但进行安全测试却不能模拟。
传统的DAST
(动态应用程序安全性测试)工具对Serverless应用不适用,主要是扫描HTTP接口进行安全测试,但很多Serverless数据源都不是Http触发器,所以DAST攻击很难对非http Serverless应用进行扫描。
SAST
(静态应用程序的安全性测试)这类工具主要是通过分析代码语法、结构、接口、控制流等检测程序等漏洞。Serverless使用了很多触发器和云服务,很多静态分析工具并没有考虑这种情况,所以就很容易出现误报。
IAST
(交互式应用程序安全性测试)这类工具通过将流量代理到测试服务器等方式进而可以得到更高的准确率、更低的误报率。这种方式对非http接口或依赖了云服务的Serverless应用依旧不适用,很难进行流量代理。
- • 传统安全防护方案不兼容
传统的安全防护方案
基于Serverless的应用没有办法访问物理机或虚拟机,所以没有办法随机部署传统的安全层,比如端点防护、Web防火墙
大多数传统安全防护方案与Serverless架构不兼容。
Serverless安全的主要风险
- • 函数事件注入
数据注入是最常见的安全风险,比如SQL注入、XSS注入。不过在传统应用中,这些数据注入都是用户输入的数据,而Serverless应用的数据不局限于用户输入。比如API的请求参数,还有大量的触发器,提供了丰富的数据源。
这些数据源都可以触发Serverless函数的执行。这些不同数据源的数据会以参数的形式传给Serverless函数,这些函数的输入、不同数据源的通信协议、编码方式、也都不尽相同。
丰富的数据源不仅增加了潜在的攻击面,也增加了安全防护的复杂性。
因为这些数据可能包含了攻击者的输入或者其他危险的输入,开发者很难判断哪些是正常数据哪些是危险数据。
比如在传统应用当中可以通过消息头请求参数来判断数据是否危险,但是在Serverless架构中的非http数据源就很难通过简单的请求消息判断了。
- • 身份认证无效
Serverless架构的应用是由几十甚至上百个函数组成,每个函数实现特定的业务功能,这些函数组合完成整体业务逻辑,一些函数可能会公开其Web API,需要进行身份认证,另一些则可能只允许内部访问,所以不用进行身份认证。
为每个函数或事件源提供合理的身份认证机制
- • 应用配置不安全
通常这些配置放在云厂商提供的配置中心,甚至直接存放在云存储中。
在云上运行的应用,尤其是Serverless应用,经常会使用到很多应用配置,另外你还会基于配置来实现环境区分,功能开关逻辑。对于配置中心或存放应用配置的云存储授权不当,这很可能造成应用敏感信息泄漏,或没有权限的用户不小心修改配置导致应用无法运行。
- • 用户或角色权限过高
Serverless应用应该秉持最小权限的原则,也就是仅给函数提供其执行时所必需的权限。很多开发者或团队为了方便,就为函数设置了统一的较大的权限,如果一个应用中函数权限过高,那单个函数的漏洞可能造成系统级灾难。
- • 函数日志和监控能力不足
虽然云厂商都对函数提供了日志和监控功能,但这些功能都很新,提供的能力也有限。要想利用这些功能来可视化Serverless架构的运行情况还非常困难。函数日志和监控能力的不足,就会导致面临攻击时你就很难针对Serverless攻击进行报警,也很难通过日志去分析、排查解决问题。
- • 第三方依赖不安全
Sererless函数的执行环境是安全隔离的环境。
很多时候为了完成业务逻辑,函数就要依赖第三方软件包,开源库甚至通过API调用第三方远程Web服务。如果函数的第三方依赖不安全,也很可能导致函数不安全。
- • 敏感信息泄漏
随着应用规模和复杂性的增长,应用需要维护未来越多的敏感信息,比如访问凭证(AccesskeyId、AccessKeySecret和SeccrityToken)、数据库密码、加密密钥等。常见的错误做法是:把这些敏感信息简单的放在项目配置文件中,随代码一起上传。
- • DDoS和资损
DDos几乎成了每个暴露在互联网上的服务面临的主要风险之一,比如大量恶意运行函数造成资损。
使函数一直挂起直到超时。
代码示例
由于boundary属性完全在请求方的控制下,恶意的用户就可以利用boundary构造请求数据给函数发起DDo是攻击。
当函数传入这个字符串的时候,构造正则表达式,解析请求体,由于效率很低,就会一直卡在这里,进而造成cpu使用率持续100%,如果这段代码放在Lambda执行,函数最终会超时而被Lambda强制结束。
攻击者就会对这个函数发起大量恶意的请求,进而生成大量的函数实例,直到超过函数最大并发和实例数限制,并且每个函数实例都会持续的运行进而超时,进而导致其他用户无法正常访问。由于函数是由实际使用时长计费的这也会增加你的费用。
- • 函数执行流程操纵
通过操作函数执行流程,攻击者可以破坏应用逻辑并且还可以利用该方式绕过访问控制、提升用户权限、甚至发起DDos攻击。在传统应用中很常见,但在Serverless应用中风险更大。
Serverless应用是由很多离散的函数组成,这些函数按特定顺序编排到一起,形成整体应用。
如果函数依赖其他云服务存储状态,那么状态存储和共享的过程也有可能称为攻击的目标。
假设有个应用需要对上传到云存储的文件进行加密。
函数1是校验文件完整性、检查文件大小是否为64KB,消息内容为待发送的文件名;函数2由消息触发器触发执行;函数2接收到消息之后,从消息内容解析文件名称,然后对文件进行加密。
函数2中恶意的方式:
1、云存储没有合适的访问控制,绕过文件完整性校验而直接上传文件,导致用户恶意上传大量文件。
2、如果消息队列没有设置合适的访问控制,任何用户都可以发送大量文件上传消息,使得函数2恶意执行。
- • 错误处理不当
1、由于Serverless的调试方式还比较有限,所以很多开发者喜欢直接在FaaS平台上打印函数运行的日志,以及冗长的错误信息;如果一些敏感信息没有被清除,可能导致敏感信息泄漏在日志中或日志中记录了详细的错误堆栈,暴露代码的漏洞。
2、代码处理不当,导致程序被挂起,一直无法运行结束。不管是传统应用还是Serverless架构的应用,都存在安全风险,因此你要先深入了解应用架构中的风险点,这样才能对症下药,解决问题。