深圳幻海软件技术有限公司 欢迎您!

基于业务场景的容器逃逸技术

2023-03-20

导读​近年来,容器凭借能在任意环境中运行、开销低、秒级启动、镜像占用小等优势,越来越受世界各种行业追捧。例如Google从Gmail到YouTube和Google搜索,几乎所有产品都在容器中运行,每个星期都要启动超过20亿个容器;京东构建了全球最大的容器集群,其内部99%都做了容器化,当前已有20万

导读

​近年来,容器凭借能在任意环境中运行、开销低、秒级启动、镜像占用小等优势,越来越受世界各种行业追捧。例如Google从Gmail到YouTube和Google搜索,几乎所有产品都在容器中运行,每个星期都要启动超过20亿个容器;京东构建了全球最大的容器集群,其内部99%都做了容器化,当前已有20万的容器集群规模,保证了京东618和双11大促销。

但容器早期发展主要考虑易用性和功能实现,对安全考虑不是很充分,存在方方面面的安全隐患。随着容器化的重要性与日俱增,容器安全的重要性也在不断提高。作为一项依然处于发展阶段的新技术,容器的安全性在不断地提高,也在不断地受到挑战。在其面临的所有安全问题当中,逃逸问题稳居首位——它直接影响到了承载容器的底层基础设施的机密性、完整性和可用性,危害了底层宿主机和整个云计算系统的安全。本文针对容器逃逸技术做全面的讲解。

1、容器安全风险

在容器时代,安全面临新旧威胁的双重挑战。一方面,传统的攻击手段依然有效,如注入漏洞、暴力破解、权限提升等。另一方面,新的攻击方式层出不穷,包括容器逃逸、投毒镜像、集群管理漏洞等,让人防不胜防。

1.1 容器作为轻量的虚拟化技术面临的主要安全风险

图1 虚拟机 vs 容器


从图中可以看出:

  • 容器没有hypervisor,安全性强依赖于Host OS内核,受内核漏洞影响;

  • 容器技术在OS层面实现了对计算机系统的虚拟化,在操作系统中,通过namespace技术对CPU、内存和文件系统等资源进行隔离、划分和控制,实现进程之间透明的资源使用,其安全性与内核隔离技术的成熟度强相关;

  • 要从虚拟机攻破到宿主机或其他虚拟机,需要先攻破Hypervisor层,这是极其困难的。而docker容器与宿主机共享内核、文件系统等资源,更有可能对其他容器、宿主机产生影响。容器的隔离层次更少,攻击路径更短,攻击面更大,危及整个系统的安全。

1.2 从容器生命周期看容器的关键安全风险

图2 Docker容器典型使用流程

Docker作为容器引擎的代表,从它的使用流程可以看出,容器安全风险贯彻容器构建、部署、运行整个生命周期。例如,在构建阶段,可能会遇到的软件供应链攻击,包括基础镜像污染、CI工具攻击、制品库漏洞攻击等。在部署阶段也可能面临针对云原生基础设施平台攻击,包括开源组件编排工具、安全合规检查等。在运行时阶段,还可能面临针对云原生应用的攻击,包括逃逸攻击、安全隔离、注入漏洞、弱口令等。

容器的生命周期短,动态变化快,超过50%容器从上线到下架的整个生命周期不超过1天。快速检测和响应容器入侵事件,把损失降到最低,成为了一大安全难题。

1.3 历年容器安全漏洞情况表明,容器逃逸占比最高、影响较大

在容器集群中,若攻陷一个容器,就可以横向移动到其它容器上,或者逃逸到node节点上进行持久化,控制整个节点。下一步,攻击者还可以通过漏洞利用或者调用API SERVER控制整个集群。容器的攻击价值高,俨然成为攻击者眼中“香饽饽”。

从下图的历年容器安全问题分布及容器运行时入侵事件统计分布可以看出,容器逃逸是用户最关注的安全问题,同时也是业务场景中遇到最多的安全问题。


图3 容器安全问题分布


图4 2021年容器运行时入侵事件统计分布

2、容器逃逸技术及原理

