方圆 盛剑桥 张亮 丁鑫
摘要:容器提供了一种逻辑打包机制,以这种机制打包的应用可以脱离其实际运行的环境。利用这种脱离,不管目标环境是私有数据中心、公有云,还是开发者的个人笔记本电脑,都可以轻松、一致地部署基于容器的应用。随着容器技术的应用,容器内的安全性也同样面临着威胁。而不管是什么样的攻击方式最终都需要以程序的方式来执行黑客的攻击手段。进程的生成由Linux 内核接管,目前没有对外放出进程生成管理的接口,而如果以内核级代码进行生成管理,若出一点意外将导致整个系统崩溃,无法使用。该研究是基于容器运行的机制并结合Linux系统的特性,在应用层接管进程的生成管理,并对恶意进程的生成进行阻断生成。
关键词:容器;容器安全;进程阻断
中图分类号:TP393 文献标识码:A
文章编号:1009-3044(2021)28-0012-05
在云原生技术的应用广泛下,容器技术也得到了极大的推广。越来越多的公司把服务从本地迁到云上,服务也越来越契合云原生框架。而容器是Paas(Platform-as-a-Service,平台即服务)的一种体现,将所需软件整合成一个应用,一个服务。
容器技术的应用提高了应用程序的可移植性,容器中运行的应用程序可以轻松部署到多个不同的操作系统和硬件平台。与传统或硬件虚拟机环境相比,容器所需的系统资源更少,因为它们不包含操作系统映像。容器中的应用程序无论部署在何处,都会运行相同的应用程序,从而程序的操作得到一致和统一。
容器的虚拟技术应用在带来方便和高效的同时,也成为黑客入侵攻击的高地。
1研究背景
1.1背景分析
徐孝晉[1]等学者通过容器安全性弱点的研究,提到对于容器相比重量级虚拟化技术,容器技术实现的是非硬件级虚拟化;同时它的实现和设计原理是将主机内核进行隔离,相比传统虚拟化技术具有更高的安全性。这主要在于传统的虚拟化技术是围绕虚拟机内核通信处理,阻断主机内核层的通信;由于容器技术没有使用这个限定,容器技术的主机内核呈“曝光式”,因此攻击者也就可以直接对内(主机内核)发动恶意攻击,无须绕行,直接参与主机内核处理的过程便是容器安全性的关键问题所在,隔离性不强是容器安全性弱点的比较根本的原因之一。相对于KVM虚拟化技术,容器中没有虚拟出硬件,而是和系统共用,这也会导致系统的安全问题,同时也是容器的安全问题,并且容器自身的安全问题会感染到系统。
进一步的观察容器各个组件的安全性,由于责任不一样表现出不一样的特点。根据鲁涛等人[2]对容器中的网络、镜像、容器、仓库、容器所依赖的Linux 内核、容器软件本身等六个角度逐类分析其中存在的安全威胁,可以看到容器中主要组件的脆弱性不一样,需要对各个组件有针对性地加固。
还有研究发现有因为容器自身的配置不当而引起的安全问题[3]。例如若以root 权限启动容器,一旦攻击者入侵容器中,即拥有了主机内核的所有功能,容器几乎可以做主机可以做的一切。
1.2容器安全实践
国内外对容器技术安全有着不同的定义和安全标准规范。国外起步比国内早,权威机构美国国家标准与技术研究院发布了《NIST.SP.800—190应用容器安全指南》作为国外容器安全的标准参考,目前国内在容器安全仍处研究和探索阶段,主要还是依靠一些研究机构、云厂商和安全厂商,针对容器的安全性提出各自的防护意见[4]。
Dosec团队提出通过对静态的容器镜像扫描,发现文件漏洞和不安全的配置信息,帮助用户解决传统安全软件无法感知的容器环境问题,同时提供容器进程白名单、文件只读保护和容器逃逸检测功能,能有效防止容器运行时安全风险事件的发生[5]。
绿盟安全厂商提出的容器安全解决方案,包括对容器镜像、仓库进行漏洞扫描,对容器访问控制,容器异常行为检测等实现容器的防护功能[6]。
各个容器安全厂商都针对容器的特性和机制按各自的技术亮点进行安全加固。但其实,容器自身的机制也是可以通过检测流程或者修改配置达到一定的安全加固[7],如:容器镜像安全机制、容器虚拟化安全机制、容器网络安全机制等。
2容器运行时安全问题
容器运行的安全保障主要来自 Linux 自带的三个机制:Seccomp、AppArmor、SELinux。
Seccomp(secure computing mode)于2005年首次被引入 Linux 内核。它是一种用于限制允许应用程序进行的系统调用 API 的机制。通过设置 seccomp 配置文件,让容器在启动的时候加载设置的seccomp 配置。配置文件内可以设置容器内进程允许和不允许的系统调用API 。容器根据设置配置内容,当容器内的进程使用了配置内不允许的系统调用API 时,seccomp 会主动切断进程调用的系统API,从而达到限制恶意进程的使用非法的问题,但同时缺陷也是很明显。Seccomp 配置应用范围是整个容器而不是单个进程,在限制恶意进程使用系统调用 API,同时也在限制非恶意进程使用系统调用 API,没办法在 Seccomp 里面做恶意与非恶意的区别。并且根据恶意风险不断的增强,seccomp 也需要更新配置文件,但是seccomp 不允许运行着的容器动态加载seccomp 配置文件,只能通过把容器停下,修改完配置文件再重新加载。
AppArmor(Application Armor)是可以在 Linux 内核部中启用的少数Linux安全模块(LSM)之一。在AppArmor中,可以将配置文件与可执行文件关联,从而根据功能和文件访问权限确定允许该文件执行的操作。AppArmor和其他的LSM实施强行访问控制,而强行访问控制由管理员设置。一旦设置成功,其他用户将无权修改该控制或将其传递给另一个用户。在某种意义上,如果自己账户拥有文件,则可以授予其他用户对该文件的访问权限(除非此文件被强制访问控制所覆盖),或者可以将其设置为不可通过自己的用户账户写,以防止自己无意中更改。使用强制性访问控制使管理员可以更细地控制其系统上可能发生的情况,而这是单个用户无法覆盖的方式。
SELinux(Security-Enhanced Linux)是Read Hat开发的另一种LSM,但是大多数人认为它起源于美国国家安全局的项目。SELinux可以限制进程与文件和其他进程的相互作用,并且每个进程都在SELinux的作用域下。SELinux权限和常规的DAC Linux权限之间的主要区别在于:在SELinux中权限与用户身份无关,它们完全由标签描述。也就是说,它们是一起工作的,因此DAC和SELinux都必须允许采取对应设置的措施。但是SE⁃ Linux必须先在计算机上的每个文件上标记其SELinux信息,然后才能执行策略。这些策略可以指示特定域的进程对特定类型的文件具有什么访问权限。实际上,这意味着可以限制应用程序只能访问其自己的文件,并阻止其他任何进程访问这些文件。如果应用程序受到威胁,即使正常的自由访问控制允许它,SELinux也会限制可能影响的文件集。
2.1容器运行的安全风险
2.1.1混乱的容器镜像
容器的运行依赖容器镜像,如果容器镜像从最开始就得不到安全保障,那运行起来的容器就更没有安全保障。现在市面上容器镜像有很多第三方仓库,除了遵守基本的传输协议,容器镜像安全没有一个统一的安全检查标准,更不用说对容器镜像安全的检查,达不到对容器镜像精简、高效、安全的要求。
2.1.2容器运行时资源占用
容器可以通过cgroup机制来控制整个容器的资源使用,但是却没办法知道容器内部具体的资源占用情况。如果一个容器被黑客占据在里面跑挖矿相关的程序,仅从容器外和资源占用情况是无法知道具体容器内被哪个进程占用過高的资源,反复停止、重启容器也无法解决这类问题。
2.1.3容器内运行病毒
黑客入侵容器中一般有两种方式,一种是通过容器与外网之间的连接进入容器内,并留下病毒文件让容器执行。另一种是通过容器镜像,在容器还未真地运行起来就把病毒文件嵌入到镜像内,当容器运行时就会把病毒文件运行起来。不管黑客用哪种方式入侵容器内,当入侵系统后往往会注入更多的工具进行攻击,比如渗透工具或挖矿软件等。而如果开发人员直接在容器中注入镜像外的可执行程序则相当于绕开了镜像安全扫描管控,一定会造成黑客在容器内利用漏洞逃逸,对主机勒索、破坏等恶意行为。
2.1.4容器启动参数
镜像中的entrypoint, cmd, volumes, env, ports, users, workdir参数限定了容器运行的行为,然而这些参数可以在启动镜像时被启动参数所覆盖,这就导致了容器行为无法受控。比如用户可以以bin/bash 启动容器从而进入容器内部shell,或挂载主机上的重要系统文件,从而带来安全隐患和风险。
2.2容器读写
2.2.1文件保护
容器内部中大部分目录都是静态的,包括etc、lib、usr等系统目录。关键的应用目录也应该设置只读保护以防止黑客进行篡改和攻击。
2.2.2容器读写控制
容器本身允许有读写行为的存在。但是如果容器被黑客控制,而容器本身的读写控制也同时下发到容器内,那黑客的恶意病毒文件利用漏洞同样是可以获取对应的读写权限,可以针对容器的敏感数据进行读取,同时可以通过写的权限,破坏容器内部数据的完整性。
2.2.3环境变量加密
容器的环境变量中往往包含密码和敏感信息,而拥有In⁃spect权限的用户可以轻易地查看容器的环境变量从而导致信息的泄露。
3容器运行分析
容器是一种操作系统虚拟化形式。可以使用一个容器运行从小型微服务或软件进程到大型应用程序的所有内容。容器包含所有必要的可执行文件、二进制代码、库和配置文件。但是与服务器或计算机虚拟化方法不同,容器不包含操作系统映像。因此,它们更轻便且可移植,其开销很小。而容器的运行也是依赖主机提供的特征来做的虚拟化。
3.1容器的隔离性
容器建立在两项关键技术之上:Linux Namespace 和Linux Cgroups。
Namespace 创建一个近乎隔离的用户空间,并为应用程序提供系统资源(文件系统、网络栈、进程和用户ID)。Cgroup强制限制硬件资源,如CPU、内存、设备和网络等。在Namespace 的作用下容器内部看到的资源视图是单独属于容器自身,并且隔离出来的资源做的任何操作都不会影响到主机侧。通过Cgroup功能,在主机侧把主机本身的动态硬件资源按一定的用户设置分配给对应的容器,控制容器运行动态资源的上限。在 Linux Namespace 和Linux Cgroups功能下对Linux主机做到静态动态资源的分配和隔离,这并不代表容器本身就是安全的。隔离带来了防护性,但同时也成为黑客的攻击点。
3.2容器运行时安全
容器和VM(Virtual Machine)不同之处在于VM模拟硬件系统,每个VM都可以在独立环境中运行OS,管理程序模拟CPU、内存、存储、网络资源等。容器正好与之反,虽然是一个独立运行环境,但是与主机的任何程序都是共享CPU、内存、存储、网络资源,特别是共享了一个Linux 内核。这也造成了容器相对于主机而言,在运行的攻击面也有所不同,如图1所示。
容器一共有七个攻击面:Linux Kernel、Namespace/Cgroups/ Aufs、Seccomp-bpf、Libs、Language VM、User Code、Container engine。
3.2.1 Linux 内核漏洞
容器的内核与宿主内核共享,使用Namespace 与Cgroups这两项技术,使容器内的资源与宿主机隔离,所以Linux 内核产生的漏洞会导致容器逃逸。容器逃逸和内核提权只有细微的差别,需要突破namespace 的限制。在容器内运行程序,收集有帮助的信息,然后触发漏洞去执行特权代码,达到揽权的效果。而在容器内一旦拿到最高的权限,namespace 本身的限制是没有意义的,同宿主侧一样可以随意操作获取任何信息,如图2 所示。
3.2.2不安全的部署配置
在实际中,我们经常会遇到这种状况:不同的业务会根据自身业务需求提供一套自己的配置,而这套配置并未得到有效的管控审计,使得内部环境变得复杂多样,无形之中又增加了很多风险点。最常见的包括:
(1)特权容器或者以root 权限运行容器;
(2)不合理的Capability 配置(权限过大的Capability)。
3.2.3容器内部攻击
不管容器内以什么样的方式被入侵,所有的行为都是依靠程序作为媒介来运行其中的行为逻辑。那么只要对程序的行为进行监控,只要发现有危险的行为就中断程序的运行。
结合容器本身的功能定义,一般只会运行指定的一个业务逻辑程序,不会再刻意加载其它的程序。只要对容器内部做程序加载监控,阻断非指定程序的加载,就能避免恶意程序在容器内部被加载运行,从而避免了被攻击的可能。
4应用层进程生成阻断分析
容器本质是 Linux 下的特殊进程,与应用层的进程共享 Linux 内核。而在容器内生成进程的流程跟Linux应用层生成进程流程是一样的,只是最终应用的环境是在容器内。
4.1进程生成基本流程
Linux 系统创建进程使用 fork()、vfork()、clone()和 exec()。 fork()、vfork()、clone()在当前进程的环境下,再创建出一个新的进程运行环境,也就是子进程,并且子进程会有自己的pid,ppid与父进程区分开;而此时的进程是一个空的状态,也就只有一个进程环境,并没有进程运行的业务逻辑代码。这三个函数接口是应用层封闭的内核创建进程的功能,而这三个函数接口最终都会进到内核中调用_do_fork()来创建进程,而这三个函数接口的区别也只是对应的flag 不同。如图3所示。
exec()用于读取可执行文件并载入上面新生成的进程空间内执行可执行文件内的业务逻辑代码;一般称之为 exec 函数族,有一系列的exec 开头的函数接口,比如:execl(),execve()等。 Exec()系列函数与fork()、vfork()、clone()函数接口一起使用,生成一个完整、独立的进程。而他们时序关系如图4所示。
4.2进程阻断原理&Linux 系统调用Hook技术
根据3.1里面的进程生成原理,把一个可执行文件创造成执行的进程需要两个步骤:
步骤1:使用fork()、vfork()、clone()中的一个函数生成全新的进程运行环境。
步骤2:使用exec()系列函数加载可执行文件。
而在步骤1 中,只是单纯地生成程序运行环境,跟实际的业务逻辑没有连接关系,并且没有任何特征可以表明生成的程序运行环境是做什么用的。而在步骤2中使用exec()系列函数是会传入需要执行的对应业务逻辑代码的地址;以此逻辑代码地址找到对应的业务逻辑并做判断,再让exec()系列函数的调用失败,就可以做到不让对应的可执行文件运行起来。而exec ()系统函数都是对系统调用中的execve()函数做的封闭,最终都是调用的系统调用execve();使用Linux Hook技术替换成带检测进程特征的函数,就能对进程的生成做干预。
系统调用(syscall)是一个通用的概念,它既包括应用层系统函数库的调用,也包括内核层系统提供的syscall_table提供的系统api。Hook技术是一个相对较宽的话题,因为操作系统从ring3到ring0是分层次的结构,在每一个层次上都可以进行相应的Hook,它们使用的技术方法以及取得的效果也是不尽相同的。而在容器内,本身就只有应用层的内容也就是ring3层的环境视图,所以只能在ring3层做Hook处理,来实现系统调用的监控功能。
4.3 ring3 Hook技术之动态连接so 函数劫持
LD_PRELOAD hook 技术属于 so 依赖劫持技术的一种实现,若要讨论这种技术的技术原理先来看一下linux操作系统加载so 的底层原理,包括Linux 系统在内的很多开源系统都是基于glibc的,动态链接的ELF可执行文件在启动时同时会启动动态链接器(/lib/ld-linux.so.X),程序所依赖的共享对象全部由动态链接器负责装载和初始化,所以这里所谓的共享库的查找过程本质上就是动态链接器(/lib/ld-linux.so.X)对共享库路径的搜索过程。
4.3.1/etc/ld.so.cache共享库搜索
Linux为了加速LD_PRELOAD 的搜索过程,在系统中建立了一个ldconfig程序,这个程序负责将共享库下的各个共享库维护一个SO-NAME(一一对应的符号链接),这样每个共享库的 SO-NAME就能够指向正确的共享库文件。将全部SO-NAME 收集起来集中放到/etc/ld.so.cache文件里面,并建立一个 SO- NAME 的缓存。当动态链接器要查找共享库时,它可以直接从/ etc/ld.so.cache里面查找。所以,如果我们在系统指定的共享库目录下添加、删除或更新任何一个共享库,或者我们更改了/ etc/ld.so.conf、/etc/ld.preload的配置,都应该運行一次ldconfig这个程序,以便更新 SO-NAME 和/etc/ld.so.cache,很多软件包的安装程序在结束共享库安装以后都会调用ldconfig
4.3.2/etc/ld.so.preload配置搜索
Linux 动态共享库加载器根据/etc/ld.so.preload文件中的配置顺序进行逐行广度搜索,而该配置文件中保存了需要搜索的共享库路径。
4.3.3环境变量搜索
在/etc/environment 文件内存放着当前程序运行环境的默认的全部环境变量值。而其中LD_LIBRARY_PATH 项根据指定的动态库搜索路径,Linux动态共享库加载器会根据该选项内的值按顺序进行搜索。
4.3.4 ELF文件中的配置信息搜索
任何一个动态链接的模块所依赖的模块路径保存在“.dy⁃namic”段中,由DT_NEED 类型的项表示,动态链接器会按照这个路径去查找DT_RPATH 所指定的路径,编译目标代码时,可以对gcc加入链接参数“-Wl,-rpath”指定动态库搜索路径。
可以看到,LD_PRELOAD 是Linux 系统中启动新进程首先要加载 so 的搜索路径,可以影响程序的运行时的链接(Run⁃ time linker),它允许你定义在程序运行前“优先加载”的动态链接库。只要在通过 LD_PRELOAD 加载的.so 中编写需要 hook 的同名函数,根据Linux对外部动态共享库的符号引入全局符号表的处理,后引入的符号会被省略,即系统原始的.so(/lib64/ libc.so.6)中的符号会被省略。
4.4绕过基于Linux消息队列通信的Hook模块
消息队列提供了一种在两个不相关的进程之间传递数据的相当简单且有效的方法,但是对于消息队列的使用,很容易产生几点安全风险:
(1)在创建消息队列的时候对message queue 的权限控制没有严格控制,让任意非 root 用户也可以从消息队列中读取消息。
(2)在用户态标识消息队列的MSGID很容易通过“ipcs”指令得到,从而攻击者可以获取到和Hook模块相同的消息队列,从中读取消息。
(3)Linux下的消息队列是内核态维护的一个消息队列,每个消息只能被“取出”一次。
(4)当系统中存在多个进程同时在从同一个消息队列中“消费”消息的时候,对消息队列中消息的获取的顺序是一个“竞态条件”,谁先获取到消息取决进程的内核调度优先级以及接收进程自身的接收逻辑,为了提高“竞态条件”的“获胜率”,可以使用nice(-20)提高进程的静态优先级,从而间接影响到内核调度优先级。
综合以上四点就可以得出一种攻击“监控软件”本身的技术方式,如果监控软件使用消息队列进行日志的通信,则攻击者可以通过这种方式强制取出队列中的消息,从而使监控软件的监控失效。
4.5基于ptrace()调试技术进行API Hook
Linux 系统基于调试器(Debuger)思想在用户层提供了一种调试机制ptrace。ptrace是一种父进程可以控制子进程运行,可以检查和改变它的核心image,它主要用于实现断点调试。一个被跟踪的进程运行中,直到发生一个信号。则进程被中止,并且通知其父进程。在进程中止的状态下,进程的内存空间可以被读写。父进程还可以使子进程继续执行,并选择是否忽略引起中止的信号。
利用Linux系统提供的ptrace()技术,可以主动注入方式,注入程序中从而达到Hook程序的API效果。总体思路如下
(1)使用Linux Module、或者LSM挂载点对进程的启动动作进行实时的监控,并通过Ring0-Ring3通信通知到Ring3程序有新进程启动的动作。
(2)用ptrace函数attach 上目标进程。
(3)让目标进程的执行流程跳转到mmap函数来分配一小段内存空间。
(4)把一段机器码拷贝到目标进程中刚分配的内存中去。
(5)最后让目标进程的执行流程跳转到注入的代码执行。
4.6容器内进程阻断方案可行性
从主机侧看容器本身只是一个特殊的进程,而在容器内的进程也只是以容器进程为父进程生成的子系进程。而本质的进程生成的方式和方式,在上面4.1小节已经分析过,只有三种方式;并且最终换可执行加载成可执行程序,也只有唯一一种途径;而该方法也是同样用于容器内部的进程生成,那么在容器内部只要对唯一的途径做拦截,再根据特征值做检测就可以。
只要有一种技术方案可以做到在容器内部对唯一途径的拦截,方案就可以得到实施,也就是对execve()函数做控制监控。
而在4.3小节里面提到的四种动态连接 so 函数劫持Hook 方法,其实除4.3.4小节的方法跟运行程序本身有关,其它方法都和运行的环境变量有关。而容器运行因为命名空间的隔离性,在真实的容器内部是完全独立于主机,那么如果通过修改环境变量的方式来做execve()函数的劫持监控是可以的,并且不会干扰到主机的环境变量。
4.4小节中的对消息队列通信做Hook,在容器内也是可以。同样也是因为容器的命名空间的隔离性,会为容器单独隔离出自己的消息队列用来通信,所以在容器内部对消息队列做通信 Hook也是可行的。
而4.5是使用主机上的ptrace()调用技术做Hook,需要在主机侧对容器内部的进程做实时的监控,但是也只能监控到单个的进程生成,进程的子系进程无法再进行监控。
5容器内进程阻断
根据第4节的分析,在容器内可以应用多个Hook方案。而在4.1小节内分析的进程生成流程,真正能用在容器内Hook到execve()系統调用API 函数的只有:LD_PRELOAD 和ptrace()系统调用功能。
而ptrace()功能的应用是有几个前提条件:
(1)有一个能承载ptrace()功能的运行程序。
(2)知道当前平台系统可执行文件加载函数execve()系统调用对应的映射编号。不同的Linux 内核版本对应的映射可能会不一样,不同的硬件架构平台不一样,对应的映射可能会不一样。
(3)需要承载ptrace()功能的运行程序,要知道被监控程序的运行信息,一般都以pid为监控条件。
但在容器内,因为PID Namepace的进程隔离性,在容器内部获取到的pid并不是真实的进程pid。使用ptrace功能就不能真實地捕获到容器内部的进程运行情况,从而无法监控到内部的系统调用情况,更无法获取到execve()系统调用是否在容器内部被使用。
根据Linux对外部动态共享库的符号引入全局符号表的处理,后引入的符号会被省略,即系统原始的.so(/lib64/libc.so.6)中的符号会被省略。而 LD_PRELOAD 是环境变量,用于动态库的加载,动态库加载的优先级最高,一般情况下,其加载顺序为 LD_PRELOAD > LD_LIBRARY_PATH >/etc/ld.so.cache>/lib>/ usr/lib 。如图5所示。
所以使用LD_PRELOAD 指定自己的so 来“覆盖”系统调用接口,从而可以达到检查系统调用接口,和参数的目的。当接口和参数特征是需要阻断的直接阻断返回。
6结语
云原生是为了能构建一种符合云计算特性的标准来指导云计算应用的编写。而容器作为当前云原生架构下基础组件之一,容器自身的安全直接影响整个云原生架构的安全性。
在享受着容器技术便利性的同时,往往会忽略对容器环境的安全加固。在弹性的容器环境中配置安全监控和防护软件显然是个费时费力且消耗资源的事情。虽然容器自身在设计之初就带有一定的安全考虑因素,再加上容器厂商的二次封闭设计对安全性进行了进一步的加强,但同时也造成了一定量的攻击面的增强。
随着容器虚拟技术的不断发展,容器已经作为微服务、API 服务、业务服务等多种服务的载体,并成为保护服务的最后一道安全屏障。不管是对容器自身运行的保障,还是对容器内的业务的管理,容器被攻击的风险都是不能忽略的。
本次研究利用容器的重要特性“容器的行为都是事先预定且固化的”,那么任何超出预定范围内的行为都代表着异常和攻击。充分利用这个特性作为容器恶意攻击的特点。而所有的攻击行为都需要应用程序做行为承接点才能实施;而容器本身只是Linux 系统下的一个特殊进程,只要是进程就一定要遵守Linux进程的生成流程和机制。Linux 的系统调用接口作为内核层与应用层之间的“桥梁”,而对应的接口库的加载优先级是存放在LD_PRELOAD 内。通过修改优先级来优先加载进程生成过滤策略,从而达到在应用层阻断恶意进程的生成。参考文献:
[1]徐孝晋,伍泽军,邓文杰,等. 基于开源平台的docker 安全性分析 [C]//2019电力行业信息化年会论文集. 无锡 , 2019:175-178.
[2]鲁涛, 陈杰,史军.Docker安全性研究[J].计算机技术与发展, 2018,28(6):115-120.
[3]胡俊,李漫.容器安全解决方案探讨与研究[J].网络空间安全, 2018,9(12):105-113.
[4]刘晓毅,王进,冯中华,等.容器云安全风险分析及防护体系设计[J].通信技术,2020,53(12):3065-3071.
[5] DoSec安全团队.Docker容器最佳安全实践白皮书[R].中国: DoSec,2018.
[6]绿盟星云实验室.绿盟科技容器安全技术报告[R].中国:绿盟科技,2018.
[7]陈伟,涂俊亮.Docker容器安全的分析研究[J].通信技术,2020, 53(12):3072-3077.
【通联编辑:代影】