【摘 要】 本文对企业云原生架构特点和云原生环境下容器、容器编排平台、网络以及微服务应用等方面面临的安全风险进行了分析说明,给出了云原生环境下安全机制左移、容器运行时行为的聚焦、最小权限原则和零信任架构的防护思路,并针对云原生风险,结合云原生防护思路提出了云原生全生命周期的安全防护解决方案。
【关键词】 云原生 云安全 容器
1 引言
云计算的快速发展和业务系统快速迭代部署、可移植性、可扩展性等需求的不断增长,促使容器化、服务网格、微服务、无服务等云原生(Cloud Native)技术得到企业的广泛关注和应用。云原生应用的敏捷、高效、弹性扩展等特性在企业数字化转型和降本增效、专注业务价值效率方面发挥着重大助力作用,但随之而来的安全问题也日益突出,构建全方位的云原生环境安全体系是企业“上云”的必经之路。
2 云原生环境及面临的安全挑战和风险
大型企业从传统的IT系统转型升级为云原生应用系统往往按照不同的业务域,分类、分段、分层建设,应用架构体系则从基础设施架构和业务能力架构两方面不断抽象发展融合。一方面,下沉应用系统的全部基础设施,将业务逻辑与基础设施完全解耦,应用端聚焦业务创新和逻辑功能实现,基础设施提供物理服务器到应用系统函数代码之间的全部技术架构和工具软件,如容器、编排引擎、服务网格、无服务计算等。另一方面,开展业务逻辑能力的抽象设计,提取共性下沉至可复用的赋能平台,形成小而精的业务灵活创新前台和厚而广的共性能力赋能中台。
在基于“大中台、小前台”的平台赋能支撑下,云原生的数字化环境可以很好地满足各业务领域的功能复用与快速迭代、数据共享与互通、需求敏捷开发与高效交付、应用流水线部署与滚动升级、资源弹性扩展与实时在线以及运维自动化和智能化的要求。
云原生技术作为企业数字业务应用创新的原动力,在进入生产环境实现云原生应用全生命周期管理,发挥数字业务快速交付与迭代的优势过程中,也带来了新的安全风险和挑战。
云原生安全并不独特,传统IT环境下的安全问题在云环境下仍然存在,如DoS攻击、内部越权、漏洞攻击、数据篡改、数据泄露等。同时,由云原生架构的多租户、虚拟化、快速弹性伸缩等特点和业务应用微服务化带来的软件架构复杂度的大幅提升,内部网络流量、服务通信端口、容器等出现、消失的动态变化,业务微服务化后大量服务认证、访问授权控制机制的自动配置管理,开发测试和生产环境中持续集成和持续交付自动化流水线的各环节的安全保护,以及未能及时跟上云原生技术快速发展而缺位的云原生安全策略和防护工具等问题,都使运行在云原生环境下的业务应用和数据面临潜在安全风险。
与传统安全技术相比,云原生安全技术表现出了明显的不同,技术架构由下至上可分为容器、虚拟化、宿主机运行时安全、编排平台、服务网格安全、微服务、无服务安全,以及与开发运维过程相关的持续集成与持续部署(CI/CD)、开发运维一体化(DevOps)和运行过程的监控、追踪和测量等安全技术。简而言之,传统安全更重视边界防护,而云原生安全更重视持续、动态和整体的安全防护。
2.1 容器环境的风险
容器技术是云原生技术体系的基石,容器是宿主机上的进程,其技术本质是对宿主机操作系统的一层虚拟化,通过操作系统命名空间(Namespace)实现不同容器间主机名与域名、信号量/消息队列和共享内存、进程编号、网络设备、网络栈、端口、文件挂载点、用户和用户组环境的隔离;通过控制组(Cgroup)将容器进程或线程分隔到按资源划分等级的不同组内,实现对不同容器资源的使用限制。容器采用镜像的方法创建,以虚拟化隔离和资源受限的方式运行在宿主机上,通过容器运行时接口(CRI)接受外部管理和调度。镜像具有分层构建、写时复制、内容寻址、联合挂载等特征。
容器直接运行于宿主机操作系统之上,与以硬件层支持实现的虚拟化技术比较,更容易出现逃逸风险。攻击者往往首先通过劫持容器内部业务逻辑或直接控制等方式(如远程攻击、恶意容器、恶意租用),获得容器内某种权限下的命令执行能力,之后借助技术手段进一步获得该容器所在宿主机上某些权限的命令执行能力并获取相应资源。
例如,通过配置特权模式可使容器获得与宿主机相同根权限(root);通过挂载宿主机上运行的通信文件/var/run/docker.sock,在容器中安装Docker客户端可操作宿主机建立新容器;通过Docker程序漏洞(CVE-2019-5736)可在宿主机内执行攻击载荷(payload)代码;通过操作系统内核漏洞(CVE-2016-5195)可进入宿主机root环境等。
因此,容器运行时的风险主要源于与宿主机操作系统共享了内核和硬件资源,共享内核相对于虚拟机(VM)而言具有更大的攻击面。如果系统内核存在漏洞或者使用者对容器有意无意地不当配置,其上运行的容器就存在被攻击和隔离性被破坏的风险。一旦隔离性被打破,随之而来的就是容器逃逸。
容器镜像的风险同样不容忽视,容器镜像通过镜像仓库的自动化、层级化管理大大降低了容器使用的难度,开发者在方便使用的同时也要重视可能发生的安全问题。镜像的风险一般来自于不可靠的镜像来源,镜像构建时引入的不安全第三方组件,及包括官方镜像在内的镜像自身存在的漏洞等。通常软件项目中会使用大量开源软件,按照以往的经验,官方提供下载的软件一般是最新且安全可靠的。但2015年一份研究报告显示,Docker公共仓库(Docker Hub)中超过30%的官方镜像包含高危漏洞,而2021年全年公开的通用漏洞披露(CVE)漏洞数为20139个,其中高危漏洞数高达4064个。漏洞镜像主要集中在种类繁多的应用程序中间件的镜像中。镜像的风险必然导致容器运行的风险。
2.2 容器编排平台的风险
云原生的焦点是业务服务,业务服务核心是对服务的管理和控制,如服务暴露、负载均衡、流量感知、应用扩容、灰度发布、应用更新等。服务编排提供了分布式的计算、存储和网络资源的管理功能,实现了按需、弹性地控制服务的位置、容量、版本,监控并保证业务的可访问性。
事实上,编排系统与容器之间并非完全独立。以当前最流行的云原生管理与编排系统Kubernetes(K8s)为例,K8s集群本身的API服务管理器(API Server)、控制器(Controller Manager)、调度器(Scheduler)、基本域名解析服务器(CoreDNS)等服务端组件和K8s网络代理(Kube-proxy)、K8s节点代理服务(Kubelet)等客户端组件均以宿主机的一个或多个进程形式运行,而集群使用YAML语言以声明形式创建的K8s最小部署单元(Pod)实际是同一网络命名空间下的多个容器组成的逻辑组,因此K8s并不能降低由其管理的容器环境本身已存在的安全风险。另外,多节点组成的K8s集群使用第三方网络插件提供节点间通信的机制,也使集群网络的风险比单宿主机运行容器的网络风险更大。
除此之外,K8s内部核心组件如API Server设置了便于测试环境或者集群初启动时使用的未加密端口8080,Kubelet和分布式键值对存储系统(Etcd)可以通过改变启动参数配置使用匿名访问功能,以及用于集群访问控制的认证、授权和准入机制设置过于宽松,高权限账号滥用等配置、操作、管理性问题同样威胁着云原生环境的安全,不安全的配置暴露于网络中将给云安全带来严重的风险。
2.3 云原生网络的风险
不同于网络位置有明确划分、具有单一网络连接关系的传统IT应用,云原生应用采用网络虚拟化的部署方式,实际上是对网络边界进行了重新定义。例如,Docker容器在网络命名空间隔离下,一般通过虚拟以太网(Veth)设备对、网桥等虚拟设备采用动态地址映射方式与外界通信;K8s则以Pod为单位,Pod内部的所有容器共享一个网络堆栈,不同Pod之间以非网络地址转换(NAT)的方式互相通信,即“每个Pod分配一个IP(IP-per-Pod)”模型。从宏观上看,集群中的网络空间、包过滤防火墙(Iptables)和路由随着容器的产生、消亡不断动态变化,分布式容器集群网络的复杂度大大提升,这必然会引入新的网络风险。
每个容器虽然与宿主机之间存在隔离,但一般情况下同一宿主机上的容器位于同一局域网,网络互通。如果攻击者非法获取局域网内一个容器的权限,就有可能与其他容器非法通信,发生容器间的网络攻击(东西向攻击)。
K8s实现了容器的分布式集群部署,集群Pod间可互相通信。在没有其他网络隔离策略和Pod安全策略的情况下,可能存在网络探测、拒绝服务和中间人攻击等网络攻击(南北向攻击)。
2.4 云原生应用的风险
云原生应用采用微服务架构、前后端分离的模式设计,交互方式从传统的Web请求/响应转向为各类API请求/响应,使用方式逐渐由“人-机交互”转变为“机-机交互”,通过表述性状态转移风格的超文本传输协议(RESTful/Http)、二进制/跨语言的远程过程调用(gRPC)等方式进行通信,App服务的数量和API请求量大大增加。新模式在带来高弹性、可扩展、可移植性优势的同时,也在安全方面有了新变化。
传统的以Web为主的应用风险依然存在,如注入、跨站脚本、敏感数据泄露、使用有漏洞的第三方组件等。当传统的单体应用拆分为多个服务后,前端的单一请求在后端可能有数以千计的服务调用关系,复杂的调用链和分布式问题更容易在外部访问急剧增加时,大量占用甚至耗尽CPU资源,从而造成拒绝服务风险。
相较于作为一个整体对用户进行授权、访问单一的传统IT应用,微服务应用的所有服务间需互相认证授权,请求来源除了用户侧外,还有大量内部或其他服务API调用,其认证授权更为复杂。若某些API或微服务之间的鉴权或访问权限配置错误,就有可能造成数据非法访问、非法操作等问题。同时,应用的配置数量与服务数量成正比,微服务数量的增加导致各种服务、证书、数据访问、环境变量等配置增加,且生产环境中要求实现的动态调整对服务的配置管理、密钥管理也提出更高的要求。复杂度和管理难度的上升,增加了数据泄露风险。
3 云原生环境安全防护思路
3.1 安全机制左移
容器的生存时间(Time To Live,TTL)对安全技术有显著的影响。据统计,46%的容器生存时间小于1小时,11%的容器小于1分钟,对容器的攻击和防护有可能跟不上容器自身的变化。因此,对于攻击者而言,在其攻击链条中会倾向于寻找更持久化的资源,如代码、第三方库、镜像、仓库、编排系统、控制面、宿主机等;而对于安全防护而言,将实时杀毒、入侵检测等防护工具安装在轻量级的容器当中变得不可行,需转变思路将安全控制向开发侧转移,在DevOps中加入更多安全控制,包括开发/测试/验证安全、软件供应链安全、镜像仓库安全、监控与分析以及配置和暴露面的核查。例如,使用代码检查工具进行代码静态分析、使用镜像漏洞扫描工具对镜像仓库进行扫描、核查用户凭证、密钥配置等。开发及安全运维一体化(DevSecOps)框架如图1所示。
3.2 容器运行时行为的聚焦
容器具有体量小、平均生命周期短、变化较快的特点,因其源于镜像,在运行时来自同一镜像的容器行为具有相似性,如容器的用户、进程及数量、文件路径、CPU/内存资源使用等。通过对容器的行为画像、分析和规格匹配,若出现异常的新用户、新路径、CPU偏高等情况,可以获取高置信度的告警信息。
3.3 最小权限原则
在宿主机、容器、编排集群、DevOps以及微服务管理中,多种访问关系错综复杂,用户和服务认证授权方面错误配置和漏洞非常容易被利用。因此,要尽量明确组件间边界和划分,控制权限的细粒度,合理限制组件的权限,确保组件只执行它被授权的行为,限制容器对基础设施和同存的其他容器的干扰和影响,保证容器与其所在宿主机的隔离,避免攻击者恶意越权访问,使数据或功能遭到恶意破环。
3.4 零信任架构
云原生环境下云计算、容器集群架构复杂,访问类型多样,尤其在涉及多租户,云的运营方、使用方、应用开发方均为独立实体的情况下,客观上要求能够随时在云原生环境的任何位置进行风险的控制、分析和防范,也就是零信任(默认不信任)架构的理念需要贯穿在安全防护中。
4 云原生环境安全体系构建方案
针对云原生环境下容器基础设施、编排平台、网络、云原生应用层面存在的风险,结合云安全防护思路,在对应层面建立安全防护机制,形成全生命周期的安全防护体系,如图2所示。
4.1 容器基础设施的安全
在镜像构建时,验证依赖镜像的来源,最小化安装减小风险引入,构建完成立即进行漏洞扫描;在镜像仓库中,从公共仓库选择官方镜像最新版本,下载后进行漏洞检测并保证及时更新,私有仓库配置安全证书,并对用户访问进行权限控制;在镜像分发时,利用数字签名对镜像进行验证,防止被恶意篡改。
从容器宿主机的角度,通过最小化安装、最小权限授权、容器存储单独分区、Docker守护进程及相关文件目录审计,Docker软件及时更新等方式对容器环境进行加固。
充分利用Linux自身内核安全机制来实现容器资源的隔离和权限的管控,如利用SELinux实现进程访问文件的强制控制访问,保证进程只能访问它的任务中所需的文件。
监测运行时容器异常行为,正常的容器进程行为虽然是动态的,但其行为应该在一定基线内变化,可以认为大幅偏离此基线的行为存在风险。这种监测基线既可以通过已知威胁的规则库建立,也可以通过大量容器行为和属性集合进行分类、聚合、自学习等方式来自动构建。
4.2 编排系统的安全
利用K8s自身提供的安全机制,从认证授权、准入控制、密钥管理以及Pod自身提供的安全策略和网络策略确保编排系统的组件和配置都是符合安全要求的。
利用X.509证书开启K8s的集群访问认证,要求客户端必须通过证书验证后才能进一步授权;启动服务账号令牌认证机制,通过令牌控制集群内进程能否与API Server进行通信;使用Secret对象保存敏感信息,如密码、令牌和SSH密钥;通过基于角色的访问控制(RBAC)为Pod安全策略授权实现准入控制,以及通过网络策略实现Pod间的可靠通信等。
4.3 网络安全
针对云原生网络架构虚拟化、连接情况复杂、网络边界动态变化的特点,需要在更细粒度上实现网络隔离,减少不同容器间网络横向攻击的风险。同时,需要引入零信任安全理念。
目前比较先进的3层以上可进行网络隔离的技术是微服务管理框架服务网格(Istio)下的边车(Sidecar)模式,如图3所示。Sidecar代理如边缘/服务代理(Envoy)通过流量劫持接受控制面的调度,协调与其连接的服务实例的出入站通信,实现了更细粒度调整和控制端口、协议的功能,所有网格内的Sidecar代理实例由控制平面的服务发现和流量管理组件(Pilot)管理和配置,流量控制较为容易且无需修改应用。
4.4 应用安全
在开发侧引入安全机制,对软件依赖的第三方库进行安全性分析和漏洞扫描,及时告警,保证软件供应链安全;在开发中加强安全检查、漏洞测试和代码审计,提升开发人员的安全意识和安全技术能力,减少早期漏洞引入。
引入云原生API网关,对所有的外部访问进行流量接入、认证授权、监控审计、传输层安全(TLS)加密等细粒度的控制。
引入服务网格治理,以Istio为主的安全机制,对微服务间的互访采用开放的JWT标准认证、Istio授权、TLS双向传输加密等方法进行安全防护。
针对无服务计算(FaaS)可能存在的风险,采用加强服务平台自身的隔离和安全防护机制,开发的函数遵从安全规范,对无服务(Serverless)实例进行监控审计,定期清理非必要Serverless来减小攻击面等方法进行防护。
5 结语
随着云计算技术的发展,云原生已是大势所趋,新技术的不断发展也必然会持续引入新的风险。云原生安全不仅仅是对已知安全问题的防护,更是对云原生环境中的所有安全风险的快速发现和响应。未来的云原生安全必然会发展出更多新的手段和工具,必然也会具备云原生的特点,如微服务、弹性扩展和自动化编排等。企业的“上云”之路必须转变传统应用安全的防护思路,重视云原生安全。
(原载于《保密科学技术》杂志2022年7月刊)