Docker Remote API TLS 认证_docker远程接口未授权访问漏洞怎么解决

漏洞描述:

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加密再进行通信。

如果情况有变,如:

  1. 通信不出网如何进行逃逸利用

可尝试写入sshkey,由于挂载的是/mnt目录,所以写入宿主机的目录就是/mnt/root/.ssh/

  1. 目标中不存在可利用镜像(目标出网)

可手动在docker hub中拉取一个镜像然后再进行操作

如拉取nginx用于操作:docker -H tcp://目标IP:2375 pull nginx:1.21.5

  1. 目标中不存在可利用镜像(目标不出网)

本地打包镜像:

本地起镜像并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 镜像,后续利用步骤同上

  1. 无法获取到有效的交互式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)怎么解决-****博客

上一篇:Elmo驱动器上位机软件的简单配置


下一篇:【CSS in Depth 2 精译_056】8.4 CSS 的新特性——原生嵌套(Nesting)+ 8.5 本章小结