容器安全:非根用户容器与准入控制器实践
1. 非根用户容器概述
在容器部署中,一个常见的安全建议是不使用根用户来运行容器。尽管容器经过了精心封装,但本质上它们只是在主机上运行的进程,并应用了沙箱技术(如 Linux cgroups 和命名空间)。如果容器默认以根用户运行,那么它实际上会以根用户身份在节点上运行,只是处于沙箱环境中。这种配置存在一个问题,即虽然沙箱可以防止进程获得根访问权限,但如果底层 Linux 容器化技术存在“容器逃逸”漏洞,沙箱内的容器进程可能会获得与运行用户相同的权限。如果容器以根用户运行,容器逃逸将导致节点获得完全的根访问权限,这是非常危险的。
Docker 默认以根用户运行所有进程,这意味着任何容器逃逸漏洞都可能带来安全问题。虽然这类漏洞相对较少,但为了遵循“深度防御”的安全原则,最好采取防范措施。深度防御意味着即使容器隔离在应用程序被攻破时能保护主机,理想情况下还应有更多的防御层,以防这层保护被突破。在这种情况下,深度防御意味着以非根用户运行容器,这样即使攻击者攻破容器并利用 Linux 中的容器逃逸漏洞,他们也不会在节点上获得提升的权限,而是需要串联另一个漏洞来提升权限,从而形成三层防御(应用程序、Linux 容器化和 Linux 用户权限)。
Docker 在构建容器时默认使用根用户,这是为了方便开发者。以根用户身份在容器中操作很方便,因为可以使用特权端口(编号低于 1024 的端口,如默认的 HTTP 端口 80),并且无需处理文件夹权限问题。然而,使用非根用户构建和运行容器可能会引入一些需要解决的错误。但如果从一开始就采用这一原则,在出现问题时解决起来可能并不困难,而且还能为系统增加一层防御。