随着容器时代Docker技术的近年来高速发展, Google、Amazon等各大公司接连发布基于容器Docker的新业务,云计算进入Docker容器时代,那么Docker容器技术下给安全防御体系带来哪些挑战和变化呢?  以下OPPO互联网安全团队基于Docker容器技术的安全实践,希望同大家一起探讨和学习, 一共分为4个部分:

(1)Docker自身安全问题

(2)给安全防御体系带来的挑战

(3)安全防御体系的应对

(4)Docker安全生态发展方向

1、Docker容器自身安全问题

no.1 Docker容器相关概念

docker pull registry.test.com/sec/xxxx:1.0.0

Registry: 注册服务器,用于存放镜像仓库的服务节点 ;

Repository: 镜像仓库,用于存放一系列镜像的仓库;

Image: 容器运行时的一些列静态文件,包括镜像元数据文件,镜像层文件等等(镜像的组成部分);

Docker daemon: docker的核心服务程序,后台运行,响应docker client 的请求;

Docker client: 用来docker server发起请求控制整个docker体系运行,包括镜像操作和容器操作;

Container: 镜像的运行时表现,容器和镜像的关系我们可以类似的理解为程序文件和进程的关系;

no.2 Daemon安全问题

运行一个容器的核心是Docker daemon, Docker服务运行目前是需要root权限来运行的,因此docker daemon 的安全性十分重要的,我们也需要投入非常大的精力来保证docker daemon的安全性。Docker允许用户在主机和容器之间共享文件目录,同时不需要限制容器的访问权限,这就非常容易让容器突破资源限制。例如恶意用户将主机的根目录映射到容器的/host目录中,那么容器就可以对主机上的文件任意修改或删除了。

普通用户利用docker删除root权限的文件

Docker daemon对外提供服务是采用API的方式,其底层通讯机制是TCP和unix domain socket两种方式,如果Docker daemon在对外暴露基于TCP的API接口,那在这一层通讯层面的API安全性就会变得非常重要,因为一旦拿下了Docker daemon的API接口,就等同于拿下了整个主机的所有Docker。现在Docker的集群管理都是采用TCP方式和docker daemon进行通讯。

docker集群管理配置原型

在Daemon安全问题的解决方案上,docker daemon为我们提供TLS传输层安全协议。在Docker中可以设置--tlsverify来进行安全传输校验,通过--tlscacert(信任的证书)、--tlskey(服务器或客户端秘钥)、--tlscert(证书位置)2个参数来配置。安全认证主要是在服务端设置,客户端可以对服务端进行验证。Docker官网提供了详细的证书配置过程,有兴趣的读者可以参考官网daemon HTTPS的配置。

no.3 镜像安全问题

今年3月份,有人做了一个测试,拉取了Docker Hub上公开热门镜像中的前十页镜像,对其使用Clair进行了CVE扫描统计。结果出乎预料。在一百多个镜像中,没有漏洞的只占到24%,包含高危漏洞的占到67%。很多我们经常使用的镜像都包含在其中,如:Htt,Nginx,MySQL等等。

镜像安全占比

镜像安全问题的来源分两种,一种是基础镜像的安全问题,业务方在制作镜像的时所采用的基础镜像是直接从Docker Hub或其他公共仓库下载的镜像,但是该镜像含有Webshell、木马、rootkit等恶意文件,造成在基础镜像层就出现安全问题;另外一种则是镜像仓库被入侵而导致业务镜像被恶意修改又或者是镜像在下载过程中被劫持而拉取到了一个恶意镜像(含有恶意文件的镜像)。

镜像安全方面,目前Docker提供了registry访问控制机制和镜像完整性校验机制来在校验确认镜像的安全,但是这依然是不够的,后面章节的主机入侵检测在Docker上的适配会讲解镜像层的安全扫描。

no.4 运行时安全问题

容器在运行时也会产生安全问题,包括有磁盘资源限制问题,容器逃逸问题,容器DoS攻击与流量限制问题等等。Docker本身在安全处理上主要是利用kernel的namespace进行资源隔离已经使用cgroups限制资源使用,因此其安全性处理主要是依赖于kernel的安全处理能力,而目前linux kernel在namespace和cgroups层面所能做到的依然是很有限,并非完全隔离,像/proc,/sys,SELinux,time,syslog,/dev等未隔离。例如下面这些都是由于linux kernel的隔离性不足而产生的问题,而利用这些问题点在容器内部非常容易造成安全性问题。

