Welcome to contact me. Wechat:LittleHann,My email, [email protected],Job mail:[email protected],Job Description:aHR0cHM6Ly9qb2IuYWxpYmFiYS5jb20vemhhb3Bpbi9wb3NpdGlvbl9kZXRhaWwuaHRtP3RyYWNlPXFyY29kZV9zaGFyZSZwb3NpdGlvbkNvZGU9R1A2MDAxMjk=
0x1:面向云原生环境的安全
面向云原生环境的安全的目标是防护云原生环境中基础设施、编排系统和微服务等系统的安全。
这类安全机制不一定具备云原生的特性,比如不是容器化、可编排的,而是以传统模式部署的,甚至是硬件设备,但其作用是保护日益普及的云原生环境,例如,
对于容器云(CaaS)的抗拒绝服务,可采用分布式拒绝服务缓解(DDoSMitigation)机制,但考虑到性能限制,一般此类缓解机制都是以硬件形态交付和部署的,正是这种传统安全机制保障了面向云原生系统的可用性。
低于容器负载的入侵检测和病毒查杀服务,可采用传统的主机类EDR产品
当然,云原生内部的安全机制以云原生形态居多,例如,
服务网格的安全通常使用旁挂串接(Sidecar)的安全容器
微服务API安全通常使用微API网关容器
容器镜像恶意代码、敏感文件扫描
这些安全容器都是云原生的部署模式,具有云原生的特性。
0x2:具有云原生特征的安全
具有云原生特征的安全是指具有上一小节所述的云原生特性的各类安全机制。此类安全机制具有弹性、敏捷、轻量级、可编排等特性。
云原生是一种理念上的创新,它通过容器化、资源编排和微服务重构传统的开发运营体系,加快业务上线和变更的速度。云原生系统的种种优良特性同样会给安全厂商带来很大启发,从而重构它们的安全产品、平台,改变其交付、更新模式。
还是以DDoS为例。在数据中心的安全体系中,抗拒绝服务是一个典型的安全应用,以硬件清洗设备为主。但其缺点是当DDoS的攻击流量超过了清洗设备的清洗能力时,无法快速部署额外的硬件清洗设备(传统硬件安全设备的下单、生产、运输、交付和上线往往以周计),因而无法应对突发的大规模拒绝服务攻击。而
如果采用云原生机制,安全厂商就可以通过容器镜像的方式交付容器化的虚拟清洗设备,当出现突发恶意流量时,可通过编排系统在空闲的服务器中动态横向扩展以启动足够多的清洗设备,从而可应对处理能力不够的场景。这时,DDoS清洗机制是云原生的,但其防护的业务系统有可能是传统的
。
以入侵行为防御和病毒查杀为例,在云原生环境中,支撑基础设施通常是容器技术。容器生命周期极短,大部分是以秒或分钟为单位,占用的资源也比虚拟化小得多,所以容器的最大特点就是轻和快。而正是因为容器有轻和快的特点,在实践中通常不会在容器中安装或更新应用,而是更新更为持久化的镜像,通过编排系统下载新镜像并启动相应的容器,并将旧的容器删除。这种只更新镜像而不改变容器运行时的模式称为不变的基础设施(immutable infrastructure)。从不变的基础设施就能看出,云原生的运营与传统虚拟机运营方式截然不同。
基于这种新的云原生架构,就可以采取容器进程白名单等强管控技术,通过研发/敏捷交付/快速部署的方式降维地解决了传统安全攻防产品多年未解决的漏报误报平衡难题
。
这种具有云原生特征的安全机制与当前流行的安全资源池有相似的特性,当然借助业界流行的云原生技术和平台,能提供比安全资源池性能更好、处置更灵活的安全能力。
需要说明的是,对于云原生安全的两层含义,我们讨论得更多的是前者,即在云原生环境中识别各个系统和组件的脆弱性和安全风险,进而提出和设计面向云原生环境的安全,而相应的安全机制必须应用于云原生环境。当然,随着讨论的逐渐深入,读者会发现,云原生环境中的安全防护会天然地要求一些主机侧的安全机制具有云原生特性。例如容器环境的短生命周期、业务变更极其迅速,导致访问控制、入侵检测等安全机制偏向于特权容器等形态。此外,还要求可以根据编排系统的业务调度策略进行安全策略的动态调整。要满足这两个要求,最后的安全机制必然与云原生系统融合,体现出明显的云原生特性。
因而,虽然我们将云原生安全分成了两种安全机制,但这两种机制会互相融合。在理想情况下,云原生安全会是在云原生环境下,对原有的安全机制进行重构或设计新的安全功能,使得最终的安全机制能与云原生系统无缝融合,最终体现出云原生的安全能力。
0x3:原生安全:融合的云原生安全
未来的云安全等价于纯安全,因为未来云计算将会变得无处不在,所有的安全机制都会覆盖云计算场景。我们谈云安全,其实就是谈一个通用场景下的安全问题。
既然未来云安全等价于纯安全,而云计算的下半场是云原生,那么不妨做个推论:未来的云原生安全等价于原生安全。那么,什么是原生安全呢?笔者认为原生安全有两个特点:
基于云原生且无处不在,即使用了云原生技术
适用于各类场景
原生安全会有三个发展阶段,如下图所示。
安全赋能于云原生体系,构建云原生的安全能力
。当前云原生技术发展迅速,但相应的安全防护匮乏,就连最基础的镜像安全、安全基线都不尽如人意。因而应该研究如何将现有成熟的安全能力,如隔离、访问控制、入侵检测、应用安全,应用于云原生环境,构建安全的云原生系统。
安全产品具有云原生的新特性,如轻/快/不变的基础设施、弹性服务编排、开发运营一体化等
。因而,安全厂商会开始研究如何将这些能力赋予传统安全产品,通过软件定义安全的架构,构建原生安全架构,从而提供弹性、按需、云原生的安全能力,提高“防护—检测—响应”闭环的效率。
在安全设备或平台云原生化后,就能提供(云)原生的安全能力,不仅适用于通用云原生、5G、边缘计算等场景,还可以独立部署在大型电商等需要轻量级、高弹性的传统场景,最终成为无处不在的安全
二、面向云原生环境的安全体系
根据云原生环境的构成,面向云原生环境的安全体系可包含三个层面的安全机制。
容器安全/基础设施安全
编排系统安全
云原生应用安全
全生命周期的云原生安全框架
0x1:容器安全
容器环境,或者叫容器云,其本质是云计算的一种实现方式,我们可以将其称为PaaS或者CaaS。容器技术是云原生体系的底层,因而容器安全也是云原生安全的基石。近两年,随着容器技术越来越多地被大家所青睐,容器安全也逐渐得到了广泛的关注和重视,容器环境的安全是云原生安全的重中之重。
总体而言,容器层面的安全可以分为以下几部分。
容器环境基础设施的安全性,比如主机上的安全配置是否会影响到其上运行的容器,主机上的安全漏洞和恶意进程是否会影响到容器,容器内的进程是否可以利用主机上的安全漏洞,等等。
容器的镜像安全,包括镜像中的软件是否存在安全漏洞,镜像在构建过程中是否存在安全风险,镜像在传输过程中是否被恶意篡改,等等。
容器的运行时安全,比如运行的容器间的隔离是否充分,容器间的通信是否是安全的,容器内的恶意程序是否会影响到主机或者其他容器,容器的资源使用情况是否安全,等等。
整个容器生态的安全性,比如Docker自身的安全性如何,Service Mesh/Serverless对容器安全有什么影响,容器中安全密钥的管理与传统环境有什么不同,容器化后的数据隐私保护与传统的数据隐私保护是否一致,等等。
相应地,容器云的整体安全建设思路可遵循云计算安全架构,见下图。
云计算安全架构
除了物理安全,容器云环境的安全可以粗略分为两个主要方面:
一方面是容器云内部的安全,这包括宿主机安全、虚拟化安全、容器(东西向)网络的安全、管理平台的安全以及数据安全等
一方面就是容器云内外之间的网络安全,也就是通常讲的南北向网络安全。
这样,对于容器云的安全方案,可以分别从两个方面进行设计。
对于南北向的网络安全,可以通过安全资源池引流的方式,实现相应的安全检测与防护,这也是业界多数云安全解决方案的实现方式。
对于容器云内部的安全,可以通过相应的容器安全机制实现。最后将这两部分统一接入云安全集中管理系统,进行统一的安全管理和运营。
容器云安全建设思路
0x2:编排系统安全
Kubernetes已经成为事实上的云原生编排系统,那么Kubernetes的安全就成为非常重要的编排安全部分。
0x3:云原生应用安全
编排系统支撑着诸多微服务框架和云原生应用,如无服务、服务网格等,这些新型的微服务体系也同样存在各种安全风险。例如,
攻击者通过编写一段无服务器的代码获得运行无服务程序容器的shell权限,进而对容器网络进行渗透。
三、云原生安全的关键问题
云原生安全与传统以虚拟化安全为主的云计算安全有巨大的差别。
容器不是轻量级的虚拟化,容器安全不是轻量级的虚拟化安全。
虚拟化安全关注的是资源,云原生安全关注的是应用。
安全左移是云原生安全的必经之路
0x1:如何防护短生命周期的容器
统计从一个容器创建到其销毁的时间间隔(TTL),发现容器的生命周期分布呈三种类型,如下图所示。
容器的TTL分布
虚拟机型。有一小部分容器被当成虚拟机使用,即将本来放置于一个虚拟机中的程序集合部署到单个容器中,那么这些容器的生命周期与虚拟机是相当的,平均在83天左右,最长的为333天。
原生型。有一部分容器是以Docker的命令启动和管理的,这部分容器完成独立的功能,因而生命周期在数十天。
编排型。还有大量的容器是由编排系统管理的,很多容器根据业务动态生成和销毁,这类容器的生命周期在1天以内。
经过进一步统计发现,46%的容器生命周期短于1小时,11%的容器生命周期短于1分钟。
容器安全和虚拟化安全的最大差别看似是隔离技术强度,但其实应是生命周期,甚至没有之一,因为这会影响到攻防双方的战术偏好。
对于攻击者而言,在攻击链的整个阶段,他们是不会优先考虑在容器中持久化的。原因很简单,如果试图这么做,很有可能在数小时或数天内容器就销毁了,持久化的努力也就付诸东流。因而,攻击者会投入大部分精力去攻击更为持久化的东西,如代码、第三方库、镜像等资产。可见,开发安全和供应链安全将是云原生环境中的重点安全措施。
对于防守者而言,容器的短生命周期、轻量级隔离特性同样存在很大的变数。传统在宿主机或虚拟机上安装杀毒软件的机制对于追求微服务和轻量级的容器而言还是过重了,很难想象在一个运行一两个进程的容器中安装杀毒软件套件,并实时对进程、文件进行查杀。
近年来终端侧兴起了终端检测与响应(Endpoint Detection and Response,EDR)系统,该系统通过捕获终端上的进程行为、状态等日志并对其进行分析和规则匹配,发现终端上的恶意攻击。但在容器环境中,一方面,容器逃逸等攻击手法往往利用操作系统层面隔离的漏洞,与通常终端上的恶意软件攻击手法不同,现有的规则检测不能直接适用;另一方面,容器运行的进程行为与桌面终端有很大的差别,在这种场景中更适合用行为特征对工作负载进行识别,类似于用户和实体行为分析(User and Entity Behavior Analytics,UEBA),不过容器上的日志只能体现短时间内的进程、业务模式,无法通过机器学习等方式对正常模式进行画像,这对于高度依赖客户侧做训练的很多UEBA算法是致命的。
因而,如何防护短生命周期的容器是一个非常重要的问题,解决过程中需要转变很多之前固有的防护思维。
0x2:如何降低安全运营成本
在应对短生命周期的容器环境时,防守者会调整异常检测、行为分析的机制。但这种技术路线有两个问题:
第一是成本较高,对大量容器中的进程行为进行检测、分析、规则匹配会消耗宿主机大量的处理器和内存资源,日志传输会占用较多网络带宽,行为检测则会消耗平台侧很多计算资源
第二是存在误报,虽然微服务场景下容器运行的进程行为模式可预测度较高,但比如从CPU占用率的特征来判断是否运行了挖矿软件,显然会造成很多误报,而当环境中容器数量巨大时,对应的安全运营成本就会急剧增加。
安全的本质在于对抗以及攻防投入产出比的平衡。从攻击方的视角看,由于容器的短生命周期,攻击容器的代价较高,而收益较小;但对第三方软件库、项目依赖的镜像“投毒”的持久化代价较小,而其收益远高于攻击容器。
那么从防守者的视角看,如何在降低安全运营成本的同时,提升安全防护效果呢?这两年,业界有一个词比较流行:Shift Left(安全左移)。将软件的生命周期从左到右展开,即开发、测试、集成、部署、运行阶段,安全左移的含义就是将安全防护从传统运行时运营(Ops)转向开发侧(Devs)。
早期防微杜渐的成本永远小于一溃千里后再修复的代价,而且往往发现问题越早,修复效果越好,这种经验在很多场合下都是适用的。以云原生的场景为例,白盒代码的审计难度远远小于对黑盒服务的渗透测试和安全评估,而且由于能掌握代码的跳转逻辑、参数信息,其准确率也相当高;检查镜像的文件系统脆弱性的难度远远小于运行时的恶意攻击检测,而且由于掌握精确的版本和漏洞信息,能够准确知道攻击者的尝试是否成功,效果远好于网络侧的入侵检测。
因此,安全团队要想降低云原生场景下的安全运营成本,提升运营效率,那么首先就应考虑防护思路的转换,贯彻“安全左移”的策略,从重视运行时安全转向先从开发侧解决最基本和最容易的问题。
0x3:DevSecOps
云原生的兴起离不开开发运营一体化(DevOps)的推动。开发者开发代码后,可以快速编译代码、构建镜像并将其部署到测试、生产环境中,使得整个开发和运营的流程打通,并且保证软件依赖库和运行时环境一致,避免各类环境不一致导致的配置、调试开销。在整个过程中,容器技术天然具有的隔离性、运行时环境一致性、镜像仓库等特性,直接推动了DevOps的落地。
DevOps不只改变开发团队、测试团队和IT运营团队,还有安全团队。传统上,安全团队通常聚焦在运营侧,可能是IT运营团队中的一部分,而开发安全则主要由开发团队负责,两者从组织架构和工作职责上来看是天然分离的。
但如前所述,在云原生场景下,安全左移要求安全团队越来越关注开发侧的安全,但同时又要保证以往运行时的各项安全功能可应用于云原生业务系统中,换句话说,安全能力应该覆盖开发和运营闭环的每个环节,这样的开发运营一体化安全称为DevSecOps,如下图所示。
DevSecOps闭环
0x4:如何实现安全的云原生化
1、安全架构具备编排能力
编排(Orchestration)是指将各类资源根据业务需要进行动态控制和管理。在云原生场景中,安全架构需要借助容器编排系统的能力来动态部署或销毁安全资源,并按需调度流量牵引或旁路到前述的安全资源,然后将安全策略下发到安全资源,形成全局统一、一致的安全能力。
除了资源管理之外,安全架构也可借助容器编排系统进行动态升级。例如,某个安全应用发布新版,则可以将其推送到镜像仓库中。编排系统可以将部署在所有节点中的安全容器进行版本升级,甚至可以通过灰度升级策略将一部分安全容器升级,其余安全容器保持不变,从而确认本次更新是否会对业务产生影响。
2、容器和宿主机安全:安全特权容器
以安全容器的形式防护容器的安全,看似是一种自然且优美的防护机制。
在过去虚拟化安全的实践中,安全团队发现在宿主机层面防护虚拟机内部的安全是非常困难的事情。由于虚拟化是硬件层面的隔离,因而宿主机中的安全机制(如安全代理、虚拟化的安全设备等)都看不到,也阻止不了虚拟机内部的恶意进程或行为。有一种权宜之计是在虚拟机中安装安全代理。但如果是公有云服务商这么做,租户会认为存在被监听、操控的风险;而如果是私有云运营者这么做,也会有稳定性、负载等方面的顾虑。
而在容器环境中,容器技术本质上是操作系统虚拟化,因而宿主机中的安全代理是可以观察到宿主机或容器中的所有进程、文件系统等信息的,也可以通过系统调用对容器中的进程、网络连接进行控制,因而在宿主机层面完全可以实现对宿主机、容器等资产的安全防护。
在云原生环境中,如果安全代理本身就是以容器的形式出现的,那么上述第1点中安全编排所需的安全软件部署、更新、扩容等功能都可以通过容器技术实现。当然,通常这个安全容器需要一些能力(Capability)来获得某些权限,当它需要所有的权限时,它其实就是一个特权容器。在很多安全厂商的容器安全方案中,宿主机侧通常会部署安全特权容器,以实现对其所在宿主机和容器的全方位防护,如下图所示。
特权容器防护示意图
3、业务安全:Sidecar安全容器
特权容器通常关心的是系统调用、网络流量,而在云原生场景下,业务团队和安全团队会更关心容器所承载业务的安全,如微服务的安全、无服务的安全。这些安全通常存在于网络和传输层之上的应用层,而在应用层上进行防护,通常可以使用Sidecar模式的安全容器。
Sidecar容器本质上就是一种提供反向代理的容器,如下图所示,该容器会劫持业务容器的流量,经过解析后获得应用层请求和响应,然后根据安全策略进行检测或防护。
除此之外,Sidecar安全容器与安全特权容器的区别是Sidecar安全容器尽可能贴近服务,可以与编排系统深度融合,随着微服务和无服务容器的增加而相应增加,反之亦然。可见,Sidecar安全容器的资源管理和策略管理是云原生的。
Sidecar防护示意图
四、云原生安全现状
随着越来越多的组织向微服务/DevOps转型,容器生态系统每年都会发生很大的变化,因而云原生安全现状也会出现快速演进的现象。
下图来自sysdig 2023云原生安全和使用报告。
在镜像中每天都会发现新的漏洞,但是在规模化地维护多个workloads时,修复每一个漏洞是不切实际的。成功地现代漏洞管理模式,需要安全团队根据漏洞对组织实际风险做评估,综合考虑。
常用于优先考虑漏洞修复工作的方法包括:
common vulnerability scoring system(CVSS)通用漏洞评分系统 - 制定已知问题的严重程度
可利用性 - 表示是否存在已知的利用漏洞的路径
可修复性 - 标识是否有可用的修复程序来解决漏洞
解决正在运行且存在被已知漏洞利用的软件包应该是首要任务。研究发现,客户积极主动地修复易受攻击且在运行时加载的漏洞。当结合上述漏洞的多个标准(修复可用性、易受攻击性、运行时加载的软件包)时,在分析的25000个镜像中找到的漏洞仅占2%。
研究人员计算了运行时加载包的漏洞百分比,根据包的类型来衡量哪种语言、库或文件类型带来的漏洞风险最大。在运行包中的32万多个漏洞中,java包占61%。
在已识别的1777个恶意镜像中,上图图表中显示了包含的恶意内容的类型。
容器是敏捷管理的理想伴侣,它加速了代码开发和发布,通常作为容器化的微服务。
上图的镜像寿命数据反映了代码发布时间间隔的变化,CI/CD流水线正在帮助开发团队,比以往任何时候都更快速度地交付软件。
容器的寿命本来就很短,过去几年中,近一半的容器寿命都不到5分钟。在2023年,这个数字增长到了70%以上,容器寿命少于5分钟。这是一个巨大的飞跃,强调了持续威胁检测和调查记录的必要性,因为容器可能只存在几秒钟。
为什么容器的寿命如此短呢?因为许多容器只需要在执行函数时存在足够长的时间即可,在完成任务后终止。几秒钟可能很短,但对于一些进程来说,这就足够了。
容器的短暂性仍然是这项技术的独特优势之一,因为容器镜像是可以根据需要进行更改的。然后,这也为监视、安全和合规性带来了新的挑战,因为许多工具无法报告不再存在的实体。
容器是敏捷管理的理想伴侣,它加速了代码开发和发布,通常作为容器化的微服务。CI/CD流水线正在帮助开发团队,比以往任何时候都更快速度地交付软件。
数据显示,大约有一半的容器镜像在一周或更短的时间内被替换,也可以成为迭代。对于今天的大多数企业来说,快速上市的速度很重要,这对于保持竞争力来说至关重要。代码被更频繁地部署,这就产生了新的容器镜像。
研究每个客户在其基础设施中运行的容器数量,61%的客户运行超过250个容器。在高级用户中,只有6%的客户管理超过5000个容器。
DevOps和云计算团队报告称,一旦证明了收益,采用的速度就会加快,因为更多的业务部门会考虑加入新平台。
今年的情况表明,总体上容器数量有所增加。这种转变可能表明,更多的workloads正在转向容器,远离传统的架构,或者基础设施越来越高效,能够处理越来越多的容器。
综上来说:
企业正在迅速采用容器化微服务、CI/CD和按需的云服来加快创新。然而,变化如此之快也带来了风险,因为云扩展和云原生应用程序的复杂性暴露了DevSecOps流程的成熟度不足的问题。此外,来自于配置错误和漏洞的供应链风险已经成为一个重要的关注领域。
研究表明,尽管人们对所需工具和零信任方法的益处有所认识,但云安全流程仍然落后于云计算应用的快速发展速度。从所调查的实际客户数据中可以看出,有几个安全实践领域需要改进以减少风险:
身份和访问管理:所授予权限与所需权限之间的巨大差距,表明用户需要定期测量和管理权限以减小攻击面。
漏洞管理:在生产环境中运行的大多数容器镜像存在高风险漏洞,团队必须解决镜像冗余的问题,并根据实际运行时风险优先处理漏洞。
检测和响应:特权升级和防御逃避攻击是客户威胁清单的头号问题。为了在不断变化的威胁环境中保持领先地位,应定期更新威胁检测规则以便发现恶意活动。
参考资料:
https://marketing.alauda.cn/service/extfile/page/032cee11d9c84ca2ac7a850da71234e1?cl_sr=inbound&cl_source1=%E5%85%AC%E4%BC%97%E5%8F%B7-%E7%81%B5%E9%9B%80%E4%BA%91#/previewer
五、容器基础设施的风险分析
0x1:容器基础设施面临的风险
下图较为全面地展现了Docker用户在使用容器的过程中涉及的组件或操作,主要包含Docker客户端、Docker容器所在宿主机和镜像仓库三部分。
它涉及的使用场景主要包括以下两类:
拉取基础镜像,构建业务镜像,运行容器。
从外部访问容器内服务。
结合桑图,我们从容器镜像、活动容器、容器网络、容器管理程序接口、宿主机操作系统和软件漏洞六个方面来分析容器基础设施可能存在的风险。
1、容器镜像存在的风险
所有容器都来自容器镜像。因此,我们首先研究容器镜像的风险。
与虚拟机镜像不同的是,容器镜像是一个不包含系统内核的联合文件系统(Unionfs),即为进程的正常运行提供基本、一致的文件环境。另外,容器是动态的,镜像是静态的。考虑到这一特点,我们从镜像的内容和镜像的流通、使用等几方面开展分析。
1)不安全的第三方组件
随着容器技术的成熟和流行,大部分流行的开源软件都提供了Dockerfile和容器镜像。在实际的容器化应用开发过程中,人们很少从零开始构建自己的业务镜像,而是将Docker Hub上的镜像作为基础镜像,在此基础上增加自己的代码或程序,然后打包成最终的业务镜像并上线运行。例如,为了提供Web服务,开发人员可能会在Django镜像的基础上,加上自己编写的Python代码,然后打包成Web后端镜像。
毫无疑问,这种积累和复用减少了造轮子的次数,大大提高了开发效率和软件质量,推动了现代软件工程的发展。如今,一个较为普遍的情况是,用户自己的代码依赖若干开源组件,这些开源组件本身又有着复杂的依赖树,甚至最终打包好的业务镜像中还包含完全用不到的开源组件。这导致许多开发者可能根本不知道自己的镜像中到底包含多少以及哪些组件。包含的组件越多,可能存在的漏洞就越多,大量引入第三方组件的同时也大量引入了风险。2020年,有研究报告显示,在使用最为广泛的镜像仓库Docker Hub中,约有51%的镜像至少包含一个危险(critical)级别的安全漏洞。这意味着,使用这些镜像或基于这些镜像制作目的镜像都将使最终业务面临安全风险——无论业务自身代码程序的安全性如何。
2)大肆传播的恶意镜像
除了有漏洞的可信开源镜像外,以Docker Hub为代表的公共镜像仓库中还可能存在一些恶意镜像。如果使用了这些镜像或把这些镜像作为基础镜像,其行为相当于引狼入室,风险不言自明。
3)极易泄露的敏感信息
容器的先进性之一在于它提供了“一次开发,随处部署”的可能性,大大降低了开发者和运维人员的负担。但凡事有利就有弊。为了开发、调试方便,开发者可能会将敏感信息——如数据库密码、证书和私钥等内容直接写到代码中,或者以配置文件形式存放。构建镜像时,这些敏感内容被一并打包进镜像,甚至上传到公开的镜像仓库,从而造成敏感数据泄露。
2、活动容器存在的风险
除了静态容器镜像的风险,当镜像以容器的形式运行起来后,这些活动容器又存在哪些风险呢?
1)不安全的容器应用
与传统IT环境类似,容器环境下的业务代码本身也可能存在Bug甚至安全漏洞。容器技术并不能解决这些问题。无论是SQL注入、XSS和文件上传漏洞,还是反序列化或缓冲区溢出漏洞,它们都有可能出现在容器化应用中。
容器默认情况下连接到由docker0网桥提供的子网中。如果在启动时配置了端口映射,容器就能够对外提供服务。在这种情况下,前述各种安全漏洞就有可能被外部攻击者利用,从而导致容器被入侵。
2)不受限制的资源共享
与其他虚拟化技术一样,容器并非空中楼阁。既然运行在宿主机上,容器必然要使用宿主机提供的各种资源——计算资源、存储资源等。如果容器使用了过多资源,就会对宿主机及宿主机上的其他容器造成影响,甚至形成资源耗尽型攻击。
然而,在默认情况下,Docker并不会对容器的资源使用进行限制。也就是说,默认配置启动的容器理论上能够无限使用宿主机的CPU、内存、硬盘等资源。
3)不安全的配置与挂载
“配置与挂载”指的是容器在启动时带有的配置选项和挂载选项。我们知道,作为一种虚拟化技术,容器的核心是两大隔离机制:
Linux命名空间机制:在文件系统、网络、进程、进程间通信和主机名等方面实现隔离。
cgroups机制:在CPU、内存和硬盘等资源方面实现隔离。
除此以外,Capabilities、Seccomp和AppArmor等机制通过限制容器内进程的权限和系统调用访问能力,进一步提高了容器的安全性。
为什么配置和挂载也可能导致风险呢?因为通过简单的配置和挂载,容器的隔离性将被轻易打破。例如:
通过配置--privileged选项,容器将不受Seccomp等安全机制的限制,容器内root权限将变得与宿主机上的root权限无异。
通过配置--net=host,容器将与宿主机处于同一网络命名空间(网络隔离打破)。
通过配置--pid=host,容器将与宿主机处于同一进程命名空间(进程隔离打破)。
通过执行挂载--volume /:/host,宿主机根目录将被挂载到容器内部(文件系统隔离被打破)。
因此,用户在对容器进行配置时,一定要慎之又慎。
3、容器网络存在的风险
默认情况下每个容器处于自己独立的网络命名空间中,与宿主机之间存在隔离。然而,每个容器都处于由docker0网桥构建的同一局域网内,彼此之间互相连通。理论上,容器之间可能发生网络攻击,尤其是中间人攻击等局域网内常见的攻击方式。
事实也确实如此。容器内的root用户虽然被Docker禁用了许多权限(Capabilities机制),但它目前依然具有CAP_NET_RAW权限,具备构造并发送ICMP、ARP等报文的能力。因此,ARP欺骗、DNS劫持等中间人攻击是可能发生在容器网络的。
4、容器管理程序接口存在的风险
Socket是Docker守护进程接收请求及返回响应的应用接口。Docker守护进程主要监听两种形式的Socket:
UNIX socket
TCP socket
安装完成并启动后,Docker守护进程默认只监听UNIX socket。
1)UNIX socket
为什么UNIX socket也可能存在风险呢?它的问题主要与Docker守护进程的高权限有关:Docker守护进程默认以宿主机root权限运行。只要能够与该UNIX socket进行交互,就可以借助Docker守护进程以root权限在宿主机上执行任意命令。相关的风险利用场景主要有两个:
许多用户为了方便,不想每次输入密码时使用sudo或su,就将普通用户也加入了docker用户组,这使得普通用户有权限直接访问UNIX socket。那么一旦攻击者获得了这个普通用户的权限,他就能够借助Docker UNIX socket在宿主机上提升为root权限。
为了实现在容器内管理容器,用户可能会将Docker UNIX socket挂载到容器内部。如果该容器被入侵,攻击者就能借助这个socket实现容器逃逸,获得宿主机的root权限。
2)TCP socket
在版本较新的Docker中,Docker守护进程默认不会监听TCP socket。用户可以通过配置文件来设置Docker守护进程开启对TCP socket的监听,默认监听端口一般是2375。
然而,默认情况下对Docker守护进程TCP socket的访问是无加密且无认证的。因此,任何网络可达的访问者都可以通过该TCP socket来对Docker守护进程下发命令。例如,以下命令能够列出IP为192.168.1.101的主机上的所有活动容器:
docker -H tcp://192.168.1.101:2375 ps
显而易见,攻击者也能够通过这样的TCP socket对目标主机上的Docker守护进程下发命令,从而实现对目标主机的控制。控制方式与通过UNIX socket的控制类似,只是需要通过-H tcp://参数来设置目标地址和端口。
5、宿主机操作系统存在的风险
与虚拟机不同,作为一种轻量级虚拟化技术,容器通常与宿主机共享内核。这意味着,如果宿主机内核本身存在安全漏洞,理论上,这些漏洞是能够在容器内进行利用的。通过利用这些漏洞,攻击者可能实现权限提升,甚至从容器中逃逸,获得宿主机的控制权。
例如,在存在CVE-2016-5195(“脏牛”)漏洞的容器环境中,攻击者可以借助该漏洞向进程vDSO区域写入恶意代码,从而实现容器逃逸。
令人欣慰的是,Capabilities及Seccomp机制在一定程度上缓解了共享内核带来的问题。另外,以Kata Containers和gVisor为代表的安全容器则能够较为彻底地解决共享内核带来的安全问题。前者为每一个容器创建一个独立的轻量虚拟机,后者在用户空间模拟内核以处理系统调用,虽然实现思路不同,但都致力于让容器摆脱对宿主机内核的直接依赖。但是,安全容器不等于绝对安全。依然存在容器逃逸的安全风险。
6、无法根治的软件漏洞
任何软件都存在漏洞,Docker自然不会例外。在已经曝光的漏洞中,CVE-2019-14271、CVE-2019-5736等漏洞能够导致容器逃逸,属于高危漏洞,其中CVE-2019-14271的CVSS 3.x风险评分更是高达9.8分(满分为10)
0x2:针对容器化开发测试过程的安全风险
过去,开发者关心的安全要素主要是代码安全性,如写的代码是否足够健壮、代码是否正确处理了异常且不会引起拒绝服务、代码是否能够有效阻止各种注入漏洞、是否有溢出等。诚然,代码安全性非常重要。但是,随着以容器为代表的云原生技术的兴起,开发环境与生产环境的差异被“容器化”逐渐消解,容器技术顺理成章地参与到开发者的编码、调试、打包过程中。然而,这同样意味着,容器自身的安全问题可能会给上述开发阶段的各个过程带来风险。
SDL(Security Development Lifecycle,安全开发生命周期)实践告诉我们,做安全越早越好,从开发阶段就开始对安全性进行合理的评估和控制能够有效提升整个工程质量。反之亦然,如果在开发阶段就引入安全问题,那么它往往是最隐蔽的,在运行时再检测这些问题将会颇为棘手。
0x3:针对容器软件供应链的安全风险
随着容器技术的普及,容器镜像也成为软件供应链中非常重要的一部分。人们像使用pip等工具从仓库获取各种编程语言软件库一样,可从Docker Hub或第三方仓库拉取镜像,在其基础上进行开发,从而实现所需功能,最后打包发布。
然而,业务依赖的基础镜像可能存在问题——无论是开发者无心导致的安全漏洞还是攻击者故意埋下的恶意代码,这种“内生风险”的潜在危害比黑客从外部发起攻击严重得多,且更不易被发现。
0x4:针对运行时容器的安全风险
在之前的小节,我们已经曝光了容器相关的开发侧和软件供应链可能出现的攻击形式。按照CI/CD的思路,从开发到集成,接下来就是生产运行了。运行时环境是攻防交锋最为精彩的擂台。
运行时容器可能发生的攻击形式数不胜数,然而归根结底,所有攻击影响的还是业务系统的机密性、完整性和可用性(CIA三要素)。从这个角度出发,我们可以对攻击做以下分类:
主要影响机密性、完整性的:通常是获取目标系统控制权、窃取或修改数据等。
主要影响可用性的:通常是对目标系统信息资源的耗尽型攻击。
基于上述分类,我们将介绍两种非常典型的攻击方式:容器及安全容器逃逸、从容器发起的资源耗尽型攻击。
1、容器逃逸
与其他虚拟化技术类似,逃逸是最为严重的安全风险,直接危害了底层宿主机和整个云计算系统的安全。
“容器逃逸”是指以下一种过程和结果:首先,攻击者通过劫持容器化业务逻辑或直接控制(CaaS等合法获得容器控制权的场景)等方式,已经获得了容器内某种权限下的命令执行能力;攻击者利用这种命令执行能力,借助一些手段进而获得该容器所在的直接宿主机上某种权限下的命令执行能力。
注意以下几点:
基于计算机科学领域层式思想及分类讨论的原则,我们定义“直接宿主机”概念,避免在容器逃逸问题内引入虚拟机逃逸问题。读者可能会遇到“物理机运行虚拟机,虚拟机再运行容器”的场景,该场景下的直接宿主机指容器外层的虚拟机。
基于上述定义,从渗透测试的角度来看,这里理解的容器逃逸或许更趋向于归入后渗透阶段。
同样基于分类讨论的原则,我们仅仅讨论某种技术的可行性,不刻意涉及隐藏与反隐藏、检测与反检测等问题。
将最终结果确定为获得直接宿主机上的命令执行能力,而不包括宿主机文件或内存读写能力,或者说,我们认为这些是通往最终命令执行能力的手段。一些特殊的漏洞利用方式,如软件供应链阶段的能够触发漏洞的恶意镜像、在容器内构造恶意符号链接、在容器内劫持动态链接库等,其本质上还是攻击者获得了容器内某种权限下的命令执行能力,即使这种能力可能是间接的。
将这些注意点延伸开来,能够获得很有意思的见解。例如,结合第4点我们可以想到,在权限持久化攻防博弈的进程中,人们逐渐积累了众多Linux场景下建立后门的方法。其中一大经典模式是向特定文件中写入绑定shell或反弹shell语句,五花八门,不胜枚举。
那么如果容器挂载了宿主机的某些文件或目录,将挂载列表与前述用于建立后门而写入shell的文件、目录列表取交集,就可以得到容器逃逸的可能途径呢,见下图。进一步说,用于防御和检测后门的思路和技术,经过改进和移植也能覆盖掉某种类型的容器逃逸问题。
六、云原生编排系统的风险分析
undone
七、云原生应用的风险分析
由于云原生应用具备高度弹性化、可扩展、可移植等特点,现今大多数企业已纷纷将其应用从传统的单体架构转向微服务架构,云计算模式也相应地从IaaS转向CaaS和FaaS(Function as aService,函数即服务)。
应用架构和云计算模式的变革会导致进一步的风险,这些风险较之传统应用风险存在延续的地方 ,同时也衍生出的新的风险。
0x1:云原生应用风险概述
观点一:云原生应用继承了传统应用的风险和API的风险
。云原生应用源于传统应用,因而云原生应用也就继承了传统应用的风险。此外,云原生应用架构的变化导致应用API交互增多,可以说云原生应用中大部分交互模式已从Web请求/响应转向各类API请求/响应,如RESTful/HTTP、gRPC等,因此API风险也进一步提升。
观点二:应用架构变革将会带来新的风险
。由于应用架构变革,云原生应用遵循面向微服务化的设计方式,导致功能组件化、服务数量激增、配置复杂等问题,从而为云原生应用和业务带来新的风险。
观点三:计算模式变革将会带来新的风险
。随着云计算的不断发展,企业在应用微服务化后,会进一步聚焦于业务自身,并将功能函数化,因而出现了无服务器计算(Serverless Computing)这类新的云计算模式,并引入了Serverless应用和Serverless平台的新风险。
综上,云原生应用带来的风险是不容小觑的,接下来我们将针对以上观点进行详细说明。
0x2:传统应用的风险分析
由于云原生应用也是应用,因而云原生应用风险可以参考传统应用风险。传统应用风险以Web应用风险为主,主要包含注入、敏感数据泄露、跨站脚本、使用含有已知漏洞的组件、不足的日志记录和监控等风险。
此外,在云原生环境中,应用的API交互模式逐渐由“人机交互”转变为“机机交互”。虽然API大量出现是云原生环境的一大特点,但本质上来说,API风险并无新的变化,因而其风险可以参考现有的API风险,主要包含安全性错误配置和注入、资产管理不当、资源缺失和速率限制等风险。
有关传统应用风险和API风险的更多细节可以分别参考OWASP组织在2017年和2019年发布的《OWASP应用十大风险报告》和《OWASP API十大风险报告》。
0x3:云原生应用的新风险分析
云原生应用面临的新风险主要“新”在哪里?在笔者看来,“新”主要体现在新应用架构。我们知道,新应用架构遵循微服务化的设计模式,通过应用的微服务化,我们能够构建容错性好、易于管理的松耦合系统。与此同时,新应用架构的出现也会引入新的风险。为了较为完整地对风险进行分析,在本节我们将以信息系统安全等级三要素,即机密性(Confidentiality)、完整性(Integrity)和可用性(Availability)作为导向,为各位读者介绍应用架构变化带来的新风险。
机密性受损的风险
。典型的如信息泄露风险,攻击者可通过利用资产脆弱性和嗅探、暴力破解等攻击方式窃取用户隐私数据,造成信息泄露。
完整性受损的风险
。典型的如未授权访问风险,攻击者可通过利用资产脆弱性和中间人攻击等行为绕过系统的认证授权机制,执行越权操作,进行未授权的访问。
可用性受损的风险
。典型的如系统受拒绝服务攻击的风险,一方面,攻击者可通过畸形报文、SYN泛洪等攻击方式为目标系统提供非正常服务;另一方面,系统供不应求的场景也会导致系统遭受拒绝服务攻击风险。
本节接下来的内容将以信息泄露、未授权访问、拒绝服务为例,分别介绍上述三类风险。
1、数据泄露的风险
在云原生环境中,虽然造成应用数据泄露风险的原因有很多,但都离不开以下几个因素。
应用漏洞:通过资产漏洞对应用数据进行窃取。
密钥不规范管理:通过不规范的密钥管理对应用数据进行窃取。
应用间通信未经加密:通过应用间通信未经加密的缺陷对传输中数据进行窃取,进而升级到对应用数据的窃取。
1)应用漏洞带来的风险
我们知道,应用中存储的数据多是基于API进行访问的,若应用中某API含有未授权访问漏洞,如Redis未授权访问漏洞,攻击者便可利用此漏洞绕过Redis认证机制访问内部数据,导致敏感信息泄露。
在传统单体应用架构下,由于API访问范围为用户到应用,攻击者只能看到外部进入应用的流量,无法看到应用内部的流量,所以恶意使用API漏洞进行数据窃取造成的损失通常是有限的。
反观微服务应用架构,当单体应用被拆分为若干个服务后,这些服务会根据业务情况进行相互访问,API访问范围变为服务到服务(Service to Service)。若某服务存在API漏洞,导致攻击者有利可图,那么攻击者将会看到应用内部的流量,这无疑为攻击者提供了更多的攻击渠道,因而就数据泄露的风险程度而言,相比传统单体应用架构,微服务架构带来的风险更大。此外,随着服务数量达到一定规模,API数量将不断递增,从而扩大了攻击面,增大了数据泄露的风险。
2)密钥不规范管理带来的风险
在应用的开发过程中,开发者常疏于密钥管理,导致数据泄露的风险。例如开发者将密钥信息、数据库连接密码等敏感信息硬编码在应用程序中,从而增大了应用程序日志泄露、应用程序访问密钥泄露等风险。
在传统单体应用架构中,开发者常将配置连同应用一起打包,当需要修改配置时,只需登录至服务端进行相应修改,再重启应用便可实现。从密钥管理风险的角度上讲,这种单个集中式配置文件的存储方式的风险是相对可控的。
在微服务应用架构中,应用的配置数量与服务数量是成正比的,服务越多,配置就越多。例如,微服务应用中会存在各种服务、数据库访问、环境变量的配置,且各个配置支持动态调整。同时,微服务应用架构对服务的配置管理也提出了更高的要求,如代码与配置可分离、配置支持分布式、配置实时可更新、配置可统一治理等。因此,微服务下的配置管理更加复杂,对运维人员的要求更高,密钥管理的难度也在不断提升,最终会造成更大的数据泄露风险。
3)应用通信未经加密带来的风险
如我们所知,如果应用采用HTTP进行数据传输,那么HTTP页面的所有信息都将以纯文本形式传输,默认是不提供任何加密措施的,因而在数据传输过程中易被攻击者监听、截获和篡改。典型的攻击流程为:攻击者首先通过Fiddler、Wireshark等抓包工具进行流量监听,之后截获传输的敏感信息,如数据库密码、登录密码等,最后根据自身意图对敏感数据进行篡改并发送至服务端,进而导致数据泄露的风险。
在传统单体应用架构中,由于网络拓扑相对简单,且应用通信多基于HTTP/HTTPS,因而造成的数据泄露风险多是因为采用了HTTP。在微服务应用架构中,网络拓扑相对复杂,具有分布式的特点,应用间的通信不仅采用HTTP/HTTPS,还采用gRPC等协议,而gRPC协议默认不加密,将会导致攻击面增多,带来更多的数据泄露风险。
2、未授权访问的风险
在云原生环境中,应用未授权访问的风险多是由应用自身漏洞或访问权限错误配置导致的。
1)应用漏洞带来的风险
应用漏洞是造成未授权访问的一大因素。如我们所知,未授权访问漏洞非常多,Redis、MongoDB、Jenkins、Docker、ZooKeeper、Hadoop等常见的应用都曾曝光过相关漏洞。例如
Docker曝出的Docker Remote API未授权访问漏洞,攻击者可通过Docker Client或HTTP请求直接访问Docker Remote API,进而对容器进行新建、删除、暂停等危险操作,甚至是获取宿主机shell权限。
再如MongoDB未授权访问漏洞,造成该漏洞的根本原因在于MongoDB在启动时将认证信息默认设置为空口令,导致登录用户无须密码即可通过默认端口对数据库进行任意操作并且可以远程访问数据库。
从漏洞成因来看,认证及授权机制薄弱是其主要原因。在单体应用架构下,应用作为一个整体对用户进行认证授权,且应用的访问来源相对单一,基本为浏览器,因而风险是相对可控的。在微服务应用架构下,其包含的所有服务均须对各自的访问进行授权,从而明确当前用户的访问控制权限。此外,服务的访问来源除了用户外还包含内部的其他服务,因而在微服务架构下,应用的认证授权机制更为复杂,为云原生应用带来了更多的攻击面。
2)访问权限错误配置带来的风险
如果运维人员对用户的访问权限进行了错误配置,就会增大被攻击者利用的风险。例如,运维人员对Web应用访问权限进行相应配置,针对普通用户,运维人员应只赋予其只读操作,若运维人员进行了错误的配置,如为普通用户配置了写操作,那么攻击者便会利用此缺陷绕过认证访问机制,对应用发起未授权访问攻击。
在传统应用架构中,由于设计相对单一,应用的访问权限也相对单一,几乎只涉及用户对应用的访问权限这一层面,因此对应的访问权限配置也相对简单。诚然,也因访问权限配置简单,用户身份凭据等所有敏感信息常存储在应用的服务端,一旦攻击者利用配置的缺陷对应用发起未授权访问入侵,就有可能拿到所有保存在后端的数据,从而造成巨大风险。
在微服务应用架构下,由于访问权限还须涉及服务对服务这一层面,因而权限映射关系变得更加复杂,相应的权限配置难度也在同步增加。例如一个复杂应用被拆分为100个服务,运维人员需要精密地对每个服务赋予其应有的权限,如果因疏忽为某个服务配置了错误的权限,攻击者就有可能利用此缺陷对服务展开攻击。若该服务中包含漏洞,就可能会导致单一漏洞扩展至整个应用。所以如何对云原生应用的访问权限进行高效率管理成为一个较难的问题,这也是导致其风险的关键因素。
3、拒绝服务的风险
拒绝服务是应用程序面临的常见风险。造成拒绝服务的主要原因包含两方面。
一方面是应用自身有漏洞,如ReDoS(Regular expression Denial of Service)漏洞、Nginx拒绝服务漏洞等
一方面是访问需求与资源能力不匹配,如某电商平台的购买API处理请求能力有限,无法面对突如其来的大量购买请求,导致平台资源(CPU、内存、网络)耗尽甚至崩溃。上述这种场景往往不带有恶意企图,带有恶意企图的则以ACK、SYNC泛洪攻击及CC(ChallengeCollapsar,挑战黑洞)等攻击为主,其最终目的也是耗尽应用资源。
1)应用漏洞带来的风险
应用漏洞可以导致应用被拒绝服务攻击,那么具体是如何形成的呢?以ReDoS漏洞为例。ReDoS为正则表达式拒绝服务,攻击者对该漏洞的利用通常是这样的场景:应用程序为用户提供了正则表达式的输入类型但又没有对具体的输入进行有效验证,那么攻击者便可通过构造解析效率极低的正则表达式作为输入,在短时间内引发100%的CPU占用率,最终导致资源耗尽甚至应用程序崩溃。
2)访问需求与资源能力不匹配带来的风险
此处我们以CC攻击举例,其攻击原理通常是攻击者通过控制僵尸网络、肉鸡或代理服务器不断地向目标主机发送大量合法请求,从而使正常用户的请求处理变得异常缓慢。
在传统Web场景中,攻击者利用代理服务器向受害者发起大量HTTP GET请求,该请求主要通过动态页面向数据库发送访问操作,通过大量的连接,数据库负载极高,并超过其正常处理能力,从而无法响应正常请求,最终导致服务器宕机。
在微服务应用架构下,由于API数量会随着服务数量的递增而递增,因而可能会导致单一请求生成数以万计的复杂中间层和后端服务调用,进而更容易引起被拒绝服务攻击的风险。例如若微服务应用的API设计未考虑太多因单个API调用引起的耗时问题,那么当外部访问量突增时,将会导致访问需求与资源能力不匹配的问题,使服务端无法对请求做出及时的响应,造成页面卡死,进而引起系统崩溃。
0x4:Serverless特征带来的风险
请参阅这篇
文章
。
八、云原生防护思路转变
0x1:变化:容器生命周期
在之前的章节中,我们提到了46%的容器生命周期小于1小时,11%的容器生命周期小于1分钟,并且分析了这种短生命周期对云原生环境中的对抗带来的影响。
总体而言,容器环境中的短生命周期是云原生业务和编排机制造成的,这种特性给攻防双方都带来了变化。
从攻方的角度,以及从攻击性价比的角度,他们在早期会越来越多地攻击持久化的资源,特别是容器镜像和镜像仓库,这样攻击成本最低,而收益最高。一个被污染的镜像可以散布到更多的计算节点,而且可以持久化直到新版镜像发布上线。
防守者则需要更改传统的异常检测、行为分析机制,以适应短生命周期的容器场景。
0x2:安全左移
云原生时代,攻击者会更关注软件开发的早期阶段,主要是一些更为持久的资产,如代码、第三方库、镜像、仓库、编排系统、控制面、宿主机等。
那么对于安全团队而言,早期投入和可用的安全技术都不会很多,做最简单的事情意义最大,此时可以考虑将安全控制向开发侧转移,也就是从运营安全转向开发安全。因为在DevOps的闭环图中,开发在左侧,运营在右侧,所以又称为安全左移(Shift Left)。
安全左移需要考虑开发安全、软件供应链安全、镜像仓库、配置核查这四个部分。
首先是开发安全,安全团队需要关注代码漏洞,比如使用代码检查工具进行静态代码分析或动态运行时分析,找到因缺少安全意识造成的漏洞;此外,应重点检查代码中是否包含用户凭证、存在密码硬编码等。
其次是软件供应链安全,也就是项目使用到的第三方软件库的安全。现在大型软件项目中或多或少都用到了开源软件,所以开源软件的安全问题需要重视,可以使用代码检查工具或代码漏洞库进行持续的安全评估。
再次是镜像仓库,当前的镜像仓库中很多容器镜像存在安全漏洞,因此应使用镜像漏洞扫描工具持续对自有仓库中的镜像进行持续评估,对有安全风险的镜像进行及时更新。
最后是配置核查,比如暴露面核查、服务器配置加固等,这部分可以最大程度提升攻击者发现脆弱资产、利用漏洞的难度。
1、开发安全
软件工程是系统性工程,其中软件代码的安全漏洞是影响软件最终运行安全性的重要因素。
然而现实并没有想象中乐观,2020全年公开CVE漏洞数为14443,其中危急漏洞占比14.07%,高危漏洞占比42.59%,两者占比达到56.66%,攻击者利用此类漏洞可以远程执行任意命令或者代码,可见代码安全的整体形势确实不容乐观。自有代码产生脆弱性的主要原因是代码开发者缺乏安全经验和安全意识,在编写代码时没有进行必要的安全检查。
为了应对代码产生的漏洞,应该对代码进行安全审计。审计实施人员对系统重要业务场景进行风险分析并审计源代码,通常可使用静态应用安全测试(Static Application SecurityTesting,SAST)的方式进行审计。
2、软件供应链安全
软件供应链存在风险,第三方库的安全性不容乐观,特别是开源软件,通常一个项目会使用大量的开源软件。据Gartner统计,2016年至少95%的IT机构会在关键IT产品中使用开源软件(这个数字在2010年为75%),这些软件可能并不被机构所感知;如今新应用程序70%~90%的代码来自外部或第三方组件,平均每个应用程序有105个开源组件。其中最让人不安的是企业对其是否使用了开源软件、使用了什么开源软件并不了解。
为了应对此类风险,可使用软件成分分析(Software Composition Analysis,SCA)技术以发现项目中用到的第三方软件库(特别是开源软件),分析相关代码版本库,将其与漏洞库比较,如有匹配则告知存在漏洞。
3、容器镜像安全
容器镜像是早期云原生安全的重要阵地,攻防双方都会聚焦在此。
针对容器镜像,可采用分析工具与人工审计相结合的方式,根据提供的应用开发过程文档,审阅系统实现的技术方案,对架构的安全性进行审计和评估,分析系统防护薄弱点及可能存在的安全风险。
1)容器镜像构建安全
镜像构建的方式通常有两种:基于容器直接构建或基于Dockerfile构建。建议所有的镜像文件由Dockerfile创建,因为基于Dockerfile构建的镜像是完全透明的,所有的操作指令都是可控和可追溯的。
镜像构建存在的风险项通常包括:
基础镜像并不是由可信的组织和人员发布的,镜像本身存在后门或者其他风险项
在Dockerfile中存储敏感信息,如配置服务时使用明文固定密码或凭证等
安装不必要的软件扩大了攻击面等
针对以上问题,可以从下面几方面来加固镜像构建安全。
验证镜像来源。为了保证镜像内容可信,建议开启Docker的内容信任机制。内容信任机制为向远程镜像仓库发送和接收的数据提供了数字签名功能,这些签名允许客户端验证镜像标签的完整性和发布者。默认情况下内容信任机制是被禁用的,可以通过执行下面指令完成或者在Docker的配置文件中配置。export DOCKER_CONTENT_TRUST=1
镜像轻量化。只安装必要的软件包,这不仅在提高容器性能方面有很大帮助,更重要的是减少了攻击面。
正确使用镜像指令。在构建镜像时要选择恰当的指令。比如,若需要引入外部文件,在Dockerfile中能用COPY指令就不要使用ADD指令,因为COPY指令只是将文件从本地主机复制到容器文件系统,ADD指令却可以从远程URL下载文件并执行诸如解压缩等操作,这可能会带来从URL添加恶意文件的风险。
敏感信息处理。尽管Docker为用户分配了只读权限,但有时用户仍需要小心容器中存储的数据,如Dockerfile中不能存储密码、令牌、密钥和用户机密信息等,即使在创建好容器后再删除这些数据也会造成风险,因为在镜像的历史记录中仍能检索到这些数据。推荐使用Kubernetes和Docker Swarm的加密管理功能,它们可以有效地对信息进行加密,以加密格式存储,并且在查找时只能由授权的用户解密。
2)容器镜像仓库安全
公共仓库安全
Docker Hub是目前最大的容器镜像仓库。有研究报告中提到Docker Hub中超过30%的镜像包含高危漏洞,因此在享受Docker Hub带来的便利时,也应确保下载镜像的安全性。
在选择镜像时,应使用官方发布的最新版本的镜像,并保持定时更新。
下载的镜像要经过漏洞扫描评估。
对于提供服务的镜像,不仅要从操作系统层面进行扫描,还要从应用层面进行扫描。
对于提供了公开Dockerfile的镜像优先选择自己构建,可避免镜像后门的植入,保证镜像构建过程可控。
私有仓库安全
Docker Registry。Docker Registry是Docker官方提供的构建私有镜像仓库的开源工具,开发者可快速构建自己的私有仓库。Docker Registry的安全性可以从两方面考虑:一方面是Docker Registry自身的安全性,如在使用时要配置相应的安全证书;另一方面是Docker客户端与Docker Registry交互过程的安全性,即实现用户访问权限控制。对于暴露在互联网上的私有仓库,一般只对特定组织开放存取镜像权限,那么仅验证Registry自身的证书是不够的,还需要配置密码或双向SSL机制来验证与仓库进行交互的Docker客户端身份的有效性。
VMware Harbor。将Harbor部署在生产环境中需要注意:需要启用HTTPS,不能使用harbor.cfg中默认的密码;早期版本的Harbor在用户身份登录时没有做防暴力破解机制,存在密码被破解的风险,生产环境中需要通过修改源码添加防暴力破解机制;严格控制挂载卷权限,默认情况下是读写(rw)模式,可选的模式有读写(rw)和只读(ro)。
3)容器镜像安全检测
容器都是由本地存储的镜像快速启动运行的,那么镜像的安全性直接关乎到容器安全。除了前述提及容器仓库中镜像安全性的问题外,本地构建的镜像也会引入第三方库,造成安全风险。所以,对下载的镜像和本地构建的镜像进行安全检测就显得尤其重要。这里的漏洞检测主要还是针对已知的CVE漏洞进行扫描分析。
目前比较流行的镜像扫描引擎有Docker Security Scanning(未开源)、Clair(开源)和Anchore(开源)等。
镜像检测的核心目前仍然是已知系统CVE检测。扫描器获取到镜像后,将它分离成相应的层和软件包,然后将这些包与多个CVE数据库包的名称和版本进行对比,从而判定是否存在漏洞。通常开源的镜像漏洞扫描工具会获取各发行版官方途径安装的软件,如Debian/Ubuntu通过apt/apt-get/aptitude等命令安装软件包,而Red Hat/CentOS则是yum/rpm安装的软件包,而至于软件开发者自己部署的非官方软件,这些扫描工具一般是不覆盖的,因而读者需要自己编写相关的扫描插件,或者购买商业版的镜像漏洞扫描器。
还有一些通过扫描镜像中的环境变量、操作命令及端口开放信息来识别恶意镜像的方案,但对于这些方案使用者仍然需要自己基于结果来判断,没有统一的标准。
4)容器镜像传输安全
容器镜像在下载和上传时须保证完整性和秘密性,以下建议有助于抵御如中间人攻击等威胁。
数字签名。上传者主动给要上传的镜像签名,下载者获取镜像时先验证签名再使用,防止其被恶意篡改。
用户访问控制。敏感系统和部署工具(注册中心、编排工具等)应该具备有效限制和监控用户访问权限的机制。
尽可能使用支持HTTPS的镜像仓库。为避免引入可疑镜像,用户谨慎使用--insecure-registry选项,以免连接来源不可靠的HTTP镜像仓库。
0x3:系统profile基线异常发现
攻防永远是成本和收益之间的平衡,如果防守方能做好对长生命周期资产的持续风险和脆弱性的评估和缓解,那么攻击者的成本显然会升高。他们就会尝试攻击业务容器,即便其生命周期短,但只要使用自动化的攻击工具,还是可以实现短时间的持久化的,然后利用这一段时间窗口进行横向移动,最后找到可以持久化的资源也是可能的。
因而防守者还是需要回到运营侧安全,但在容器环境中,无论是杀毒软件(AV),还是EDR或UEBA,都或多或少存在一些固有的缺陷,或不能用,或要做改造。例如,
在做检测响应方面,安全机制应该多关注造成容器逃逸的攻击场景,特别是利用运行时环境、操作系统漏洞的攻击
在行为分析方面,应该充分利用镜像的持久化特性,一般而言,从某个镜像启动的各容器的进程行为模式是相似的,那就完全可以将容器按照镜像进行聚合,针对聚合的容器集合再进行画像,那么这样的画像结果是一致、低偏差的。
下图比较了某宿主机上容器中进程的相似度,可以发现大量容器中的进程存在相似性,这就能对容器群的进程进行画像,偏离基线的进程都可以认为是异常行为。
下图展示了一些异常行为,如某些进程所在的文件路径与正常的不同,就很可能是攻击者尝试逃避进程名白名单机制,而CPU偏高可能存在如挖矿等资源耗尽的攻击。
需要注意的是,这些异常检测都是基于机器学习得到的,也就是统计意义上的异常,并不能“实锤”恶意行为。如果要获得高置信度的告警,则需要通过专家经验规则来匹配恶意行为。
0x4:关注应用业务层面风险
在云原生环境中,开发者关注的是如何编写业务功能,而攻击者关注最多的也是是否能滥用业务功能,最典型的就是“薅羊毛”等黑产。
业务安全是离客户最近且价值最大的安全功能,然而云原生场景非常复杂,很难有统一的业务安全模型;此外,在微服务和服务网格的场景下,服务之间大部分通过API调用实现,这与当前Web应用存在大量人机交互完全不同,因而API安全在云原生场景下也存在很大的差异。
从技术上看,要实现API和业务安全,第一步是获得API调用的可观测能力(visibility),当前有很多开源项目具有这样的能力,但其在开发、构建过程中的侵入性各有不同,如下表所示。一般而言,侵入性越强,其最后获得的API请求信息越多,但在既有的开发流程和项目中部署就越难。
其中Jaeger通过在代码中插桩的方式,能够获得所有调用顺序和参数,因而理论上就能建立非常精准的API调用参数和序列的基线,而Sidecar反向代理的方式无法获得调用序列,只能通过分析启发式地获得近似基线,其上限可以逼近Jaeger所得到的基线。
获得API调用的参数范围、调用序列后,就可以通过学习获得正常的基线,如果攻击者调用的参数、序列出现异常,安全团队就可能获知并找到相关的恶意行为。