容器逃逸,是指“流氓”容器尝试突破正常隔离环境限制,借助一些手段获得容器所在的直接宿主机、宿主机上的其他容器或集群内其他主机、其他容器的某种权限下的命令执行能力,进行恶意攻击或执行越权访问的行为。如下图所示,容器逃逸漏洞可能打穿容器节点,甚至整个集群。

图5 从攻击方视角看容器逃逸攻击路径

容器逃逸的前提是已经获得了容器内某种权限下的命令执行能力,然后捅破隔离。容器的隔离技术不是新发明的,它借助Linux资源隔离的核心技术namespace来实现。

图6 应用层容器逃逸原理分析

从图6可以得知,Linux内核先天性隔离性不足,尽管目前namespace已经提供了非常多的资源隔离类型如PID、mount、network、UTS、IPC、user等,但除namespace外其它内核资源并未隔离或隔离不充分,其中包括一些系统的关键性目录(如/sys、/proc等),这些关键性的目录可能会泄露主机上一些关键信息,让攻击者利用这些信息对宿主机发起攻击,使得容器逃逸到宿主机。

特权模式在6.0版本的时候被引入Docker,其核心作用是允许容器内的root拥有宿主机的root权限。使用特权模式启动容器后(docker run --privileged),Docker容器被允许访问宿主机上的所有设备、可以获取大量设备文件的访问权限、可以执行mount命令进行挂载。当Docker管理员可通过mount命令将宿主机磁盘设备挂载进容器内部,即可获取对整个宿主机的文件读写权限,也可以通过写入计划任务等方式在宿主机执行命令,成功逃逸。

Linux内核自版本2.2引入了Capabilities机制,将传统的root用户的特权划分为30+个不同的单元,进行精细化管理。但如果Capabilities设置不正确,就会让攻击者有机可乘,实现权限提升。例如当容器以--cap-add=SYSADMIN启动,Container进程就被允许执行mount、umount等一系列系统管理命令,如果攻击者此时再将外部设备目录挂载在容器中就会发生Docker逃逸。可见,capabilities控制不当同样会引入容器逃逸,当前业界已识别SYSADMIN、DAC_READ_SEARCH、SYS_MODULE、SYS_PTRACE引入了逃逸漏洞。

3、基于业务的容器逃逸场景分析

基于大量业界容器安全CVE漏洞的研究,对产品业务场景中运行态的容器安全薄弱环节进行了分类,识别出容器逃逸主要分布在应用层、服务层和系统层。

图7 在产品业务场景中识别的容器逃逸问题

应用层的逃逸,主要体现在特权模式与配置不当,如利用特权模式逃逸、借助Capability逃逸。为了方便容器与宿主机进行数据交换,几乎所有主流的解决方案都会提供挂载宿主机目录到容器的功能,由此而来的容器逃逸问题也呈上升趋势,当容器以读写形式挂载宿主机上的敏感文件或目录如docker.sock、主机procfs时,从容器中逃逸出去易如反掌,手段也多种多样。

除了应用本身的脆弱性引入的攻击外,服务层集群、容器运行时本身的脆弱性问题也不容忽视。例如攻击者借助k8s的8080、6443未授权访问,可通过容器访问K8S master api进行恶意调用;参与到容器生态中的服务端、客户端程序自身存在的漏洞如runc、Containerd组件漏洞,同样可被容器利用从而获取宿主机的控制权。

此外,从系统层面来看,Docker直接共享宿主机的内核,所以当宿主机内核存在安全漏洞时会一并影响Docker的安全,导致可能会造成Docker逃逸。例如著名的脏牛漏洞CVE-2016-5195是Linux内核中的权限提升漏洞,通过它可实现Docker容器逃逸,获得root权限的shell。

4、解决容器逃逸的方案

4.1 Docker自身安全性改进

容器发展早期,容器内的root等同于宿主机上的root,若容器被攻破或容器本身存在恶意程序时,在容器内就可以获取到宿主机的root权限。Docker 1.10版本,引入User Namespace技术进行用户隔离,可将容器内的root用户映射到宿主机上的非root用户,大大减轻了容器逃逸的风险。容器社区持续在努力将纵深防御、最小权限等理念和原则落地,因此建议尽可能使用最新版Docker。且使用最新版本docker,已知的CVE漏洞都已修复,如更新Docker版本到19.03.1及更高版本,不再受CVE-2019-14271、CVE-2019-5736等漏洞影响。