1. 在Docker容器中执行top、free等命令,会发现看到的资源使用情况都是宿主机的资源情况,而我们需要的是这个容器被限制了多少CPU,内存,当前容器内的进程使用了多少资源等;

2. 在容器里修改/etc/sysctl.conf,会收到提示”sysctl: error setting key ‘net.ipv4….’: Read-only file system”;

3. 程序经常需要获取系统的内存、CPU等系统资源情况,但运行在容器里面,调用API所获取的是宿主机的资源情况;

4. 对于多进程程序,一般都可以将worker数量设置成auto,自适应系统CPU核数,但在容器里面这么设置,取到的CPU核数是不正确的,例如Nginx,其他应用取到的可能也不正确,需要进行测试;

磁盘资源的限制也会成Docker的一个很大的安全性问题,容器本质上是一个进程,通过镜像层叠的方式来构建容器的文件系统。当需要改写文件时,把改写的文件复制到最顶层的读写层,其本质还是在宿主机文件系统的某一个目录下存储这些信息。所有容器的rootfs最终存储在宿主机上,这就有可能导致一个容器把宿主机上的磁盘容量消耗尽。

运行时安全问题的处理,主要通过容器能力的限制来增强安全性,包括削减能力,增添能力,seccomp,SELinux,trafic controller,quota技术。后面章节也会有在这方面的相关介绍。

主机上的所有容器共享内核

no.5 生态安全问题

大名鼎鼎的容器编排工具kubernetes最近爆出来一个严重的用户提权漏洞(CVE-2018-1002105)。该漏洞可以从Kubernetes API服务器的网络中可以直接访问聚合API服务器,就可以提升权限对任何聚合API服务器端点进行API调用,以及对该聚合API服务器执行任何API请求(例如Pod的创建以及执行任意命令并获得返回结果)。 在默认配置中,允许所有用户(经过身份验证和未经身份验证的用户)执行允许此权限提升的API调用。该漏洞目前官方推荐的嘴角修复方案是及时升级到kubernetes v1.10.11,kubernetes v1.11.5,kubernetes v1.12.3,kubernetes v1.13.0-rc.1。

今年7月份爆出了基于Docker版本的Apache OpenWhisk中发现了一个严重漏洞(CVE-2018-11757) 可导致恶意人员覆写并执行任意代码, 这些漏洞本可允许攻击者在某些情况下覆写在容器中执行的某个函数的源代码并影响同样容器中的后续执行,即使是由不同用户执行的也不例外。漏洞如遭利用,可导致敏感数据遭泄露或导致合法动作的原始逻辑遭恶意执行。研究人员指出,“另外,攻击者可能发动类似攻击,从而影响其它容器,导致攻击变成更具持续性或传播广泛的威胁”。具体而言,攻击者可利用这些缺陷获取敏感的用户数据如密码、修改或删除信息、挖掘密币或发动分布式 DDoS 攻击。具体修复方案需要更新到最新的版本。

2016年5月爆出来的docker swarm集群管理配置问题,就是将docker daemon暴露在公网上,导致任何人都可以使用docker api 来操纵容器。Docker daemon必须要绝对禁止能从公网直接访问,可以使用Docker安全代理的方式通过认证进行访问。

2、给安全防御体系带来的挑战

非容器时代下安全防御体系的落地方式主要通过以主机、用户为边界进行安全策略控制和落地,甚至很多企业由于业务发展迅猛,安全相对滞后,连这一层的安全措施都是做的并不是那么精细。但是随着我们对Docker的深入了解,会发现很多基于主机层或用户层的很多安全策略已然无法满足Docker容器层的安全要求。因为容器本身是一个Linux进程,业务进程则是由docker daemon启动的一些列子进程,因此安全策略需要在进程级做能力限制。下面我们分几个小节来进行深入的分析。

no.1 安全策略的精细化管理

目前Docker本身并没有提供进程级的能力限制与管理,而默认只是利用内核的Capability机制做了部分能力限制。现在业界的通用方案是通过SELinux、AppArmor、seccomp、capability、TOMOYO、GRSEC等做能力限制和进程级精细化安全策略管理。

