CVE-2019-16884:apparmor绕过
前置知识
apparmor
apparmor 可以让管理员通过程序的配置文件限制程序的功能,其本身作为一个内核模块集成在 Linux 内核中(可能发现 lsmod 里面并没有 apparmor,这是因为 lsmod 展示的是所有动态加载的内核模块,通过 ls /sys/module/ 就可以看到所有的内核模块包括系统中内置的),因此其通过内核提供强访问控制。
漏洞原理
- 这个漏洞的根源在
libcontainer/rootfs_linux.go文件中的checkMountDestination函数。 这个函数的本意是防止容器将目录挂载到/proc上,以确保后续写入/proc/self/attr/exec的操作能真正加载 AppArmor 策略到内核。但函数实现中存在一个逻辑缺陷——它检查了挂载到/proc子目录的情况,却遗漏了对挂载目标刚好是/proc本身的检查*。更糟糕的是,这个错误在测试代码中也被复制了(把==写成了!=),导致测试阶段都没能发现
假设我们可以成功挂载/proc卷,那么我们就可以自定义/proc里面的内容,这样我们就可以使得/proc/self/attr/exec可控,因此就会使得相关的apparmor安全策略无法加载
漏洞复现
确认 AppArmor 已启用
创建一个规则来阻止对 /flag 文件的读取

创建一个flag文件

使用 apparmor_parser 工具加载我们刚刚创建的规则

启动一个正常的容器,并应用 no_flag 安全策略,然后尝试读取 /flag 文件

创建恶意镜像所需的目录结构和一些“诱饵”文件。关键在于创建一个虚假的 /proc 目录

创建一个 Dockerfile,用于构建恶意镜像

这个 Dockerfile 的关键是 VOLUME /proc 指令,它声明将容器的 /proc 目录挂载为一个卷。
使用刚才编写的 Dockerfile 构建镜像,并命名为 apparmor-bypass

最后,运行这个恶意镜像,并尝试读取被保护的 /flag 文件
由于环境问题,没能实现,但思路是没问题的TvT