Docker Registry 枚举与镜像投毒
Docker Registry 默认监听 5000 端口。认证缺失或薄弱时,攻击者不仅能枚举并下载镜像,还能把植入后门的镜像以相同 tag 推回,构成一次供应链投毒:依赖 latest 或固定 tag 自动拉取的部署,会在下次更新时加载恶意镜像。
仅限授权环境
推送恶意镜像会真实污染目标环境,投毒演示只能在授权测试或自有靶场中进行,结束后应清理并恢复。
方法 A:API 枚举
curl http://<target>:5000/v2/_catalog
curl http://<target>:5000/v2/<name>/tags/list
_catalog 列出全部镜像名,tags/list 列出某个镜像的 tag。
方法 B:Basic 认证爆破
hydra -L users.txt -P rockyou.txt <target> http-get "/v2/_catalog:A=BASIC:F=UNAUTHORIZED"
方法 C:镜像层审计
拉取镜像或按 layer 逐层下载后,审计历史层中的内容:
| 审计目标 | 产出 |
|---|---|
| 源码与 .env | 硬编码的 DB 密码 |
| hardening 脚本 | 加固逻辑,投毒时需要绕过或删除 |
| disable_functions 配置 | PHP 执行限制,决定 WebShell 可用函数 |
| 导出目录映射 | 宿主机共享目录位置 |
方法 D:镜像投毒
- 用
FROM <目标镜像>构建继承镜像。 - 删除原镜像中的 hardening 措施,写入 WebShell。
docker push推回相同 tag。- 等待依赖 latest/固定 tag 自动拉取的部署(watchtower 类自动更新或手动更新流程)在下次拉取时加载恶意镜像。
投毒命中后进入容器时,/proc/1/mounts 与 mountinfo 可看到卷映射关系,用于定位宿主共享目录。
复核要点
- 记录投毒前的原始 tag 摘要,便于授权测试后恢复。
- 审计镜像层时优先看最早的历史层,敏感文件常在构建早期写入。
- 确认目标部署的拉取策略是浮动 tag 还是摘要锁定。
防御建议
- Registry 启用强认证并全程 TLS。
- 启用镜像签名(content trust),只部署已签名镜像。
- tag 设置不可变策略,部署用摘要锁定而非浮动 tag。
- 凭据不进入镜像层,构建时改用 secret 管理机制。