1. SELinux的配置相对比较复杂,要求配置者对linux kernel的相关安全机制非常熟悉,同时需要对业务的关联访问细节有非常清晰的了解,否则非常容易造成业务访问故障。即使配置者掌握了相关知识,单元由于业务发展和迭代的速度非常快,配置变更将变得非常频繁,这更加加剧了依靠人工进行SELinux的配置的复杂度。虽然AppArmor对SELinux的配置复杂度有所改善,但与SELinux的基于角色的MAC(Mandatory Access Control)不同,AppArmor是与程序绑定的基于路径的MAC,然而在这种机制下,一旦程序路径发生改变则策略失效了。

2. Seccomp,Secure computing mode的缩写,它是linux内核层提供的一个操作,用于限制一个进程可以执行的系统调用。我们需要一个配置文件来指明进程到底可以执行哪些系统调用,不可以执行哪些调用。很显然,这需要我们能够非常清晰的了解docker内核里面有哪些系统调用,业务层需要哪些系统调用,否则就误伤了docker进程本身的运行或者业务进程的运行,到底如何配置seccomp的系统调用的安全策略有很大的执行难度。

3. Capability,docker默认对启用了Capability,关闭了docker对一部分内核能力的操控,这使得docker在安全能力上提升了一个台阶。然后很多能力还是默认开放的,如果我们去调整,则同样会遇到前面策略遇到的问题,需要对我们有很精细的安全策略管理。

因此,在业务高速发展的同时,对我们安全策略的精细化管理上提出了更高的要求。

no.2 内核安全机制的深入理解

Docker的安全机制受限于外部的安全保障,主要是Linux kernel层提供的安全机制。这需要我们对linux kernel的安全机制有充分的理解,包括SELinux的原理,配置方案等,内核能力管理,系统调用管理,在内核中启用GRSEC和PAX,通过地址随机化机制避免恶意探测等。

Docker是通过kernel的namespace 和cgroups来隔离和限制资源的使用。因此对Linux的命名空间机制需要有非常深入的了解,才能准确的判断出docker可能的潜在的安全风险。是否会通过kernel层的安全威胁穿透逃逸到宿主机上,从而影响其他业务docker或者泄露主机的相关敏感信息。例如著名的shocker.c程序就是通过open_by_handle_at调用来暴力扫描宿主机文件系统获取宿主机敏感文件(需要通过kernel的capability机制来限制相关的系统调用能力)。

3、安全防御体系应该如何应对Docker时代

之前的安全防御体系以数据、服务器和网络为中心的防御体系将要随之变化,包括主机入侵检测系统从主机上实时检测主机的安全健康情况;传统DDoS防御系统在接入层对网络数据流量进行分析和清洗;安全态势感知会从“外部“的视角审视系统内主机或业务的漏洞情况和整体的安全概况等等。

然而,Docker作为一个新的技术体系而引入到业务、运维当中,那么传统的安全防御体系,防御工具等是否需要做调整,以及如何调整。下面会从主机入侵检测系统,安全态势感知系统(安全扫描),DDoS防御,防火墙管理等几个方面做一些分析。

no.1 主机入侵检测系统

主机入侵检测系统通常情况下是按在主机上的agent对主机上的文件(包括可执行文件,配置文件,脚本文件等),进程,网络情况,日志审计情况等进行扫描和恶意识别,并且及时预警主机的安全状况。而Docker的产生,这些都发生了一些微妙的变化,例如入侵检测的agent是安装在主机上还是打包到Docker镜像里面和容器一起运行呢?如果是在Docker容器里面运行,是否会出现问题呢?

就目前业内方案,两种做法都有,有可以和镜像打包到一起的agent也有独立驻守与主机的agent,并且后者居多。一般而言,入侵检测系统都会利用的kernel层的部分特性,例如audit等。如果是在Docker容器里面运行,而Docker容器又是共享内核的,所以在同一台主机上可能会有很多agent在运行,但是他们的区别仅仅是运行在各自的kernel namespace里面(Docker会创建不同的namespace),而做的很多事情确是一样的。这样不但无故增加主机的资源消耗,并且也有可能会因为内核共享的原因导致agent的运行不正确、可能会出现不可预知的情况。

其实主机上单独安装agent是可以完成胜任docker的扫描和审计的。Docker的可读写层文件系统实际上是会挂载主机上的文件系统,可以通过从主机上来的相关文件目录扫描来识别Webshell,恶意二进制文件等。对于业务进程而已,Docker上的进程其实对于主机上是可见的,因为docker的namespace一般都是继承自主机的root namespace。可以通过直接扫描主机上的进程行为来识别当前docker中运行的进程是否有问题。下面简单分析一下Docker的启动一个反弹shell,我们可以在主机上使用常规的手段对这个反弹shell进行分析识别。

