Docker容器安全性解决方案.docx
《Docker容器安全性解决方案.docx》由会员分享,可在线阅读,更多相关《Docker容器安全性解决方案.docx(30页珍藏版)》请在冰豆网上搜索。
Docker容器安全性解决方案
目录
一、从虚拟化安全到容器安全 3
1、传统虚拟化技术 3
2、容器技术 3
二、Docker容器安全风险分析 7
1、镜像安全风险 7
2、容器虚拟化安全风险 10
3、网络安全风险 13
三、Docker容器安全机制与解决方案 16
1、容器虚拟化安全 16
3、容器网络安全 27
四、总结 30
Docker是目前最具代表性的容器技术之一,对云计算及虚拟化技术产生了颠覆性的影响。
本文对Docker容器在应用中可能面临的安全问题和风险进行了研究,并将Docker容器应用环境中的安全机制与相关解决方案分为容器虚拟化安全、容器安全管理、容器网络安全三部分进行分析。
一、从虚拟化安全到容器安全
1、传统虚拟化技术
虚拟化技术是实现硬件基础设施资源的充分利用、合理分配和有效调度的重要技术手段。
例如,在基于OpenStack的典型IaaS服务中,云服务提供商可通过搭建设备集群建立资源池,并将服务器、存储和网络等底层资源进行弹性虚拟化提供给租户。
传统虚拟化技术以虚拟机为管理单元,各虚拟机拥有独立的操作系统内核,不共用宿主机的软件系统资源,因此具有良好的隔离性,适用于云计算环境中的多租户场景。
2、容器技术
容器技术可以看作一种轻量级的虚拟化方式,将应用与必要的执行环境打包成容器镜像,使得应用程序可以直接在宿主机(物理机或虚拟机)中相对独立地运行。
容器技术在操作系统层进行虚拟化,可在宿主机内核上运行多个虚拟化环境。
相比于传统的应用测试与部署,容器的部署无需预先考虑应用的运行环境兼容性问题;相比于传统虚拟机,容器无需独立的操作系统内核就可在宿主机中运行,实现了更高的运行效率与资源利用率。
Docker是目前最具代表性的容器平台之一,它模糊了传统的IaaS和PaaS的边界,具有持续部署与测试、跨云平台支持等优点。
在基于Kubernetes等容器编排工具实现的容器云环境中,通过对跨主机集群资源的调度,容器云可提供资源共享与隔离、容器编排与部署、应用支撑等功能。
Docker容器技术以宿主机中的容器为管理单元,但各容器共用宿主机内核资源,分别通过Linux系统的Namespaces和CGroups机制实现资源的隔离与限制。
1、Namespaces
为了保证容器进程之间的资源隔离,避免相互影响和干扰,Linux内核的Namespaces(命名空间)机制提供了UTS、User、Mount、Network、PID、IPC等命名空间实现了主机名、用户权限、文件系统、网络、进程号、进程间通信等六项资源隔离功能。
通过调用clone()函数并传入相应的系统调用参数创建容器进程,可实现对应资源内容的隔离,具体情况如表1所示。
表1:
Namespaces隔离机制
命名空间
系统调用参数
隔离内容
Linux内核版本
UTS
CLONE_NEWUTS
主机名和域名
2.6.19
IPC
CLONE_NEWIPC
信号量、信息队列和共享内存
2.6.19
PID
CLONE_NEWPID
进程编号
2.6.24
Network
CLONE_NEWNET
网络设备、网络栈、端口等
2.6.29
Mount
CLONE_NEWNS
挂载点(文件系统)
2.4.19
User
CLONE_NEWUSER
用户和用户组
3.8
对于某个进程而言,可通过查看/proc/[PID]/ns文件,获取该进程下的命名空间隔离情况,如图1所示。
其中,每一项命名空间都拥有一个编号对其进行唯一标识,如果宿主机中两个进程指向的命名空间编号相同,则表示他们同在一个命名空间之下。
图1:
进程命名空间
2、CGroups
CGroups(ControlGroups,控制组)机制最早于2006年由Google提出,目前是Linux内核的一种机制,可以实现对任务组(进程组或线程组)使用的物理资源(CPU、内存、I/O等)进行限制和记录,通过多种度量标准为各个容器相对公平地分配资源,以防止资源滥用的情况。
在实际应用中,CGroups会为每个执行任务创建一个钩子,在任务执行的过程中涉及到资源分配使用时,就会触发钩子上的函数并对相应的资源进行检测,从而对资源进行限制和优先级分配。
CGroups提供了资源限制(ResourceLimitation)、优先级分配(Prioritization)、资源统计(Accounting)、任务控制(Control)四个功能,包含blkio、cpu、cpuacct、cpuset、devices、freezer、memory、perf_event、net_cls、net_prio、ns、hugetlb等子系统,每种子系统独立地控制一种资源,可分别实现块设备输入/输出限制、CPU使用控制、生成CPU资源使用情况报告、内存使用量限制等功能。
几个主要子系统的具体功能如表2所示。
表2:
CGroups子系统
子系统
功能
blkio
为块设备(如磁盘、固态硬盘等物理驱动设备)设定输入/输出限制
cpu
通过调度程序控制任务对CPU的使用
cpuacct
生成任务对CPU资源使用情况的报告
cpuset
为任务分配独立的CPU和内存
devices
开启或关闭任务对设备的访问
freezer
挂起或恢复任务
memory
设定任务对内存的使用量限制,生成任务对内存资源使用情况的报告
3、安全性
传统虚拟化技术与Docker容器技术在运行时的安全性差异主要体现在隔离性方面,包括进程隔离、文件系统隔离、设备隔离、进程间通信隔离、网络隔离、资源限制等。
在Docker容器环境中,由于各容器共享操作系统内核,而容器仅为运行在宿主机上的若干进程,其安全性特别是隔离性与传统虚拟机相比在理论上与实际上都存在一定的差距。
二、Docker容器安全风险分析
根据Docker容器的主要特点及其在安全应用中的实际问题,本文将Docker容器技术应用中可能存在的技术性安全风险分为镜像安全风险、容器虚拟化安全风险、网络安全风险等类型进行具体分析,如图2所示。
图2:
容器安全风险分类
1、镜像安全风险
Docker镜像是Docker容器的静态表示形式,镜像的安全决定了容器的运行时安全。
Docker容器官方镜像仓库DockerHub中的镜像可能由个人开发者上传,其数量丰富、版本多样,但质量参差不齐,甚至存在包含恶意漏洞的恶意镜像,因而可能存在较大的安全风险。
具体而言,Docker镜像的安全风险分布在创建过程、获取来源、获取途径等方方面面。
1、Dockerfile安全问题
Docker镜像的生成主要包括两种方式,一种是对运行中的动态容器通过dockercommit命令进行打包,另一种是通过dockerbuild命令执行Dockerfile文件进行创建。
为了确保最小安装原则,同时考虑容器的易维护性,一般推荐采用Dockerfile文件构建容器镜像,即在基础镜像上进行逐层应用添加操作。
Dockerfile是包含用于组合镜像命令的文本文件,一般由基础镜像信息(FROM)、维护者信息(MAINTAINER)、镜像操作指令(RUN、ADD、COPY等)、容器启动时执行指令(CMD等)四个部分组成,Docker可通过读取Dockerfile中的命令创建容器镜像。
Dockerfile文件内容在一定程度上决定了Docker镜像的安全性,其安全风险具体包括但不限于以下情况:
如果Dockerfile存在漏洞或被插入恶意脚本,那么生成的容器也可能产生漏洞或被恶意利用。
例如,攻击者可构造特殊的Dockerfile压缩文件,在编译时触发漏洞获取执行任意代码的权限。
如果在Dockerfile中没有指定USER,Docker将默认以root用户的身份运行该Dockerfile创建的容器,如果该容器遭到攻击,那么宿主机的root访问权限也可能会被获取。
如果在Dockerfile文件中存储了固定密码等敏感信息并对外进行发布,则可能导致数据泄露的风险。
如果在Dockerfile的编写中添加了不必要的应用,如SSH、Telnet等,则会产生攻击面扩大的风险。
2、镜像漏洞
对于大多数一般的开发者而言,通常需要获取一系列基础镜像进行容器云的部署和进一步开发,因此,基础镜像的安全性在一定程度上决定了容器云环境的安全性。
镜像漏洞安全风险具体包括镜像中的软件含有CVE漏洞、攻击者上传含有恶意漏洞的镜像等情况。
①CVE漏洞
由于镜像通常由基础操作系统与各类应用软件构成,因此,含有CVE漏洞的应用软件同样也会向Docker镜像中引入CVE漏洞。
镜像的获取通常是通过官方镜像仓库DockerHub或网易、阿里云等提供的第三方镜像仓库。
然而,根据对DockerHub中镜像安全漏洞的相关研究,无论是社区镜像还是官方镜像,其平均漏洞数均接近200个,包括nginx、mysql、redis在内的常用镜像都含有高危漏洞。
②恶意漏洞
恶意用户可能将含有后门、病毒等恶意漏洞的镜像上传至官方镜像库。
2018年6月,安全厂商Fortinet和Kromtech在DockerHub上发现17个包含用于数字货币挖矿恶意程序的Docker镜像,而这些恶意镜像当时已有500万次的下载量。
目前,由于Docker应用在世界范围内具有广泛性,全网针对Docker容器的攻击很多都被用于进行数字货币挖矿,为攻击者带来实际经济利益,损害Docker用户的正常使用。
3、镜像仓库安全
作为搭建私有镜像存储仓库的工具,DockerRegistry的应用安全性也必须得到保证。
镜像仓库的安全风险主要包括仓库本身的安全风险和镜像拉取过程中的传输安全风险。
仓库自身安全:
如果镜像仓库特别是私有镜像仓库被恶意攻击者所控制,那么其中所有镜像的安全性将无法得到保证。
例如,如果私有镜像仓库由于配置不当而开启了2357端口,将会导致私有仓库暴露在公网中,攻击者可直接访问私有仓库并篡改镜像内容,造成仓库内镜像的安全隐患。
镜像拉取安全:
如何保证容器镜像从镜像仓库到用户端的完整性也是镜像仓库面临的一个重要安全问题。
由于用户以明文形式拉取镜像,如果用户在与镜像仓库交互的过程中遭遇了中间人攻击,导致拉取的镜像在传输过程中被篡改或被冒名发布恶意镜像,会造成镜像仓库和用户双方的安全风险。
Docker已在其1.8版本后采用内容校验机制解决中间人攻击的问题。
2、容器虚拟化安全风险
与传统虚拟机相比,Docker容器不拥有独立的资源配置,且没有做到操作系统内核层面的隔离,因此可能存在资源隔离不彻底与资源限制不到位所导致的安全风险。
1、容器隔离问题
对于Docker容器而言,由于容器与宿主机共享操作系统内核,因此存在容器与宿主机之间、容器与容器之间隔离方面的安全风险,具体包括进程隔离、文件系统隔离、进程间通信隔离等。
虽然Docker通过Namespaces进行了文件系统资源的基本隔离,但仍有/sys、/proc/sys、/proc/bus、/dev、time、syslog等重要系统文件目录和命名空间信息未实现隔离,而是与宿主机共享相关资源。
针对容器隔离安全风险问题,主要存在以下两种隔离失效的情况:
攻击者可能通过对宿主机内核进行攻击达到攻击其中某个容器的目的。
由于容器所在主机文件系统存在联合挂载的情况,恶意用户控制的容器也可能通过共同挂载的文件系统访问其他容器或宿主机,造成数据安全问题。
2、容器逃逸攻击
容器逃逸攻击指的是容器利用系统漏洞,“逃逸”出了其自身所拥有的权限,实现了对宿主机和宿主机上其他容器的访问。
由于容器与宿主机共享操作系统内核,为了避免容器获取宿主机的root权限,通常不允许采用特权模式运行Docker容器。
在容器逃逸案例中,最为著名的是shocker.c程序,其通过调用open_by_handle_at函数对宿主机文件系统进行暴力扫描,以获取宿主机的目标文件内容。
由于Docker1.0之前版本对容器能力(Capability)使用黑名单策略进行管理,并没有限制CAP_DAC_READ_SEARCH能力,赋予了shocker.c程序调用open_by_handle_at函数的能力,导致容器逃逸的发生。
因此,对容器能力的限制不当是可能造成容器逃逸等安全问题的风险成因之一。
所幸的是,Docker在后续版本中对容器能力采用白名单管理,避免了默认创建的容器通过shocker.c案例实现容器逃逸的情况。
此外,在BlackHatUSA2019会议中,来自Capsule8的研究员也给出了若干Docker容器引擎漏洞与容器逃逸攻击方法,包括CVE-2019-5736、CVE-2018-18955、CVE-2016-5195等可能造成容器逃逸的漏洞。
CVE-2019-5736是runC的一个安全漏洞,导致18.09.2版本前的Docker允许恶意容器覆盖宿主机上的runC二进制文件。
runC是用于创建和运行Docker容器的CLI工具,该漏洞使攻击者能够以root身份在宿主机上执行任意命令。
CVE-2018-18955漏洞涉及到User命名空间中的嵌套用户命名空间,用户命名空间中针对uid(用户ID)和gid(用户组ID)的ID映射机制保证了进程拥有的权限不会逾越其父命名空间的范畴。
该漏洞利用创建用户命名空间的子命名空间时损坏的ID映射实现提权。
CVE-2016-5195脏牛(DirtyCoW)Linux内核提权漏洞可以使低权限用户在多版本Linux系统上实现本地提权,进而可能导致容器逃逸的发生。
Linux内核函数get_user_page在处理Copy-on-Write时可能产生竞态条件,导致出现向进程地址空间内只读内存区域写数据的机会,攻击者可进一步修改su或者passwd程序以获取root权限。
3、拒绝服务攻击
由于容器与宿主机共享CPU、内存、磁盘空间等硬件资源,且Docker本身对容器使用的资源并没有默认限制,如果单个容器耗尽宿主机的计算资源或存储资源(例如进程数量、存储空间等)可能导致宿主机或其他容器的拒绝服务。
①计算型DoS攻击
ForkBomb是一类典型的针对计算资源的拒绝服务攻击手段,其可通过递归方式无限循环调用fork()系统函数快速创建大量进程。
由于宿主机操作系统内核支持的进程总数有限,如果某个容器遭到了ForkBomb攻击,那么就有可能存在由于短时间内在该容器内创建过多进程而耗尽宿主机进程资源的情况,宿主机及其他容器就无法再创建新的进程。
②存储型DoS攻击
针对存储资源,虽然Docker通过Mount命名空间实现了文件系统的隔离,但CGroups并没有针对AUFS文件系统进行单个容器的存储资源限制,因此采用AUFS作为存储驱动具有一定的安全风险。
如果宿主机上的某个容器向AUFS文件系统中不断地进行写文件操作,则可能会导致宿主机存储设备空间不足,无法再满足其自身及其他容器的数据存储需求。
3、网络安全风险
网络安全风险是互联网中所有信息系统所面临的重要风险,不论是物理设备还是虚拟机,都存在难以完全规避的网络安全风险问题。
而在轻量级虚拟化的容器网络环境中,其网络安全风险较传统网络而言更为复杂严峻。
1、容器网络攻击
Docker提供桥接网络、MacVLAN、覆盖网络(Overlay)等多种组网模式,可分别实现同一宿主机内容器互联、跨宿主机容器互联、容器集群网络等功能。
①网桥模式
Docker默认采用网桥模式,利用iptables进行NAT转换和端口映射。
Docker将所有容器都通过虚拟网络接口对连接在一个名为docker0的虚拟网桥上,作为容器的默认网关,而该网桥与宿主机直接相连。
容器内部的数据包经过虚拟网络接口对到达docker0,实现同一子网内不同容器间的通信。
在网桥模式下,同一宿主机内各容器间可以互相通信,而宿主机外部无法通过分配给容器的IP地址对容器进行外部访问。
由于缺乏容器间的网络安全管理机制,无法对同一宿主机内各容器之间的网络访问权限进行限制。
具体而言,由于各容器之间通过宿主机内部网络的docker0网桥连接以实现路由和NAT转换,如果容器间没有防火墙等保护机制,则攻击者可通过某个容器对宿主机内的其他容器进行ARP欺骗、嗅探、广播风暴等攻击,导致信息泄露、影响网络正常运行等安全后果。
因此,如果在同一台宿主机上部署的多个容器没有进行合理的网络配置进行访问控制边界隔离,将可能产生容器间的网络安全风险。
②MacVLAN
MacVLAN是一种轻量级网络虚拟化技术,通过与主机的网络接口连接实现了与实体网络的隔离性。
MacVLAN允许为同一个物理网卡配置多个拥有独立MAC地址的网络接口并可分别配置IP地址,实现了网卡的虚拟化。
MacVLAN模式无需创建网桥,即无需NAT转换和端口映射就可以直接通过网络接口连接到物理网络,不同MacVLAN网络间不能在二层网络上进行通信。
然而,处于同一虚拟网络下各容器间同样没有进行访问权限控制,因此MacVLAN模式依然存在与网桥模式类似的内部网络攻击的安全风险。
③Overlay网络
Overlay网络架构主要用于构建分布式容器集群,通过VxLAN技术在不同主机之间的Underlay网络上建立虚拟网络,以搭建跨主机容器集群,实现不同物理主机中同一Overlay网络下的容器间通信。
与其他组网模式一样,Overlay网络也没有对同一网络内各容器间的连接进行访问控制。
此外,由于VxLAN网络流量没有加密,需要在设定IPSec隧道参数时选择加密以保证容器网络传输内容安全。
因此,无论采用何种网络连接模式,都难以避免容器间互相攻击的安全风险。
2、网络DoS攻击
由于网络虚拟化的存在,容器网络面临着与传统网络不同的DoS攻击安全风险。
Docker容器网络的DoS攻击分为内部威胁和外部威胁两种主要形式。
内部威胁:
针对Docker容器网络环境,DoS攻击可不通过物理网卡而在宿主机内部的容器之间进行,攻击者通过某个容器向其他容器发起DoS攻击可能降低其他容器的网络数据处理能力。
因此,存在容器虚拟网络间的DoS攻击风险。
外部威胁:
由于同一台宿主机上的所有容器共享宿主机的物理网卡资源,若外部攻击者使用包含大量受控主机的僵尸网络向某一个目标容器发送大量数据包进行DDoS攻击,将可能占满宿主机的网络带宽资源,造成宿主机和其他容器的拒绝服务。
三、Docker容器安全机制与解决方案
1、容器虚拟化安全
在传统虚拟化技术架构中,Hypervisor虚拟机监视器是虚拟机资源的管理与调度模块。
而在容器架构中,由于不含有Hypervisor层,因此需要依靠操作系统内核层面的相关机制对容器进行安全的资源管理。
1、容器资源隔离与限制
在资源隔离方面,与采用虚拟化技术实现操作系统内核级隔离不同,Docker通过Linux内核的Namespace机制实现容器与宿主机之间、容器与容器之间资源的相对独立。
通过为各运行容器创建自己的命名空间,保证了容器中进程的运行不会影响到其他容器或宿主机中的进程。
在资源限制方面,Docker通过CGroups实现宿主机中不同容器的资源限制与审计,包括对CPU、内存、I/O等物理资源进行均衡化配置,防止单个容器耗尽所有资源造成其他容器或宿主机的拒绝服务,保证所有容器的正常运行。
但是,CGroups未实现对磁盘存储资源的限制。
若宿主机中的某个容器耗尽了宿主机的所有存储空间,那么宿主机中的其他容器无法再进行数据写入。
Docker提供的—storage-opt=[]磁盘限额仅支持DeviceMapper文件系统,而Linux系统本身采用的磁盘限额机制是基于用户和文件系统的quota技术,难以针对Docker容器实现基于进程或目录的磁盘限额。
因此,可考虑采用以下方法实现容器的磁盘存储限制:
为每个容器创建单独用户,限制每个用户的磁盘使用量;
选择XFS等支持针对目录进行磁盘使用量限制的文件系统;
为每个容器创建单独的虚拟文件系统,具体步骤为创建固定大小的磁盘文件,并从该磁盘文件创建虚拟文件系统,然后将该虚拟文件系统挂载到指定的容器目录。
此外,在默认情况下,容器可以使用主机上的所有内存。
可以使用内存限制机制来防止一个容器消耗所有主机资源的拒绝服务攻击,具体可使用使用-m或-memory参数运行容器。
·
(命令示例:
docker run [运行参数] -memory [内存大小] [容器镜像名或ID] [命令])
2、容器能力限制
Linux内核能力表示进程所拥有的系统调用权限,决定了程序的系统调用能力。
容器的默认能力包括CHOWN、DAC_OVERRIDE、FSETID、SETGID、SETUID、SETFCAP、NET_RAW、MKNOD、SYS_REBOOT、SYS_CHROOT、KILL、NET_BIND_SERVICE、AUDIT_WRITE等等,具体功能如表3所示。
表3:
容器默认能力
容器默认能力
作用
CHOWN
允许任意更改文件UID以及GID
DAC_OVERRIDE
允许忽略文件的读、写、执行访问权限检查
FSETID
允许文件修改后保留setuid/setgid标志位
SETGID
允许改变进程组ID
SETUID
允许改变进程用户ID
SETFCAP
允许向其他进程转移或删除能力
NET_RAW
允许创建RAW和PACKET套接字
MKNOD
允许使用mknod创建指定文件
SYS_REBOOT
允许使用reboot或者kexec_load
SYS_CHROOT
允许使用chroot
KILL
允许发送信号
NET_BIND_SERVICE
允许绑定常用端口号(端口号小于1024)
AUDIT_WRITE
允许审计日志写入
如果对容器能力不加以适当限制,可能会存在以下安全隐患:
内部因素:
在运行Docker容器时,如果采用默认的内核功能配置可能会产生容器的隔离问题。
外部因素:
不必要的内核功能可能导致攻击者通过容器实现对宿主机内核的攻击。
因此,不当的容器能力配置可能会扩大攻击面,增加容器与宿主机面临的安全风险,在执行dockerrun命令运行Docker容器时可根据实际需求通过—cap-add或—cap-drop配置接口对容器的能力进行增删。
(命令示例:
dockerrun--cap-dropALL--cap-addSYS_TIMEntpd/bin/sh)
3、强制访问控制
强制访问控制(MandatoryAccessControl,MAC)是指每一个主体(包括用户和程序)和客体都拥有固定的安全标记,主体能否对客体进行相关操作,取决于主体和客体所拥有安全标记的关系。
在Docker容器应用环境下,可通过强制访问控制机制限制容器的访问资源。
Linux内核的强制访问控制机制包括SELinux、AppArmor等。
①SELinux机制
SELinux(Security-EnhancedLinux)是Linux内核的强制访问控制实现,由美国国家安全局(NSA)发起,用以限制进程的资源访问,即进程仅能访问其任务所需的文件资源。
因此,可通过SELinux对Docker容器的资源访问进行控制。
在启动Dockerdaemon守护进程时,可通过将—selinux-enabled参数设为true,从而在Docker容器中使用SELinux。
SELinux可以使经典的shocker.c程序失效,使其无法逃逸出Docker容器实现对宿主机资源的访问。
·
(命令示例:
dockerdaemon--selinux-enabled