lxcfs 的场景和手法应该是目前业界 HIDS 较少进行覆盖的,我们目前也未在真实的攻防场景中遇到 lxcfs 所导致的容器逃逸利用,学习到这个有趣的场景主要还是来自于 @lazydog 师傅在开源社区和私聊里的分享,他在自己的实际蓝军工作中遇到了 lxcfs 的场景,并调研文档和资料构建了一套相应的容器逃逸思路;由此可见,这个场景和手法在实际的攻防演练中也是非常有价值的。
lxcfs: https://linuxcontainers.org/lxcfs/
假设业务使用 lxcfs 加强业务容器在 /proc/ 目录下的虚拟化,以此为前提,我们构建出这样的 demo pod:
并使用 lxcfs /data/test/lxcfs/
修改了 data 目录下的权限。若蓝军通过渗透控制的是该容器实例,则就可以通过下述的手法达到逃逸访问宿主机文件的目的,这里简要描述一下关键的流程和原理。
(1)首先在容器内,蓝军需要判断业务是否使用了 lxcfs,在 mount 信息里面可以进行简单判断,当然容器不一定包含 mount 命令,也可以使用 cat /proc/1/mountinfo 获取
(2)此时容器内会出现一个新的虚拟路径:
(3)更有趣的是,该路径下会绑定当前容器的 devices subsystem cgroup 进入容器内,且在容器内有权限对该 devices subsystem 进行修改。
使用 echo a > devices.allow 可以修改当前容器的设备访问权限,致使我们在容器内可以访问所有类型的设备。
(4)如果跟进过 CVE-2020-8557 这个具有 Kubernetes 特色的拒绝服务漏洞的话,应该知道
/etc/hosts, /dev/termination-log,/etc/resolv.conf, /etc/hostname 这四个容器内文件是由默认从宿主机挂载进容器的,所以在他们的挂载信息内很容易能获取到主设备号 ID。
(5)我们可以使用 mknod 创建相应的设备文件目录并使用 debugfs 进行访问,此时我们就有了读写宿主机任意文件的权限。
这个手法和利用方式不仅可以作用于 lxcfs 的问题,即使没有安装和使用 lxcfs,当容器为 privileged、sys_admin 等特殊配置时,可以使用相同的手法进行逃逸。我们曾经多次使用类似的手法逃逸 privileged、sys_admin 的场景 (在容器内 CAPABILITIES sys_admin 其实是 privileged 的子集),相较之下会更加隐蔽。
当然自动化的工具可以帮我们更好的利用这个漏洞并且考虑容器内的更多情况,这里自动化 EXP 可以使用 CDK 工具 (该工具由笔者 neargle 和 CDXY 师傅一同研发和维护,并正在持续迭代中):
https://github.com/cdk-team/CDK/wiki/Exploit:-lxcfs-rw
逃逸章节所使用的技巧很多都在 CDK 里有自动化的集成和实现。