文章来源:opensource 作者:Daniel J Walsh

Containers do not contain

我听到和读到很多人把docker假设为一个沙箱的应用程序——这意味着他们可以通过Docker以root用户随机跑一些应用程序在他们的系统,他们相信Dokcer contianer将会真实地保护他们的主机。

  • 我听到有人说Docker container中运行一些进程和在VMs/KVM一样安全。
  • 我知道有些人随机的下载一些Docker镜像并运行在他们的主机中
  • 我甚至见过PaaS服务器允许用户上传自己的镜像在一个多租户的系统(multi-tenant system)上运行
  • 我有一个同事说:“Docker就是从网上下载代码并以root用户运行”

停止假设Docker和linux kernel会在恶意软件中保护你。

你关心吗?

如果你没有运行Docker在一个多租户的系统和你有一个好的安全实践在container里面运行服务,你可能不需要担心。但可以说拥有特权的进程运行在container里面和运行在container外面是没有区别的。

一些人错误的认为container是一个更好和更快的运行虚拟机的方式,从安全的角度上来说,容器是很弱的,我将会在稍后的文中介绍到。

如果你相信我,Docker container应该被对待为“容器服务”——意味着对待container运行的Apache服务和在系统中运行Apache服务一样,这意味着你要做到一下几点:

  • 尽可能快的关闭特权
  • 尽可能的不用root去运行你的服务
  • 在容器里面对待root权限和在容器外对待root权限一样

目前,我们正在告诉人们使用通用的标准处理容器里面的特权进程和就像在容器外处理特权进程一样。

不要随便的在你的系统中运行一个未知的Docker镜像,在很多方面我看到Docker container的革命就像1999年linux的革命一样,当管理员听到一个新的酷的linux服务,他们会:

  • 在internet上查找这个包,例如在rpmfind.net或者任意的网站。
  • 下载这个程序到系统中
  • 通过RPM或者make install安装
  • 用特权运行它

What could go wrong?

两个星期之后管理员听到了关于zlib的漏洞并要找出它,同时希望和祷告这并不是漏洞,他们的软件是脆弱的。

所以,只运行可信方的容器,如果你的代码并非来自内部和信任的第三方,别依赖容器技术去保护你的主机。

So what is the problem? Why don’t containers contain?

最大的问题是任何东西在linux是没有命名空间的,当前,Docker使用五个namespace去改变系统的进程视图:Process、NetWork、Mount、Hostname、Shared Memory。

虽然这些给予用户的的安全级别并不是最全面的,像KVM,在KVM环境中进程在虚拟机里面是不会和主机的kernel直接交互的,他们也不会访问任何像/sys,和/sys/fs,/proc/*,等kernel的文件系统。

Device node是和VMs的kernel交互而不是主机的kernel,因此为了提升拥有整个VMs的特权,这个进程必须有subvirt在虚拟机的内核中,而且要找到HyperVisor的漏洞,突破SELinux的控制,这些对与VM来说是非常密封的,直到最后才能攻击主机的内核。

而当你运行一个container的时候,它就已经和你的kernel在交互了。

没有namespace的主要kernel子系统有:

  • SELinux
  • Cgroup
  • 在/sys下的文件系统
  • /proc/sys, /proc/sysrq-trigger, /proc/irq, /proc/bus

没有命名空间的Device有:

  • /dev/mem
  • /dev/sd* 文件系统devices
  • kernel Modules

如果你用一个特权进程去和上面其中一个进行通信或者攻击,你就可以拥有这个系统。