应用存储的数据基于 API进行访问,若应用中某个 API含有漏洞或通信未采用加密协议,攻击者便 可利用漏洞进行越权或中间人攻击,从而达到数据窃取的目的。
容器镜像为承载云原生
应用的实体,开发者将敏感信息写入 Dockerfile、源码或以环境变量的方式 进行传递,这种行为增加了数据泄露的风险,随着微服务数量的不断增多,其造成的损失也呈指数增长。Kuberenetes 作为主流的微服务管理平台内置了许多安全机制,但默认值通常并不安全,例如我们 创建了 Secrets 资源用于存储数据库
登录信息,虽然这是一种正确存储敏感信息的方式,但默认情况下, Kubernetes 在 Etcd 组件中存储的信息是明文的,如果未对 Etcd 组件开启 TLS访问,攻击者一旦进入 Kubernetes 集群内部便可对 Etcd 组件进行访问从而造成大量微服务密钥信息泄露。服务网格场景中,当微服务数量达到一定规模,API数量将不断递增,从而增大了数据泄露的风险。 另外,微服务间有着复杂的网络拓扑,如果服务间的通信流量未加密,攻击者一旦进入服务内部网络, 便可通过截获请求中的敏感传输数据(例如用户名、密码、密钥信息等)进行中间人攻击。
应用架构的改变使微服务授权面临新的风险。在单体应用架构下,应用作为一个整体对用户进行授 权。在微服务场景下,所有的服务均需对各自的访问进行授权,明确当前用户的访问控制权限。传统的 单体应用访问来源相对单一,基本为浏览器
,而微服务的访问来源还包括内部的其它微服务,因此,微 服务授权除了服务对用户的授权,还增加了服务对服务的授权。Kubernetes 中,内部容器间访问控制和隔离可使用网络策略(NetworkPolicy)实现,但其默认情 况下 Pod 之间是互通的,这也就意味着网络策略是以白名单的模式出现,因此如果不对 Pod 之间的访 问进行显示授权,一旦集群内部的某一 Pod 失陷,便会极速扩展至整个集群的 Pod 失陷。
OWASP发布了 Web 应用安全 10 大风险,其中对常见的 Web 攻击风险进行了详细的总结 [17]。Web 攻击作为应用层的主要攻击类型,在微服务架构中也依然存在,其风险同时不容小觑。
与网络层的安全不同,业务层面的安全往往没有明显的网络攻击特征。攻击者可以利用业务系统的 漏洞或者规则对业务系统进行攻击来获利,给业务系统造成损失。
在微服务架构下,各服务如果安全措施不完善,例如用户鉴权、请求来源校验不到位,将会导致针 对微服务业务层面的攻击变得更加容易。例如针对一个电商应用,攻击者可以对特定的服务进行攻击, 例如通过 API传入非法数据,或者直接修改微服务的数据库系统等。攻击者可以绕过验证码服务,直接 调用订单管理服务来进行薅羊毛操作。攻击者甚至可以通过直接修改订单管理和支付所对应的微服务系 统,绕过支付的步骤,直接成功购买商品等。
在云原生环境中,编排系统无疑处于重中之重的地位,而 Kubernetes 早已成为容器编排系统的“事 实标准”。本节,我们来从控制权限陷落、拒绝服务攻击和网络安全风险三个方面去介绍管理编排系统 的潜在风险。
Kubernetes 组件的不安全配置。 由于 Kubernetes 组件众多、各组件配置复杂,不安全配置引起 的风险不容小觑。比如 Kubernetes API Server 的未授权访问,Kubernetes Dashboard 的未授权访问, Kubelet 的未授权访问等。
以 API Server 的未授权访问为例,默认情况下,API Server 能够在两个端口上对外供服务: 8080 和 6443,前者以 HTTP 协议提供服务,无认证和授权机制;后者以 HTTPS 协议提供服务,支持认证和 授权服务。
在较新版本的 Kubernetes 中,8080 端口的 HTTP 服务默认不启动。然而,如果用户在启用了 8080 端口并重启 API Server,那么只要网络可达,攻击者即可通过此端口操控集群。
Kubernetes 权限提升。 以 CVE-2018-1002105 漏洞为例,这是一个 Kubernetes 的权限升漏洞, 允许攻击者在拥有集群内低权限的情况下升权限至 Kubernetes API Server 权限,CVSS 3.x 评分为
9.8[18]。通过构造一个对 Kubernetes API Server 的特殊请求,攻击者能够借助 Kubernetes API Server 作 为代理,建立一个到后端服务器的连接。利用该连接,攻击者能够以 Kubernetes API Server 的身份向 后端服务器发送任意请求,实现权限提升。
突破隔离,访问宿主机文件系统。 以 CVE-2017-1002101 漏洞为例,这是一个 Kubernetes 的文件 系统逃逸漏洞,允许攻击者使用 subPath 卷挂载来访问卷空间外的文件或目录,CVSS 3.x评分为 9.8[19]。 所有 v1.3.x、v1.4.x、v1.5.x、v1.6.x 及低于 v1.7.14、v1.8.9 和 v1.9.4 版本的 Kubernetes 均受到影响。
这个漏洞本质上是 Linux符号链接特性与 Kubernetes 自身代码逻辑两部分结合的产物。符号链接 引起的问题并不新鲜,这里它与虚拟化隔离技术碰撞出了逃逸问题,以前还曾有过在传统主机安全领域 与 SUID概念碰撞出的权限提升问题等 [20]。
拒绝服务攻击有多种类型。常见的是基于流量的拒绝服务攻击和基于漏洞的拒绝服务攻击。
传统环境和云原生环境的流量攻击的差异性较小,攻击效果通常取决于流量大小。基于漏洞的拒绝 服务攻击则不然,存在于云原生组件的拒绝服务漏洞很可能并不存在于传统主机环境,典型的漏洞包括 CVE-2019-11253、CVE-2019-9512、CVE-2019-9514 等。
默认情况下,Kubernetes 集群中所有 pod 组成了一个小型的局域网络,那么就可能发生像中间人 攻击这样的针对局域网的攻击行为。
假如攻击者借助 Web 渗透等方式攻破了某个 Pod,就有可能针对集群内的其他 Pod 发起中间人攻 击,进而进行 DNS劫持等。例如,攻击者攻破一个前端服务(Web APP Pod)之后,通过 ARP欺骗诱 导另一个后端服务(Backend Pod)以为 Web APP Pod 是集群的 DNS服务器,进而使得 Backend Pod 在对外发起针对某域名(example.com)的 HTTP 请求时首先向 Web APP Pod 发起 DNS 查询请求。 Backend Pod 以为自己拿到了正确的信息,其实不然。攻击者能够潜伏在集群中,不断对其他 Pod 的
网络流量进行窃听,甚至可以悄无声息地劫持、篡改集群其他 Pod 的网络通信,危害极大。
服务网格是一个微服务的基础设施层,主要用于处理服务间的通信。通常云原生应用会有大量微服 务,微服务组成了复杂的服务拓扑,服务网格负责在这些拓扑中实现请求的可靠传递。在实践中,服务 网格通常实现为一组轻量级网络代理,它们与应用程序部署在一起,而对应用程序透明。Istio 是一款典 型的微服务管理和服务网格框架项目,其架构图 [21]如下所示:
图 3.2 Istio 架构图
Istio 架构的设计类似软件定义网络,主要分为控制平面和数据平面两个部分,其中数据平面由一组 代理组成并以 Sidecar 的形式部署在服务旁,这些代理负责管理服务间的所有网络通信;控制平面用于 对数据平面的代理进行管理和配置,具有应用无感知、可扩展、统一管理等优点。然而,引入新的架构 设计同时会引入新的风险,服务网格带来的安全风险不容小觑。
在当前的服务网格中,服务与服务间通过 Sidecar 进行通信,Istio 的 Sidecar 使用 Envoy 作为边车 代理,默认情况下,由于 Envoy 未对服务间的通信采用双向 TLS认证,所以攻击者一旦入侵某服务, 便可在服务网格中自由进行横向移动,进而发起攻击。一方面,攻击者可在服务通信时进行中间人攻击, 通过截取、修改、伪造通信内容造成数据泄漏;另一方面,攻击者也可以伪造服务身份进行通信,从而 破坏整个微服务网络。
服务网格认证授权面临安全风险主要分为以下两种类型:
东西向的认证授权:东西向流量是微服务间的流量,即服务网格内部流量。由于请求在到达业务容 器前首先经过 Sidecar 容器,因此为了向服务间下发访问控制策略,Sidecar 容器应具备有流量管理、 元数据收集、安全控制等功能,Istio 主要采用 Envoy 内部的 filter 机制实现上述功能。默认情况下, Envoy 容器通过修改 Pod 底层 iptbales 实现流量的重定向,这一操作只是起到了流量传递的作用,并未 对流量进行任何限制,这无疑是非常危险的。如果未对服务网格的服务间下发有效认证授权策略,一旦 服务网格中的服务 A有权限对服务 B进行访问,便也可对网格中的其它服务进行访问,那么在微服务 内网被攻破的前提下,攻击者可以进行任意越权操作,从而造成严重损失。
南北向的认证授权:外界服务访问微服务的流量为南北向流量。在服务网格设计中,通常南北向流 量会经过服务网格边界处的 API网关,后者会对外部的 API请求做负载均衡、请求频次控制和安全控制 等,若 API网关供的防护能力不强,则攻击者可利用应用程序漏洞恶意访问服务,并利用服务间未授 权访问漏洞进行进一步的提权操作,从而最终控制整个微服务网络,造成了严重的损失。
2016 年 8 月,martinfowler.com 网站上发表的《Serverless》[22]一文中对 Serverless 概念做了阐述: Serverless 可在不考虑服务器的情况下构建并运行应用程序和服务,它使开发者避免了基础设施管理, 例如集群配置、漏洞修补、系统维护等。Serverless 并非字面理解的不需要服务器,只是服务器均交由 第三方管理。
FaaS(Function as a Service)是 Serverless 主要的实现方式,开发者通过编写一段代码,并定义 何时以及如何调用该函数,随后该函数在云厂商供的服务端运行,全程开发者只需编写并维护一段功 能代码即可,比如广泛使用的 AWS Lambda 服务。
Serverless 是新的云计算模式,在给开发者带来便利的同时,其安全风险也备受关注。由于 Serverless 架构包含开发者侧及服务提供商侧,因此其安全架构也有相应的责任划分。
下文主要从开发者面临的安全威胁出发,大致分为五类。
如果应用程序未对外界输入数据进行过滤或编码校验,那么它们就可能存在 SQL注入、系统命令执 行等攻击成功的风险。在传统应用程序开发中,开发者根据自身实践经验,在数量有限的可能性中可判 定出恶意输入来源,但 Serverless 模式下函数调用是由事件源触发,如下图所示,输入来源的不确定性 限制了开发者的判定。
图 3.3 函数事件源触发示意图
通常来说,当函数订阅一个事件源后,该函数在该类型的事件发生时被触发,这些事件可能来源 于 FaaS 平台,也可能来源于未知的事件源,对于来源未知的事件源可以被标注为不受信任。在实际应 用场景中,如果开发者没有良好的习惯对事件源进行分类,则会经常导致将不受信任的事件错认为是 FaaS 平台事件,进而将其视为受信任的输入来处理,最终受到了大量注入攻击。
关于 Serverless 下应用程序的注入攻击实例可以参考 OWASP(Open Web Application Security Platform)组织在 2017 年发布的《Top 10 Interpretation for Serverless》报告 [23]。
开发者在编写应用程序时不可避免的会引入第三方依赖库,这就引入了一个非常严的问题:开发 者是否使用了含有漏洞的依赖库。
据 Synk 公司在 2019 年的开源软件安全报告 [24]中透露,已知的应用程序安全漏洞在过去两年增加 了 88%。即便开发者编写的函数只有短短几十行无漏洞的代码,但只要引入了第三方含有漏洞的依赖库, 那么该函数也是存在脆弱性的。
此外,引入了第三方依赖库也会实际增加应用部署至服务器的代码总量,例如 python 库,其代码 量可能是上千行,node.js 的 npm 包中的代码量就更大了,可能会导致上万行。即便没有已知漏洞,但 随着代码量的增多,潜在的风险也相应增加,从而给 Serverless 应用带来了极大安全隐患。
近年来,随着业界对不安全的第三方依赖库的重视,许多行内报告例如 OWASP Top 10[25]项目出 了使用已知漏洞依赖库的安全风险,这些含有漏洞的依赖库可在 CVE、NVD等网站上进行查询,例如 Node.js 库 CVE漏洞列表 [26]、Java 库 CVE漏洞列表 [27]、Python 库 CVE漏洞列表 [28]。