容器应用安全威胁
微服务安全
从传统的单体应用到微服务应用,安全一直是人们关注的热点,传统的单体应用由于暴露服务端口少,攻击 面较为单一,安全人员也知道常见的攻击点,所以做好相应的防护即可解决大部分问题。
微服务由于将传统的单体应用模块拆分为众多的服务,其端口数量的暴涨必然导致攻击面增多。对于传统的 单体应用架构,访问权限、授权机制、隔离审计等只需要做好一道入口的防护即可。
而对于微服务架构来说由于含有多个服务,故每个服务的访问都要进行适当的监控管理和保护。可以想象下, 如果在众多的微服务中泄露了某个身份验证令牌或接收了伪造的访问凭证,那整个系统都会陷入威胁中,这些威 胁无疑增加了安全防护的难度。
微服务通常由许多服务构成,虽然微服务提倡隔离、轻量、独立开发部署、业务间耦合等,但有时服务间 是需要紧密相联的,比如多个服务间共享数据。这些服务之间的联系在微服务架构中通常是以点对点的形式呈现, 随着这些联接的增多,如果其中一个服务因安全漏洞
被攻破,那么其它联接的服务也会受到牵连,从而整个系统 都会落入攻击者手中。此外,微服务通常使用容器作为载体,应用被打包成镜像,并以容器的方式分布式
地运行在微服务架构中, 容器自身有许多安全威胁,比如从容器逃逸宿主机,容器网络攻击等。#### DevOps 安全
在网络急速发展的大数据时代,很多企业都贯彻着“敏捷”的思维和行动。例如 DevOps 这种开发和运营的 新模式,缩短了软件生命周期
各个环节的等待时间,减少了很多重复性、手工性的工作,使得解决问题的成本明 显降低,提高了敏捷开发的效率。但敏捷之余忽略安全,这会是一个危险的信号,而且正在不断的被验证着 [49]。2017 年 11 月 22 日,Uber 发布声明,承认 2016 年曾遭黑客攻击并导致数据大规模泄露。根据这份声明, 两名黑客通过第三方云服务对 Uber 实施了攻击,获取了 5700 万名用户数据,包括司机的姓名和驾照号码, 用户的姓名、邮箱和手机号。调查发现,Uber 数据泄露的原因竟然是工程师将解锁数据库
的安全密钥存储在 GitHub 的一个可以公开访问的页面。这类由于操作不当引发数据泄漏的事件并不是孤案,尤其值得注意的是,当今云环境和 DevOps 的迅速发 展导致安全风险显著地提高了。安全公司 Detectify 的安全顾问 FransRosén 曾于 2017 年 7 月 13 日发布一份 报告称“网络管理员经常忽略 AWS 访问控制
列表(ACL)规则,因服务器错误配置而导致大量数据泄露。”越来越多的消费者、监管机构和市场发现由此所造成的数据泄漏的代价是高昂的、无法接受的。由于数据泄 漏,市场资本中朝夕之间损失数以亿美元计、消费者对企业和机构的信任度下降,在某些情况下,企业负责人的 职业生涯可能会受到影响。毫不夸张地说,一些依赖数据生存的企业甚至可能在无意中因为一个密钥存储的疏忽 而使整个企业面临灭顶之灾。
安全容器防护
作为轻量的虚拟化实现方式,容器技术在设计之初就已经做了一些安全考虑,并且构成了容器安全重要的防 护基础。本章将就容器面临的安全风险与威胁,介绍常见的防护思路和防护方法。
Linux 内核安全机制
基础安全主要指 Linux内核相关功能模块实现,包括容器资源的隔离、管控等。容器技术,无论是 Docker 还是 LXC,在初始设计时,都具有类似的安全考虑。例如通过内核命名空间(Namespace)构建一个相对隔离 的运行环境,保证了容器之间互不影响;通过控制组(CGroups)对 CPU、内存、磁盘 I/O 等共享资源进行隔离、 限制、审计等,避免多个容器对系统资源的竞争。这些 Linux内核模块功能,构成了容器的基本安全保障。
内核命名空间
内核命名空间是 Linux内核一个强大的特性。新创建一个容器时,后台会为其创建一组命名空间和控制组的 集合。命名空间为容器提供了最原始也是最简单的隔离方式。保证一个容器中运行的进程看不到或者影响不到运 行在另一个容器中的进程或者是容器主机的进程。命名空间提供了 PID命名空间、网络命名空间、IPC 命名空间、 mnt 命名空间、uts 命名空间和用户命名空间等。
例如,PID 命名空间实现了不同用户之间进程的隔离,保证不同的命名空间中可以有相同的 pid,同时 可以方便地实现容器的嵌套。容器中进程的交互,采用了 Linux 常见的进程交互方法 IPC(Inter-Process Communication),包括信号量、消息队列和共享内存等,需要在 IPC 资源申请时,加入命名空间信息,保证每
个 IPC 资源有一个唯一的 32 位 Id。
容器网络的隔离通过网络命名空间实现,每个网络命名空间拥有独立的网络设备、IP 地址、路由表等。每个 容器也都拥有自己的网络协议栈,不同的容器不会获取对其它容器的套接字或接口的访问权限。
Linux内核在 2.6.26 之后引入了内核命名空间,这也就意味着自 2008 年 7 月 2.6.26 版本内核发布之后,命 名空间已经已经在大量的生产系统得到使用和验证。其设计和实现可以认为较为成熟。
控制组
控制组 CGroups 是 Linux 内核的另一个重要特性,主要用来实现对资源的限制和审计等,该技术最早由 Google 在 2006 年提出,Linux 内核自 2.6.24 版本开始进行支持。
在容器技术的实现中,CGroups 是一个重要的组成部分,它提供了多种度量标准,来确保每个容器获得公平 的 CPU、内存和 I/O 等资源,对容器资源进行限制和审计。同时限制某个容器的最大资源使用量,防止其耗尽资 源致使系统性能降低。
CGroups 虽然不能实现容器间的隔离,但是其对资源的审计和限制,对于缓解拒绝服务攻击有着重要的作用, 尤其是像公有云和私有云的 PaaS 服务在面对多租户时,保证每个租户容器的正常运行,防止恶意租户滥用资源。
内核功能限制(Capabilities)机制
通常 Linux系统上众多的服务进程以 root 用户权限运行,比如 SSH、Cron、Syslog、硬件管理工具、网络配 置工具等,一旦服务被攻击者攻破,攻击者就有系统最高权限进行破坏。Linux内核功能提供了更细粒度的权限 控制,例如挂载、访问文件系统,以及内核模块加载等。
容器服务可利用 Linux内核功能的机制,在多数情况下避免使用真正的主机 root 用户权限。因此容器可以运 行在一个内核功能集合的约束下,比如在容器创建的时候,可以拒绝所有的挂载(mount)文件系统、访问原始 套接字、创建新设备节点、以及更改文件所有者 / 属性等文件系统操作。这样,即使容器遭到攻击者入侵,攻击 者也是很难在容器内部对宿主机做恶意操作。
默认情况下,Docker 采用白名单方式实现功能限制的,也就是说,白名单之外的功能会全部被禁用,在 Linux手册中可以查看完整的可用功能列表 [50]。
不过运行 Docker 容器时有一个风险:容器采用默认内核功能和挂载可能会导致容器之间的隔离问题,此外, 攻击者通过主机系统漏洞对容器产生威胁。因此 Docker 允许通过使用非默认配置文件添加和删除内核功能,来 增加其安全性。对于用户,应该明确其所需的具体功能,删除不必要的内核功能。
其它内核安全机制
内核功能是现代 Linux内核提供的众多安全特性之一,除此之外,还可以利用其它常用的安全机制来加固和 防护 Docker 容器,比如 TOMOYO[51],AppArmor[52],SELinux[53],Grsec[54]等。
比如使用 Grsec 和 PAX运行内核可在编译和运行时,基于地址随机化等技术增加安全检查,这样就避免了 许多漏洞利用。由于这些安全特性属于宿主机系统范畴,独立于容器,因此不需要对容器进行特殊的配置。
另外,如果使用的发行版操作系统带有 Docker 容器的安全模板,则可以直接使用。例如,Docker 官方团队 发布了一个可与 AppArmor 配合使用的模板,Red Hat 也提供了适用于 Docker 的 SELinux策略。这些模板提供 了一个额外的安全网,用户可以使用特定的访问控制机制来定义自己的策略。
- SELinux 安全加固
首先介绍强制访问控制(Mandatory Access Control,MAC),它是指计算机系统根据使用系统机构事先确 定的安全策略,对用户的访问权限进行强制性的控制,也就是说系统独立于用户行为强制执行访问控制。
SELinux最早由美国国家安全局(NSA)发起,是一种强制访问控制的实现,它是 Linux历史上最杰出的安 全子系统。在这种访问控制体系的限制下,进程只能访问那些在它的任务中所需的文件。对于目前可用的 Linux 安全模块来说, SELinux 功能最全面,而且测试最充分,它是基于对 MAC 20 年的研究基础之上建立的。
使用方法:启动 Docker 服务时需添加 SELinux选项。
- docker daemon --selinux-enabled = true
当运行 shocker1 时: - docker run --rm -ti --cap-add=all shocker bash
shocker 的代码在暴力破解的过程中循环遍历找出/etc/shadow,但是读取时被 SELinux阻止了,返回信息为: #open: Permission denied
可见 SELinux安全加固确实有效。!
1 Github 上的项目 Shocker,它描述了怎样逃逸 Docker 容器并读取到 Host 的 /etc/host 文件的内容,完整代码为:
- AppArmor 安全加固
AppArmor 也是一种 MAC控制机制,其主要作用是设置某个可执行程序的访问控制权限,可以限制程序读 / 写某个目录 / 文件,打开 / 读 / 写网络端口等。
Docker 服务在启动过程中会判断当前内核是否支持 AppArmor,若支持,就创建默认的 AppArmor 配置文件 /etc/apparmor.d/docker,并应用这个配置文件。启动容器时,在初始化过程中 Docker 会使用相应的 AppArmor 配置作用于容器。也可以使用 –security-opt 选项来指定作用于容器的 AppArmor 配置文件。
制定一个 AppArmor 规则,并应用到容器上。首先拷贝一个模板。
- cp /etc/apparmor.d/docker /etc/apparmor.d/container
使用方法:修改 /etc/apparmor.d/container 配置文件,加入一行 deny /etc/hosts rwklx,用该规则运行
shocker。 - apparmor_parser -r /etc/apparmor.d/container
- docker run --rm -ti --cap-add=all --security-opt apparmor:container-default shocker bash
返回的结果同样为 open: Permission denied,攻击依然不奏效,“deny /etc/hosts rwklx” 该条规则限制了 容器内的其它程序对 /etc/hosts 的获取。
容器技术跟虚拟化技术相比,没有了 Hypervisor 这一层,即容器的资源管理没有 VMM(Virtual Machine Manager),而完全依赖于主机的操作系统,那么如何保证容器是按照其规范正确的使用,成为了容器安全的一 个重要的前提。
Docker 公司与美国互联网安全中心(Center for Internet Security,CIS)合作,发布了一份详尽的基准配置 文档 [55],该基准文档从容器主机、Docker 守护进程、镜像配置、运行配置等方面,给出了参考的配置建议。