4.2 安全配置及挂载

应用层大多容器相关漏洞,均由不安全配置或挂载引入。无论是细粒度权限控制还是其他安全机制,用户都可以通过修改容器环境配置或在运行容器时指定参数来调整。建议docker容器或k8s pod启动时,做到:

  • 不以root权限运行Docker服务;
  • 不将宿主机敏感目录挂载至容器目录;
  • 不开启特权模式,如需添加相应的权限可以使用-cap-add参数;
  • 不将容器以-cap-add=SYSADMIN、-cap-add=DAC_READ_SEARCH、-cap-add=SYS_MODULE、-cap-add=SYS_PTRACE等高Capabilities启动。如攻击者借助容器的CAP_DAC_READ_SEARCH权限,采用著名的Shocker攻击方式,可在容器内逃逸读取到host的/etc/shadow文件。

4.3 加强内核安全和管理

尽量安装最新补丁的主机内核版本,如Linux内核版本>=2.6.22解决了CVE-2016-5195(脏牛),Linux内核版本>=4.14解决了CVE-2017–1000405(大脏牛)。

4.4 使用安全加固组件

Linux的SELinux、AppArmor、GRSecurity组件都是Docker官方推荐的安全加固组件,这三个组件可以限制容器对主机的内核或其他资源的访问控制权限。下面说明下这些安全加固组件:

  • SELinux:是Linux的一个内核安全模块,提供了安全访问的策略机制,通过设置SELinux策略可以指定如何严格或宽松地进行检查,实现某些进程允许访问某些文件;
  • AppArmor:类似于SELinux,也是一个Linux的内核安全模块,普通的访问控制仅能控制到用户的访问权限,而AppArmor可以控制到用户程序的访问权限,也能识别0day漏洞和未知的应用程序漏洞所导致的攻击;
  • GRSecurity:是一个对内核的安全扩展,可通过智能访问控制,提供内存破坏防御,文件系统增强等多种防御形式。它提供了一些工具让用户配置、使用这些安全特性。

4.5 使用安全容器

容器有着轻便快速启动的优点,虚拟机有着安全隔离的优点,安全容器可以兼顾两者的优点,做到既轻量又安全。

安全容器与普通容器的主要区别在于,安全容器中的每个容器都运行在一个单独的微型虚拟机中,拥有独立的操作系统和内核,并且有虚拟机般的安全隔离性。

安全容器目前推荐的主流技术方案是Kata Containers,它并不包含一个完整的操作系统,只有一个精简版的Guest Kernel运行着容器本身的应用,可以通过使用共享内存来进一步减少内存的开销。另外,它还实现了OCI规范,可以直接使用Docker的镜像启动Kata容器,具有开销更小、秒级启动、安全隔离等许多优点。

图8 普通容器与安全容器对比

5、后记

正如前文所述,容器已经成为黑客的重点攻击目标,而应用层的容器逃逸漏洞占比最高。容器在应用层的安全很大程度上取决于其配置的安全性,我们在业务场景中尤为重要的就是Capabilities的赋予,一定要做到权限最小化,丢弃没有用到的特权。借助Capabilities逃逸只是冰山一角,还有大量逃逸场景待进一步研究。尽管有些Capabilities当前还没有被恶意利用,但无法确保后续不会成为攻击者逃逸的手段,因此务必做到维持业务必须的最小权限。

权限过多,难免疏忽。权限最小化的同时也要参考业界最佳实践:启用user namespace进行用户隔离并且以非root运行,这就好比使用预编译语句防御SQL注入,从根源上防御,切断所有的攻击路径,尽管这个方案可能对现有业务部署方案有大量的改动,但仍然应该成为容器防御的最终目标之一。

当前Docker的隔离性还远达不到虚拟机的水平,应该避免把Docker容器当成虚拟机来使用,除非在虚拟机里部署容器,否则建议Docker容器里只跑可信应用。