本文整理自2019年GOPS 全球运维大会主题演讲——《容器时代:数万台服务器下的 Docker 深度安全实践》,演讲嘉宾刘湛卢,来自于OPPO互联网安全团队,负责OPPO互联网安全团队的研发工作。本文主要内容如下:
Docker生态与架构安全问题和应对方案OPPO容器安全实践容器生态的安全展望先简单介绍一下行业背景。
当前,OPPO在全球有超过2亿+的DAU,最近几年资料量增长超过180倍。从服务器数量和业务量的变化趋势,可以看到互联网业务整体的发展趋势是呈指数型上升,同时业务量的增长带来了服务器数量的高速增长,这也与业务指数曲线是类似的。而当下,业界主流技术已经从物理服务器承载业务转向了Docker化,Docker是当前热门的云端计算主流技术。
Datadog 2018年6月统计的资料显示,25%的公司已经采用Docker,预计2020年会达到50%,其他没有使用Docker的公司也在追赶过程中。
一、Docker生态与架构
所谓容器生态,就是围绕容器周边的一系列元素和容器一起构成整个容器构建、执行的方案和工具、档案等,而容器的安全并不仅仅只是容器本身的安全性,也和容器生态的安全紧紧结合在一起,需要有容器整个生态的安全支撑才能一起构建容器完善的安全方案。
那么容器的安全具体包括哪些元素?毫无疑问,Docker本身是其中核心的一部分。这是把容器执行起来的关键,控制着容器的启停、管理容器执行所需要的资源、以及容器和外界的互动等容器核心功能点。
同时,Docker容器的执行是需要映象作为支撑点的。每个业务功能可能会有一个映象,当业务众多,而且有不同版本时,尤其像微服务这种对业务的拆分粒度很小的情况,会产生大量的映象。在Docker里面是由registry来管理映象,他存放着我们所有的映象,当Docker在执行的时候,可以指定从某个registry拉取相应映象到本地执行,当然这个拉取动作Docker自己会去执行。
到了生产环境,尤其是业务体量比较大的公司或者机构,对如何管理映象的分发、容器的排程、业务的高可用能力、容器多副本的维护等方面提出了很大的挑战,由此kubernetes应运而生。kubernetes的出现更加方便了容器在大规模使用,复杂业务场景上的使用。
先来看一副Docker安全与传统安全的对比图:
传统的主机层安全问题包括操作系统的安全漏洞,webshell,恶意二进位制程式,rootkit,核心安全,ssh暴力破解等。
Docker的安全包括:Docker本身的安全(包括主机的安全),映象的安全,registry的安全,映象分发传输的安全,编排系统(kubernetes)的安全将会成为容器安全建设的核心点。
Docker的架构:
一般而言,Docker会跨私有网络和互联网执行,宿主机,企业级自己的私有注册中心都会在私有网络中,而Docker hub 这类公有注册中心,互联网上的其他的公共注册中心会执行在公网。在私有网络中,宿主机上包括Docker客户端和Docker的守护程式(Docker daemon),通过Docker客户端向Docker的守护程序传送Docker指令来启停容器,或者获取容器的相关资讯。Docker守护程式则接收到来自客户端的请求则执行Docker命令,包括解析Docker指令,执行容器的启停,向各个仓库拉取映象等来完成容器的操控。所以Docker守护程式的安全是非常关键的,他能直接操控该主机上的所有容器。
二、安全问题和应对方案
几个核心安全问题,第一是主机与容器守护安全,第二是映象安全,第三是容器执行时安全问题,第四是生态安全。
主机与容器守护安全问题。主机上的安全配置是否影响到容器的执行,主机的安全漏洞是否影响到容器执行,容器内的程序是否可以利用主机上的安全漏洞。
映象安全方面。映象是否安全,映象传输过程中是否会篡改,映象被销毁后是否还存在安全问题。
容器执行时的安全问题。各容器之间的通讯是否安全,隔离是否充分,容器在资源使用上是否安全。
生态安全。主要是Docker本身的安全性,还有编排系统的安全问题,容器的秘钥管理和传统的秘钥管理是否不一样,容器化以后的资料隐私保护方案是否和传统方案一致。
2.1 主机与Docker守护程序的安全问题
先看Docker守护程序的安全,这个是用root许可权建立的档案,通过非root档案就把它删除掉了,这种主要是Linux对核心隔离性的不足,在Docker使用时隔离级别是由使用者自行决定的,把这个账号直接加到Docker的账号组里就具备了这个许可权。
我们再看一个例子,曾经爆出来的Docker swarm丛集管理配置问题,就是将Docker daemon的相关界面暴露在公网上,并且并没有启用任何保护措施,从而导致任何人都可以使用Docker api来操纵容器,这就造成了一个危险极大的安全隐患。
而通常安全可靠的做法可以由这几种方式:
使用Docker本身提供的TLS/HTTPS加密界面通道,但这种在大规模使用的时候在证书和秘钥的管理方面会带来一定的挑战。通过统一的代理来访问每个Docker daemon的界面,而不直接暴露其界面,这样使用安全代理加固的方式保护Docker daemon的界面安全性。总的来说 Docker 守护程序的安全问题主要来自这几个方面:
需要root许可权执行,这个在daemon安全上可能会带来很大的安风险;守护程序对外提供API服务,用于的容器和整个Docker的管理工作,这使得对这些界面进行安全保护是非常重要的;
应对方案:
尽量不要直接开启Docker remote api服务,如果必要则可以通过中间代理层来做隔离控制;在隔离层新增ACL,新增控制白名单,加强对访问源的监管;启用TLS认证,加强验证和通讯的传输过程;守护程序的相关安全配置的合规扫描和审计;2.2 映象安全问题
所有容器都是基于映象执行,如果映象的安全性受到威胁,显然容器就被攻陷了,甚至主机都可能沦陷。
Docker hub是在行业主流的映象仓库,其由Docker官方提供。曾经有人对其映象进行抽样,使用clair对映象扫描,发现安全的映象只有24%,而风险映象占到76%,其中高风险的映象有67%,这说明映象已经成为Docker安全中的一个重要的安全攻击防御战场了。
例子:有人曾经利用Docker hub 传播了17个恶意映象,其中包括有挖矿程式码,后来分析其相关映象的恶意程式码,发现其中相关联的钱包地址显示,这些恶意映象挖出了价值9万美元的门罗币;所以,利用恶意映象进行挖矿、传播恶意档案、勒索病毒、逃逸到主机系统做恶意攻击等等,这些都可以植入到映象中。
总结一下映象会产生安全问题的几个方面:
映象内容安全:映象可以携带的安全问题如依赖库漏洞,植入病毒,恶意档案等其他安全问题,如果使用了基础映象,那么基础映象是要可信的;
映象内容性质:映象内容的大小,在磁盘上是否会建立或者包含较大的磁盘空间,因为一个映象可以建立多个容器,容器多了以后容易导致主机资源不够用,再者是映象中档案个数过多,会导致大量的inode被占用而过多消耗系统资源;
映象仓库安全:包括仓库本身的问题和安全加固,映象的传输安全,安全认证,映象签名体系等等;
映象中的使用者许可权控制:预设在映象中的程序是root许可权执行,使用者可以在构建映象时遵从相关规范,以最小许可权原则执行;
映象扫描审计:通过对映象的深度扫描和审计,可以及时发现映象的安全问题。
映象安全扫描工具:
Clair:当下非常主流的映象安全扫描工具,其扫描分析特点是使用静态分析方式,会把映象包拆开,对映象进行层级分析,和已知的CVE库进行版本对比的方式来扫描映象。这种分析方式有很多局限性,只能根据CVE库的版本进行对比,换言之对0day是毫无防御能力,没有收录在CVE或其恶意库中的将得不到准确的扫描结果。所以扫描效果不是特别明显。
其他几个扫描工具包括 anchore 和 Dockerscan 的扫描工具也是类似的思路。
这些都是当前开源、主流的一些扫描工具,后面我们也会讲讲oppo的深度映象扫描系统的相关实践。
2.3 执行时安全问题
容器执行时安全是从Docker daemon根据映象拉起一个容器开始,那么在执行过程当中,容器的安全性就和容器的执行机制、执行时库、系统呼叫、读写行为等这一系列的动态动作关联起来了。前不久爆发的runC容器逃逸的漏洞,简单来说这个漏洞就是通过在拉起一个恶意映象的过程中,把Docker-runc这个关键程式覆盖了,当然Docker daemon下次再启动容器时就会执行替换的Docker-runc恶意程式码。除了runc容器逃逸的安全问题,主机层核心如果存在dirty cow漏洞也可以溢位到主机上。
容器执行时安全,除了从容器内逃逸到主机上之外还有其他的方式,容器执行时的安全问题还有下面这些:
磁盘资源限制上,例如某个容器把磁盘写满了导致其他容器无法正常工作。容器之间的Ddos攻击,某个容器把当前主机的带宽打满,导致其他容器无法工作。由于kernel层的隔离性不足上面,例如/proc,/sys等子系统的隔离性不足,容器内看到的cpu个数/mem等资料不准确等等。那么应对这些问题都有哪些办法?Docker本身在这个层面上的安全控制能力是比较弱的,主要依靠核心层面有提供一些能力和许可权限制工具来辅助处理,包括seccomp,capability,selinux,apparmor,tc流量控制,quota技术等。
2.4 容器生态安全问题
除了容器的执行时安全,映象安全,守护程序的安全问题,容器生态中还有非常重要的一环,容器编排和排程,当下最主流的容器编排和排程系统kubernetes,那么kubernetes的安全性是怎么样的呢,其实kubernetes也发生过好多安全问题,包括曾经遭遇的大范围的劫持等。
对于kubernetes的安全应对方案:
对系统使用最小特权。定期更新系统软件来确保已经被官方修复的漏洞得到保护。对其操作日志进行记录和审计,是系统保持在一个被安全监控的环境下执行。权衡好安全和生产力的依托关系,通过调整产品形态把对一下有安全风险的功能关闭,或者使用方式替代使用。使用安全埠进行通讯等。三、OPPO容器安全实践
整个容器的生命周期,包括了从映象构建到编排分发,从容器建立到执行、销毁这一系列阶段,因此我们需要从容器生命周期全阶段进行安全加固和保护。
在映象的生成阶段:从映象构建到把映象推送到注册服务器,映象构建中需要根据业务情况来定制安全构建策略,遵从映象的安全构建规范,例如建立专门用在容器的使用者来启动容器内业务程序、使用可信映象、涉密资讯不储存在Dockerfile、在Dockerfile中使用copy而不是add等等;那么在注册服务器,映象仓库中会进行映象的深度扫描、签名验证等以防止恶意映象流入生产环境的映象仓库,同时需要对映象仓库界面进行加固和映象操作日志进行审计以防止映象仓库系统的入侵攻击和被恶意修改。
编排分发阶段:编排系统同样需要做安全基线审查扫描,提供有效的安全策略配置,编排系统kubernetes的界面层安全加固,这是由kubenetes本身所提供的一系列机制来实现丛集安全控制,其中包括API Server的认证授权、准入控制机制以及保护敏感资讯的securet机制等。同时在编排系统也需要做好日志审计,以便于风险问题的预警分析和溯源。
容器映象的传输:在传输途径中需要使用https进行加密传输,以防止中间人攻击篡改映象。
映象的执行:映象最终是需要流转到主机来真正使用,由Docker守护程式根据映象建立容器执行,那么在主机层的映象审计和回扫都是很关键的,同时也需要对映象进行深度分析、映象的合规基线扫描,来检测在主机侧是否有恶意映象。
3.1 映象安全构建
安全构建,是在业务侧进行,我们需要给业务侧提供映象的安全构建规范,业务方严格强流程按照安全构建规范完成构建。
主要是为了达到以下几个目的:
有可信的安全的基础映象,可以由运维或者基础映象团队统一提供安全基础映象;映象内业务许可权最小化,依赖资源最小化,例如使用专用的容器执行账号来启动业务程序而非root使用者,移除不必要的许可权如setuid/setgid等系统呼叫能力防止提权攻击;尽量减少映象中外部资源的使用;包括使用COPY替代ADD,因为ADD可以通过外部链接来载入资源,不在Dockerfile中单独使用更新命令等等;3.2 映象仓库加固
映象仓库的架构中,一般仓库API不要直接对外提供服务,可以通过增加一个中间代理层proxy来负责所有访问对接,不论是在开发环境构建映象还是扫描引擎对映象进行安全扫描,还是产环境对容器进行编排部署都通过proxy进行来做映象的操作审计,客户端认证、授权等操作。
中间层的作用主要包括:
映象的提交审计;传输加密;客户端认证、授权;扫描引擎和映象仓库的扫描对接;对映象仓库服务器IP做访问控制,界面恶意呼叫拦截等安全加固。映象仓库上可以给它进行角色上的许可权认证,比如不同角色分配不同许可权,像开发、扫描和生产环境上分别配置不同的角色和配置不同许可权,对业务进行划分,不同业务使用时也有不同的许可权,可以设定黑白名单进行访问控制,日志操作审计,在操纵流程中包括上传、下载及所有操作。
3.3 映象深度扫描
把映象从映象仓库拉取下来,对映象的Dockerfile做指令分析,当然映象里面并没有直接携带Dockerfile档案,而是对其产生的history指令进行分析扫描,检测其是否有不合规指令,包括基础映象进行分析,账号许可权分析,ADD指令分析,内容信任分析,setuid/setgid等合规检查。
映象是由各个层叠加而成,在history指令分析以后,我们需要对其各个层进行拆解,对每一个层级进行深度扫描分析;拆解以后,会对所有档案进行恶意特征扫描,包括从公司内部收集和沉淀的恶意版本特征库,cve漏洞库,黑白名单等进行版本特征扫描。
在版本特征扫描之后,会进入到深度扫描部分,包括webshell的深度扫描,例如使用yara规则,语法分析,大资料机器学习,模糊hash检测等;恶意elf档案的深度扫描,同样的,elf的扫描也有相应的yara规则,黑白名单,符号表分析,模糊hash,病毒、木马特征库检测;敏感资讯检测,分析映象各层中的档案,检视里面是否存在敏感资讯,比如说是映象里面写的有各类账号密码(如mysql/redis),我们会对其进行统一分析扫描,用于保护密码泄露,及早发现和预警。现在各类敏感资讯泄露的事件层出不穷,敏感资讯泄露也是我们非常关注的一个层面。这个就是整体的深度映象扫描流程。
刚才我们介绍的是单个映象的扫描全流程,整个映象仓库应该如何去扫描?OPPO当前的使用者体量也是非常庞大,有超过两亿+的使用者,业务体系也非常庞大,像浏览器,资讯流,内容分发等互联网业务非常丰富,现在微服务的架构大行其道,成千上万的映象该如何组织,如何扫描,这是非常值得我们深度思考的问题,从映象构建到映象管理都是非常具有挑战性的。
从实践来看,映象的组织一般划分三大层次:
由运维提供的基础映象层,该层映象只提供系统基础能力,必要的通用工具,执行时库;基础元件层,基础元件层会对各业务提供基础元件,包括相关的业务通用库档案等等,提供相关共性业务所需要的通用能力;业务服务层,这个层面的映象是完全业务化的,不同的业务有不同的映象,一个业务有多个映象;并且这个三个层次一般都有继承关系,基础元件层会继承自运维提供的base映象,业务会继承基础映象;3.4 主机安全加固
除了映象的安全扫描,主机层也需要对Docker进行安全加固,包括两个层面:
核心层面的加固:使用apparmor/selinux等配置精细的安全策略,针对程序级的通讯访问许可权做限制,seccomp:(secure computing mode),是一种核心特性,可用于限制程序能够呼叫的系统呼叫范围,从而减少核心的攻击面,用于构建沙箱;capability,使用者许可权的能力限制,把相同的使用者划分为不同的各个组,可以给每个组赋予的系统呼叫能力不一样,例如系统超级许可权使用者root,可以把它划分成多个组,每个组给做一些不同的能力削减,同样是root使用者所能操作的能力是不一样的,从而达到许可权的精细化管理。使用者层加固:尽可能的缩小容器使用者的许可权,限制挂载敏感目录,磁盘单独分割槽用于执行容器,主机安全的基线配置规范,Docker守护程序的日志和相关配置目录进行操作审计等这些层面来加强对主机的安全加固。
3.5 容器日志收集
主机日志审计,需要有一套高效日志收集系统,统一日志规范,在主机上有统一的日志收集容器,不同的业务容器的日志统一收集传送到大资料平台,进行恶意日志分析,包括使用日志规则库进行恶意日志扫描,对恶意样本日志进行训练,使用机器学习方式做补充识别等业界主流日志分析方式。分析到异常日志对接到统一的安全预警平台进行容器安全预警。
3.6 流量分析
网络流量安全:Docker daemon会帮容器在主机上建立一个网桥Docker0用于容器间的通讯,因此我们在主机上做流量分析时需要同时Docker0和eth0(当然这里的名字需要根据具体的主机配置来定)确保同主机和跨主机的各容器之间的流量都能被分析到;流量分析还有一种方式,交换机旁路映象分析,这种方式的优点是不影响主机的计算力,可以分析到容器跨主机之间的通讯,但是不能分析同主机的容器流量,也无法检测和防御同主机的容器之间Ddos攻击。
流量分析主要是检测容器间的恶意访问,包括恶意域名检测,网址检测,入侵检测,病毒检测,内容审计等,同时会做到协议还原,档案内容还原等,包括像主流的协议,TCP/UDP/DNS/HTTP/MYSQL/REDIS等等。同时在网络层进行网络安全配置规范化,例如只对映必要埠到主机,特权埠禁止对映,不共享主机网络的namespace等。在主机上做TC,traffic control,防止容器间的Ddos行为;
3.7 对容器程序的监控
获取容器的程序列表,把容器ID和其相关程序对映起来;在主机层监控异常程序,发现有异常程序,例如容器中的反弹shell,确定其所属容器并预警;对敏感目录的挂载进行档案监控,发现有异常操作进行预警;
除了做程序监控外,程序的审计呼叫也非常关键,包括网络是否有外联网络联到恶意的地址或域名,Exec函式族审计,还有域名解析审计。Docker的关键命令程式进行监控,需要监控Docker目录下像Docker-runc、Dockerd、Docker的程式有没有被篡改,需要进行监控和预警保护。
3.8 主机入侵检测与Docker的结合
主机入侵检测中,首先需要把程序和容器ID、映象ID都关联起来,对程序和相关的webshell/恶意二进位制档案进行疑似恶意分析,对于疑似的恶意档案提交到后台进行yara,符号表,特征库,ssdeep的模糊hash等方面的深度分析从而形成检测结果。在这过程中也会遇到比较大的挑战,例如webshell扫描,扫描过程中容器启停问题,业务混布,档案多而且混杂,在基线扫描方面也需要考虑的针对容器自身的安全基线和安全策略的扫描。
这是oppo在入侵检测方面覆盖到Docker的检测实践:第一个是检测到容器中的一个反弹shell的问题;第二个是容器外部挂载的一个目录中发现了webhsell;第三个则是在容器执行中发现的一个恶意二进位制的后门。
四、容器生态的安全展望
总体来说容器的安全方面包括:
容器的安全运维方案:自动编排,编排系统的安全性,对接到现有业务中,为了相容业务架构,在容器上线的初期有可能会做出调整而破坏一部分安全机制;Docker方案代替传统方案之后对资料的安全审计和秘钥管理也会带来很大的挑战,像容器的漂移性,部分流量并不会过交换机,所以其安全审计方案会变得更加复杂;容器自身的安全机制,包括0day,而且目前容器主要还是依靠主机来提供安全机制,而Docker本身对安全方面所做的较少;对核心的安全机制依赖,目前核心的隔离机制尚不完善,同时核心的安全问题也透露到容器层面;防御与检测方面:容器漂移非常频繁,同时与主机上档案的对映关系较复杂等等,这一些列问题都会给让与检测的带来很大的挑战,而且方案也会更加复杂。说明:以上为OPPO互联网高阶专家刘湛卢在 GOPS 2019 · 深圳站的演讲。