3.3.1 镜像漏洞利用
镜像漏洞利用指的是镜像本身存在漏洞时,使用镜像创建并运行的容器也通常会存在相同漏洞,攻击者利用镜像中存在的漏洞去攻击容器,往往具有事半功倍的效果。
例如,Alpine是一个轻量化的Linux发行版,基于musl libc和busybox构建而成。由于其体积较小(成稿时最新的镜像只有5.57MB),因此以Alpine为基础镜像构建软件是非常流行的。但Alpine镜像曾曝出一个漏洞:CVE-2019-5021。在3.3~3.9版本的Alpine镜像中,root用户密码被设置为空,攻击者可能在攻入容器后借此提升到容器内部root权限。
这个漏洞看起来很简单,但是CVSS 3.0评分高达9.8分。我们拉取一个3.3版本的镜像,然后构建容器并检查一下密码信息文件“/etc/shadow”,如图3-5所示,可见shadow文件记录的root密码的确为空。
图3-5 容器内的/etc/shadow文件
官方对此的回应[1]是,Alpine镜像使用busybox作为核心工具链,通过/etc/securetty文件限制了可以登入root用户的tty设备。除非是用户主动安装shadow和linux-pam来代替默认工具链,否则这个漏洞并不好利用。
但是,安全防护注重全面性,具有明显的短板效应。假如用户真的出于某种需求替换了默认工具链呢?那么进入容器的攻击者借助此漏洞就能直接获得容器内部root权限了。
我们模拟一下这个场景。基于3.5版本的Alpine创建一个镜像,添加一个普通用户non_root,并安装shadow[2]:
FROM alpine:3.5 RUN apk add --no-cache shadow RUN adduser -S non_root USER non_root
执行如下命令构建镜像:
docker build --network=host -t alpine:cve-2019-5021
然后运行一个容器,尝试执行su切换为root,切换成功,如图3-6所示。
图3-6 容器内提升权限为root
整个过程非常简单。在现实中,如果用户使用了旧版本的Alpine,没有及时更新,同时安装了shadow,一旦攻击者利用Web服务等获得了一个容器内的低权限shell,就可以凭借此漏洞直接提升为容器内root权限。利用过程如此简单,造成危害又如此严重,大概就是这个空密码问题被分配CVE编号成为漏洞,并获得如此高威胁评分的原因吧。
[1] https://alpinelinux.org/posts/Docker-image-vulnerability-CVE-2019-5021.html。
[2] 随书代码仓库路径:https://github.com/brant-ruan/cloud-native-security-book/tree/main/code/0303- 供应链攻击/01-CVE-2019-5021-alpine。