Docker 的镜像并不安全!(2)

使用libtrust下载一个清单经过签名和认证的镜像,就可以触发下面这条不准确的信息(说不准确,是因为事实上它验证的只是清单,并非真正的镜像):

ubuntu:14.04:The image you are pulling has been verified(您所拉取的镜像已经经过验证)

目前只有Docker公司“官方”发布的镜像清单使用了这套签名系统,但是上次我参加Docker的会议讨论时,我所理解的是,Docker公司正计划在未来扩大部署这套系统。他们的目标是以Docker公司为中心,控制一个认证授权机构,对镜像进行签名和(或)客户认证。

我试图从Docker的代码中找到签名秘钥,但是没找到。好像它并不像我们所期望的把密钥嵌在二进制代码中,而是在每次镜像下载前,由Docker守护进程远程获取。这是一个多么糟糕的方案,有无数种攻击手段可能会将可信密钥替换成恶意密钥。这些攻击包括但不限于:CDN供应商出问题、CDN初始密钥出现问题、客户端下载时的中间人攻击等等。

补救

研究结束前,我报告了一些在tarsum系统中发现的问题,但是截至目前我报告的这些问题仍然没有修复。

要改进Docker镜像下载系统的安全问题,我认为应当有以下措施:

摒弃tarsum并且真正对镜像本身进行验证

出于安全原因tarsum应当被摒弃,同时,镜像在完整下载后、其他步骤开始前,就对镜像的加密签名进行验证。

添加权限隔离

镜像的处理过程中涉及到解压缩或解包的步骤必须在隔离的进程(容器?)中进行,即只给予其操作所需的最小权限。任何场景下都不应当使用root运行xz这样的解压缩工具。

替换 libtrust

应当用更新框架(The Update Framework)替换掉libtrust,这是专门设计用来解决软件二进制签名此类实际问题的。其威胁模型非常全方位,能够解决libtrust中未曾考虑到的诸多问题,目前已经有了完整的说明文档。除了已有的Python实现,我已经开始着手用Go语言实现的工作,也欢迎大家的贡献。

作为将更新框架加入Docker的一部分,还应当加入一个本地密钥存储池,将root密钥与registry的地址进行映射,这样用户就可以拥有他们自己的签名密钥,而不必使用Docker公司的了。

我注意到使用非Docker公司官方的第三方仓库往往会是一种非常糟糕的用户体验。Docker也会将第三方的仓库内容降为二等地位来看待,即使不因为技术上的原因。这个问题不仅仅是生态问题,还是一个终端用户的安全问题。针对第三方仓库的全方位、去中心化的安全模型既必须又迫切。我希望Docker公司在重新设计他们的安全模型和镜像认证系统时能采纳这一点。

结论

Docker用户应当意识到负责下载镜像的代码是非常不安全的。用户们应当只下载那些出处没有问题的镜像。目前,这里的“没有问题”并包括Docker公司的“可信(trusted)”镜像,例如官方的Ubuntu和其他基础镜像。

最好的选择就是在本地屏蔽 index.docker.io,然后使用docker load命令在导入Docker之前手动下载镜像并对其进行验证。Red Hat的安全博客有一篇很好的文章,大家可以看看。

感谢Lewis Marshall指出tarsum从未真正验证。

CentOS 6/7系列安装Docker

Docker的搭建Gitlab CI 全过程详解

Docker安装应用(CentOS 6.5_x64)

在 Docker 中使用 MySQL

在Ubuntu Trusty 14.04 (LTS) (64-bit)安装Docker

Docker安装应用(CentOS 6.5_x64)

Ubuntu 14.04安装Docker 

阿里云CentOS 6.5 模板上安装 Docker

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/af3f5363149cf40b307e7a16f32d25f4.html