本文转自绿盟科技研究通讯公众号 《【云原生应用安全】云原生应用安全防护思考(二)》
专题信息
专题:【云原生应用安全】
往期回顾:
一. 概述
本文为云原生应用安全防护系列的第二篇,也是最终篇,本文笔者主要针对微服务架构下的应用安全、Serverless安全提出一些防护见解及思考。文章篇幅较长,内容上与之前笔者发表的若干文章有相互交叉对应的部分,希望能为各位读者带来帮助。
二. 微服务架构下的应用安全
针对《云原生应用安全风险思考》一文中对云原生应用的新风险分析,我们可以看出应用的微服务化带来的新风险主要包含数据泄露、未授权访问、被拒绝服务攻击,那么如何进行相应的防护也应从以上三方面去考虑,笔者通过调研和一些实践发现使用传统的防护方法是可行的,但当服务随业务的增多而逐渐增多时,传统的防护方法由于需要开发人员进行大量配置而变得非常复杂,例如用户的应用部署在Kubernetes上,该应用包含上百个服务,当我们做访问控制时可以依托Kubernetes的RBAC机制对目的服务进行授权,进而我们就需要依赖Kubernetes的API以完成配置,每次配置是会耗费一定时间的,因此需要大量服务授权时,开发者往往感到力不从心,为解决诸如以上服务治理带来的难题,我们可以使用微服务治理框架进行相应防护,笔者在2018年发表的《Service Mesh实践之Istio初体验》文章中对什么是Service Mesh及Istio的基本概念进行了相应介绍,从中可以看出Istio目前已成为第二代微服务治理框架的代表,因而笔者认为Istio的安全防护能力也是基本能够覆盖微服务应用安全范畴的。事实上,笔者在2019年发表的《Istio系列一:Istio的认证授权机制分析》一文中也对Istio的安全机制进行了介绍,不过当时Istio处于较早期版本,虽然与目前最新版本的Istio在功能实现稍有不同,但底层原理几乎未变,可供各位读者参考。
综上,笔者认为面向微服务架构下的应用安全,可以采用传统的防护方式或微服务治理框架进行防护,具体的防护方法可以包含以下几方面。
认证服务
由于攻击者在进行未授权访问前首先需要通过系统的认证,因而确保认证服务的有效性非常重要,尤其在微服务应用架构下,服务的不断增多将会导致其认证过程变得更为复杂。
授权服务
授权服务是针对未授权访问风险最直接的防护手段,微服务应用架构下,由于服务的权限映射相对复杂,因而会导致授权服务变得更难。
数据安全防护
与《云原生应用安全风险思考》一文中分析数据安全防护的必要性一样,但微服务应用架构下,服务间通信不仅使用HTTP协议,还会使用gRPC协议等,这是我们需要注意的地方。
其它防护
除了上述防护方法之外,微服务治理框架与API网关/WAF可以结合以进行深度防护,例如可以在一定程度上缓解微服务环境中被拒绝服务攻击的风险。
2.1 认证服务
微服务架构下,服务可以采用JWT或基于Istio的认证方式,下面笔者将分别进行说明。
2.1.1 基于JWT(JSON Web Token)的认证
微服务架构下,每个服务是无状态的,传统的session认证方式由于服务端需要存储客户端的登录状态因此在微服务中不再适用。理想的实现方式应为无状态登录,流程通常如下所示:
-
客户端请求某服务,服务端对用户进行登录认证;
-
认证通过,服务端将用户登录信息进行加密并形成令牌,最后再返回至客户端作为登录凭证;
-
在2步骤之后,客户端每次请求都需携带认证的令牌;
-
服务端对令牌进行解密,判断是否有效,若有效则认证通过,否则返回失败信息;
为了满足无状态登录,我们可通过JWT实现,JWT是JSON风格轻量级认证和授权规范,也就是上述流程中提到的令牌,主要用于分布式场景,其使用流程如图1所示:
2.1.2 基于Istio的认证
本节主要为各位读者介绍基于Istio的认证,在具体介绍前,我们首先为各位读者介绍Istio的安全架构,如下图所示:
图2展示了Istio的认证和授权两部分,Istio的安全机制涉及诸多组件,控制平面由核心组件Istiod提供,其中包含密钥及证书颁发机构(CA)、认证授权策略、网络配置等;数据平面则由Envoy代理、边缘代理(Ingress和Egress)组件构成。
借助控制平面Istiod内置的CA模块,Istio可实现为服务网格中的服务提供认证机制,该认证机制工作流程包含提供服务签名证书,并将证书分发至数据平面各个服务的Envoy代理中,当数据平面服务间建立通信时,服务旁的Envoy代理会拦截请求并采用签名证书和另一端服务的Envoy代理进行双向TLS认证从而建立安全传输通道,保障了数据安全。
下面笔者将为各位读者介绍Istio的两种主要认证类型。
2.1.2.1 传输认证(Peer authentication)
传输认证是Istio的一种认证类型,其主要用于微服务应用架构中服务到服务的认证,从而可验证所连接的客户端。针对此类型的认证,Istio提供了双向TLS的解决方案,该解决方案提供以下功能[1]:
-
确保服务到服务间的通信安全;
-
提供密钥管理系统,从而自动进行密钥及证书的生成、分发和轮换;
-
为每个服务提供一个代表其角色的身份,从而实现跨集群的互操作性。
具体的我们可以通过使用传输认证策略为Istio中的服务指定认证要求,例如命名空间级别TLS认证策略可以指定某命名空间下所有的Pod间的访问均使用TLS加密,Pod级别TLS认证策略可以指定某具体Pod被访问时需要进行TLS加密等,更多关于Istio的双向TLS解决方案内容可以参考官方文档[2]。
2.1.2.2 请求级认证(Request authentication)
请求级认证是Istio的一种认证类型,主要用于对终端用户的认证,与传输认证的主要区别为,请求级认证主要用于验证用户请求服务时携带的凭据,而非服务到服务的认证。
请求级认证主要通过JSON Web Token(JWT)机制实现,实现原理与前面“基于JWT的认证”小节中提到的内容类似,区别为Istio在其基础上进行了一层封装,使用户可以以yaml的方式进行策略配置,用户体验更为友好。
Istio的JWT认证主要依赖于JWKS(JSON Web Key Set), JWKS是一组密钥集合,其中包含用于验证JWT的公钥,在实际应用场景中,运维人员通过为服务部署JWT认证策略实现请求级认证,为方便理解,下面展示了JWT认证策略的核心部分配置:
issuer: https://example.com
jwksUri: https://example.com/.well-known/jwks.json
triggerRules:
- excludedPaths:
- exact: /status/version
includedPaths:
- prefix: /status/
其中:
issuer:代表发布JWT的发行者;
jwksUri:JWKS获取的地址,用于验证JWT的签名,jwksUri可以为远程服务器地址也可以为本地地址,其通常以域名或URL形式展现;
triggerRules(重要):triggerRules为使用JWT验证请求的规则触发列表,如果满足匹配规则就进行JWT验证,此参数使得服务间的认证变得弹性化,用户可以按需配置下发规则。上述策略中triggerRules的含义为对于任何带有“/status/”前缀的请求路径,除了/status/version以外,都需要JWT认证。
当JWT认证策略部署完成后,外部对某服务有新的请求时,请求级认证会根据策略内容验证请求携带的令牌(Token),若与策略内容匹配则返回认证失败,反之认证成功。
2.2 授权服务
微服务架构下,授权服务可以通过基于角色的授权以及基于Istio的授权实现,以下笔者将分别进行说明。
2.2.1 基于角色的授权服务
基于角色的授权服务为RBAC(RoleBased Access Control),通过角色关联用户,角色关联权限的方式间接赋予用户权限。在微服务环境中作为访问控制被广泛使用,RBAC可以增加微服务的扩展性,例如微服务场景中,每个服务作为一个实体,若要分配服务相同的权限,使用RBAC时只需设定一种角色,并赋予相应权限,再将此角色与指定的服务实体进行绑定即可。若要分配服务不同的权限,只需为不同的服务实体分配不同的角色,而无需对服务具体的权限进行修改,通过这种方式不仅可以大幅提升权限调整的效率,还降低了漏调权限的概率。
如果用户选择在Kubernetes中部署微服务应用,则可以直接使用Kubernetes原生的RBAC策略,具体使用方式可参考官方文档[3]。
2.2.2 基于Istio的授权服务
有了前述提到的Istio认证机制作为基础,Istio还提供授权机制,其主要用于对服务进行授权。在Istio 1.4版本之前,其授权机制依赖于Kubernetes的RBAC策略,相比Kubernetes的原生RBAC策略,Istio对其进行了进一步的封装,可让用户直接通过Istio的声明式API对具体的服务进行授权,不过Istio为了更好地用户体验,在其1.6版本中引入了AuthorizationPolicyCRD[16](Custom Resource Definition),相比1.4版本,AuthorizationPolicy CRD带来了更多的优势,一方面该CRD将RBAC的配置变得更为简化为从而大幅提升了用户体验,另一方面该CRD支持了更多的用例,例如对Ingress/Egress的支持,且同时不会增加复杂性。
此外,Istio的授权模式也是基于其提供的授权策略去实现。
图3展示了Istio的授权架构:
如图3所示,Istio授权流程可以归纳总结为以下内容:
Administrator使用yaml文件指定Istio授权策略并将其部署至Istiod核心组件中,Istiod通过API Server组件监测授权策略变更,若有更改,则获取新的策略,Istiod将授权策略下发至服务的Sidecar代理,每个Sidecar代理均包含一个授权引擎,在引擎运行时对请求进行授权。
以下是一个简单的Istio授权策略:
apiVersion:security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: httpbin
namespace: foo
spec:
selector:
matchLabels:
app: httpbin
version: v1
rules:
- from:
- source:
principals:["cluster.local/ns/default/sa/sleep"]
to:
- operation:
methods: ["GET"]
when:
- key: request.headers[version]
values: ["v1", "v2"]
可以看出,以上策略适用于foo命名空间下,且满足标签为app:httpbin和version: v1的目标Pod, 并设置授权规则为当访问源为“cluster.local/ns/default/sa/sleep”服务,且请求头中包含 v1 或 v2 的 version 字段时,才允许访问。默认情况下,任何与策略不匹配的请求都将被拒绝。
2.3 数据安全
如《云原生应用安全风险思考》一文中提到的,传统应用架构中,我们可以通过安全编码、使用密钥管理系统和使用安全协议的方式防止数据泄露,在微服务应用架构中,我们可以考虑使用Kubernetes原生的安全机制或微服务治理框架的安全机制去进行防护。
针对Kubernetes原生的安全机制,例如Secret机制,我们可以使用其进行密钥存储,从而规避了敏感信息硬编码带来的数据泄露风险,更详细的内容可以参考官方文档[4]。
针对微服务治理框架的安全机制,如Istio支持服务间的TLS双向加密、密钥管理及服务间的授权,因而可以有效规避由中间人攻击或未授权访问攻击带来的数据泄露风险。
2.4 其他防护机制
通过以上三小节的介绍,我们能从中看出采用微服务治理框架的防护方式可在一定程度上有效规避云原生应用的新风险,但其防护点主要针对的是微服务架构下应用的东西向流量,针对南北向的流量防护稍显脆弱,由于微服务架构下的应用防护应当是全流量防护,因而针对南北向所存在的问题,我们可以考虑将微服务治理框架与API网关和WAF相结合,从而提升南北向的防护能力。
本节笔者将以微服务治理框架Istio为例,为大家介绍Istio和API网关协同的全面防护以及Istio与WAF结合的深度防护。
2.4.1 Istio和API网关协同的全面防护
针对应用的南北流量而言,Istio采取的解决方案为使用边缘代理Ingress与Egress分别接管用户或外界服务到服务网格内部的入/出站流量,Ingress与Egress实则为Istio部署的两个Pod,Pod内部为一个Envoy代理,借助Envoy代理的安全Filter机制,在一定程度上可对恶意Web攻击进行相应防护,但现有的Envoy安全Filter种类相对较少,面对复杂变化场景下的Web攻击仍然无法应对,可行的解决方案为在服务网格之外部署一层云原生API网关,具体如图4所示:
安全功能上,云原生API网关可提供全方位的安全防护,例如访问控制、认证授权、证书管理、Bot流量检测、数据丢失防护、黑白名单限制等,在这些有效防护基础之上,应用的南北向得到了控制。
此外,该解决方案的好处还在于应用内部的东西流量无需通过外部网关层,这样可以从边缘到端点进行一站式防护。
2.4.2 Istio和WAF结合的深度防护
WAF作为一款抵御常见Web攻击的主流安全产品,可以有效对Web流量进行深度防护,并且随着云原生化概念的普及,国内外安全厂商的容器化WAF产品也在迅速落地,未来容器化WAF与Istio的结合将会在很大程度上提升微服务安全。
根据近期市场调研,Signal Sciences、Fortiweb、Wallarm、Radware这几家公司已有了各自的容器化WAF解决方案。值得注意的是Signal Sciences 公司的解决方案支持WAF服务与Envoy或Istio结合,其设计如图5所示,该方案主要运用了Envoy的Filter机制,通过External Authorization HTTP Filter可以将流经业务容器的东西/南北向流量引流至WAF容器,从而可阻断恶意请求,保护了微服务的安全。
此方案带来的好处是对业务入侵较小,实现较为容易、且容器化WAF规模不会随用户业务更改而更改。但同时也有一些弊端,比如需要单独部署容器化WAF、Envoy引流模块的性能问题、引流方式对WAF处理的延迟等。
另一种解决方案是Radware提出的Kubernetes WAF方案,该方案基于Istio实现,其中WAF被拆分为Agent程序和后端服务两部分,Agent程序作为Sidecar容器置于Pod的Envoy容器和业务容器间,该Sidecar的主要作用为启动一个反向代理,以便将外部请求流量代理至Pod外部的WAF后端服务中,如图6所示。该套方案带来的好处是无需关心外部请求如何路由至Pod、与Istio结合的理念更接近云原生化、实现了以单个服务为粒度的防护。但同时也存在着一些不足,例如流量到达业务容器前经历了两跳,这在大规模并发场景下可能会影响效率。
此外,由于Istio的数据平面为微服务应用安全防护提供了引擎,而数据平面默认采取Envoy作为Sidecar代理,因此Envoy自身的扩展性成为了安全厂商较为关心的问题,近些年Envoy也在不断提升着其适配性,例如Envoy提供Lua过滤器[5]和Wasm过滤器[6],以便安全厂商将安全能力,例如WAF的能力融入Envoy, 从而对微服务应用进行防护。
三. Serverless安全防护
3.1 Serverless应用安全防护
通过《云原生应用安全风险思考》一文中的Serverless风险分析,我们了解到传统应用的风险几乎可以覆盖Serverless应用的风险,因而针对Serverless应用的安全防护各位读者可以大体参考《【云原生应用安全】云原生应用安全防护思考(一)》一文中传统应用安全的防护方式,尤其是应用程序的代码漏洞缓解、依赖库漏洞防护、数据安全防护。
针对应用程序访问控制,除了《【云原生应用安全】云原生应用安全防护思考(一)》中提到的使用基于角色的访问控制之外,由于Serverless云计算模式带来的变化,还需要进行更深层次的防护,笔者认为函数隔离及底层资源隔离是较为合适的防护方法。
函数隔离
函数间进行隔离可有效降低安全风险。一个FaaS应用通常由许多函数以既定的序列和逻辑组成,每个函数可以独立进行扩展、部署等,但也同时可能被攻破,如果安全团队没有对函数进行有效隔离,那么攻击者也可同时访问应用中的其它函数。再如随着应用设计不断变化,这些函数更改了执行序列,从而使攻击者有机可乘并发起业务逻辑攻击,这些是FaaS产生的碎片化问题。正确的做法应当是将每个函数作为边界,使得安全控制粒度细化至函数级别,这对于创建能够长期保持安全的FaaS应用是非常必要的。
为了更好地将函数进行隔离,笔者认为应当从以下几方面进行考虑:
-
不要过度依赖函数的调用序列,因为随着时间推移调用序列可能会改变;如果序列发生了变化,要进行相应的安全审查;
-
每个函数都应当将任何事件输入视为不受信任的源,并同时对输入进行安全校验;
-
开发标准化的通用安全库,并强制每个函数使用;
-
使用FaaS平台提供的函数隔离机制,例如AWSLambda采用Amazon弹性计算云(ElasticCompute Cloud EC2)模型[7]和安全容器Firecracker模型[8]机制进行隔离。
底层资源隔离
仅仅对函数层面进行访问控制是不够的,例如攻击者仍可以利用函数运行时环境的脆弱性以获取服务端的shell权限从而进行滥用,笔者在之前发表的《【云原生攻防研究 】针对AWS Lambda的运行时攻击》有详细的利用过程,可供各位读者参考。
为了预防上述场景的发生,我们应当从底层进行资源隔离,例如可通过KataContainer[9]从上至下进行防护,再如可通过Kubernetes的网络策略(NetworkPolicy)[10]实现由左至右的网络层面隔离。
3.2 Serverless平台安全防护
针对《云原生应用安全风险思考》一文中提出的Serverless平台风险,我们可以考虑通过以下几种防护方式进行相应缓解。
3.2.1 使用云厂商提供的存储最佳实践
为了尽量避免用户在使用云厂商提供的Serverless平台时因不安全的错误配置造成数据泄露的风险,主流云厂商均提供了相应的存储最佳实践供各位开发者参考,例如Howto secure AWS S3 Resources[11]、Azure Storage SecurityGuide[12]、Best Practices for Google Cloud Storage[13]等。
3.2.2 使用云厂商的监控资源
现今各大云厂商均为Serverless配备了相应的监控资源,例如AzureMonitor、AWS CloudWatch、AWSCloudTrail等,使用云这些监控资源可以识别和报告异常行为,例如未授权访问、过度执行的函数、过长的执行时间等。
3.2.3 使用云厂商的账单告警机制
针对拒绝钱包服务(DoW)攻击,公有云厂商提供了账单告警机制进行缓解[14],如AWS开发者可通过在Lambda控制台为函数调用频度和单次调用费用设定阈值进行告警;或提供资源限额的配置,主流的云厂商已提供了以下资源选项供开发者配置:
-
函数执行内存分配;
-
函数执行所需临时的磁盘容量;
-
函数执行的进程数和线程数;
-
函数执行时常;
-
函数接收载荷大小;
-
函数并发执行数;
通过上述选项的合理配置可以在一定程度上缓解DoW攻击。
3.3 Serverless被滥用的防护措施
针对《云原生应用安全风险思考》一文提出的Serverless被滥用的风险,我们可以采取以下方式进行防护[15]:
-
通过IDS等安全设备监测木马在本机的出口流量,诸如“/pixel”、“/utm.gif”、“ga.js”等URL的流量应进行重点监测;
-
确认自己的资产中是否有云厂商提供的Serverless函数业务,如果没有可以通过浏览器禁用相关云厂商的子域名;
-
采取断网措施,从根源上直接禁止所有网络访问。
3.4 其他防护措施
3.4.1 Serverless资产业务梳理
由于云厂商通常缺乏一套自动化机制对现有Serverless应用中包含的函数,数据及可用API进行分类、追踪,评估等操作,因此开发者在不断完善应用的同时,可能疏于对应用数据及API的管理,从而导致攻击者利用敏感数据、不安全的API发起攻击。为了避免这种情况,开发者需要在应用的设计阶段对资产业务进行详细梳理。其中包括但不限于以下几个部分:
-
确认应用中函数间的逻辑关系;
-
确认应用的数据类型及数据的敏感性;
-
评估Serverless数据的价值;
-
评估可访问数据API的安全;
有了一个较为全面的应用全景图,便可在一定程度上降低应用被攻击的风险。
3.4.2 定期清理非必要的Serverless实例
由于Serverless应用通常遵循微服务的设计模式,因此一套完整的工作流应由许多函数组成,而开发者可能部署了非常多的Serverless应用,在这些应用中,必定存在一些长时间不被调用的实例,为了避免被攻击者利用,应当定期对Serverless应用进行检测,清理非必要的实例,从而降低安全隐患。
3.4.3 限制函数策略
开发者首先应当限制函数策略,给予其适当的访问权限,删除过于宽松的权限,这样即便攻击者拿到了访问凭证也无法对所有资源进行访问。
四. 总结
本文较为系统地对微服务架构下的应用安全及Serverless安全提供了相应的防护思路,其中:
针对《云原生应用安全风险思考》一文提出的云原生应用的新风险,我们可以看出应用架构的变化是带来新风险的主要原因,鉴于此,本文笔者针对具体的风险提出了防护方法,其中,使用微服务治理框架Istio可以在一定程度上缓解应用架构带来的风险,此外,也介绍了Istio与API网关和WAF结合的业界方案,从而可实现微服务应用的全流量防护。
针对《云原生应用安全风险思考》一文提出的Serverless风险,笔者较为系统地从Serverless应用及平台两方面对前述提到的Serverless风险进行了相应防护介绍。可以看出,与传统安全防护不同的是Serverless模式带来的新型云原生下的应用安全场景,因而,我们需要适应云计算模式的不断变化,并不断总结新场景下的防护方法,才能最终将安全落实到底。
五. 参考文献
[1] https://istio.io/latest/docs/concepts/security/#authentication
[2] https://istio.io/latest/docs/concepts/security/#mutual-tls-authentication
[3] https://kubernetes.io/docs/reference/access-authn-authz/rbac/
[4] https://kubernetes.io/docs/concepts/configuration/secret/
[5] https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/lua_filter
[7] https://docs.aws.amazon.com/lambda/latest/dg/services-ec2.html
[8] https://firecracker-microvm.github.io/
[9] https://github.com/kata-containers
[10] https://kubernetes.io/docs/concepts/services-networking/network-policies/
[11] https://aws.amazon.com/cn/premiumsupport/knowledge-center/secure-s3-resources/
[12] https://docs.microsoft.com/en-us/azure/storage/blobs/security-recommendations
[13] https://cloud.google.com/storage/docs/best-practices#security
[16] https://istio.io/latest/docs/reference/config/security/authorization-policy/
「真诚赞赏,手留余香」
真诚赞赏,手留余香