Docker进程关系树

主机上识别到的恶意进程

上面两个图中,其实是在docker中启动了一个反弹shell,主机上可以直接观察到这个进程,并且可以分析这个进程的so等相关信息的加载情况。

通过上述分析,以及根据docker的镜像和容器运行规范,主机入侵检测系统可以支持以下这些方面来覆盖到Docker容器。

1.传统的主机入侵检测能力依然保持;

2.对容器挂载的目录可以重点扫描和监控;

3.针对docker的配置进行专门的审计,包括daemon的配置,证书的检测,docker运行目录的扫描等等;

4.针对docker的本地镜像库进行镜像扫描,其镜像文件的扫描其实主机上其他普通可执行文件的扫描是一样的,所谓镜像其实就是按层把二进制文件通过一个配置文件组织起来;

5.针对docker的子进程进行特定扫描,但是其关联的可执行文件需要到相对应的镜像中去查找;

no.2 安全态势感知

安全态势感知是从“外部”视角去对系统进行扫描探测,发现系统存在的安全缺陷,从而提供给使用方对业务系统的安全预警和安全事件跟踪。安全态势感知的主要工作是:

1. 对主机上开放的端口进行扫描和服务识别;

2. 对识别到的应用组件进行漏洞探测;

3. 对Web应用进行链接抽取和web漏洞探测扫描;

4. 任务,漏洞进行管理和告警;

Docker技术的引入对扫描本身影响不大,依然可以使用原来的方式探测扫描,但是在业务、服务端口上docker的变化会很快,而且非常频繁,这会导致端口、服务的跟踪管理变得很复杂,例如当前扫描到的服务很有可能一会儿之后就不在这台机器,迁移到其他机器上了,诸如此类。因此,态势感知的扫描识别和漏洞追踪管理需要结合具体的docker编排系统进行适配。

no.3 DDoS防御系统

使用Docker后,主机上的业务将会出现大规模的混布,业务和服务器之间的关系不再是以前的一对多的模式,而是变成成多对多的模式。在这种模式下服务的访问关系变的更加复杂,数据访问除了跨主机之间的访问还有主机内通过网桥方式访问,所以传统DDoS防御(从交换机进行流量分析)方式的效果会大打折扣。DDoS的防御方式除了在入口层做防御之外还需要保证在主机内的流量是可以受到控制的,必须要在主机的网卡层面做到流量的检测和清洗,同时也包括限流。例如,如果在一台主机上同时部署了MySQL,Memcached,如果有入侵者利用Memcached做放大攻击,Memcached的流量将会影响MySQL的使用。因此在主机层不但要做入向流量的限制、检测和清洗,同时我们还需要兼顾出向的流量的使用情况。

DDoS防御的适应

no.4 防火墙管理

默认情况,Docker和外界通讯都是通过iptables来做NAT的,当Docker的实例数量很大时,iptables的规则会变的很混乱,并且没有办法统一管理,这对防火墙管理将是灾难性的,性能也无法得到保障。而且业务访问管理也是非常复杂,因此SDN的方案的优势就显现出来了。

结合Docker在网络架构中的插件模型,可以很好的根据用户的自定义扩展网络模型。我们也正在考虑和探索在应用层使用DPDK构建一套完整的网络安全转发层用于支持Docker的跨主机通讯。在这套体系中,可以支持到正常业务通讯能力,安全防御能力,防火墙管理能力,以及兼顾到SDN方案,同时还可以提升整体的通讯性能。

4、Docker生态未来的安全方向

Docker 和容器技术的发展可谓是日新月异,对传统的安全方案带来很多挑战。当下的安全方案也都是处于萌芽状态,基本都是靠外部辅助工具(方案)做为安全手段,而docker本身对安全的支持会比较薄弱,这种做法只能暂时把一些安全漏洞从外部补上,而无法从根本上解决。

后续Docker安全可以从下面几块内容开展:

1. 沿着Docker本身,在Docker内部提供原生态的安全机制,让Docker发展和成长都是直接在自身的安全体系下成长;

2. 对于相关生态圈内(例如kubernetes),直接集成安全方案;

3. 在Docker的libnetwork层定制安全专用的安全通信机制。

声明:本文来自OPPO安全应急响应中心,版权归作者所有。文章内容仅代表作者独立观点,不代表安全内参立场,转载目的在于传递更多信息。如有侵权,请联系 anquanneican@163.com。