通过安装日志超越Kubernetes中的Pod

注意事项 佩雷夫 :本说明由DevSecOps公司Aqua Security的一位IT安全研究员撰写。 她很好地说明了Kubernetes配置中的细微之处,在为生产环境中的群集提供服务时要牢记这一点非常重要。 当然,如果您考虑他们的安全...



Kubernetes由许多组件组成,有时以某种方式将它们组合会导致意想不到的结果。 在本文中,我将展示以root用户特权启动的pod和节点的已挂载/var/log目录如何向有权访问其日志用户打开整个主机文件系统的内容 。 我们还将讨论该问题的解决方案。

Kubernetes如何查看日志


您是否想知道kubectl logs <pod_name>如何从pod中提取日志? 谁负责从容器中收集日志? 以及它们如何进入您的计算机?

下图说明了该过程:



Kubelet在主机的/var/log目录内创建一个结构,该结构表示主机上的Pod。 我们的0.log的目录中有一个文件0.log (1),但实际上,它是指向/var/lib/docker/containers的容器日志的符号链接。 这一切都是从主机的角度来看的。

Kubelet打开端点/logs/ (2),该端点/logs/ (2)仅与目录(3)中的HTTP文件服务器一起使用,从而使日志可用于来自API服务器的请求。

现在想象一下,我们部署的pod安装在/var/log 。 这样的Pod可以访问主机上的所有日志文件。 尽管这本身就是一个潜在的问题,但我们可以采取下一个逻辑步骤。 如果我们用符号链接替换0.log到...,例如/etc/shadow怎么办?

 │ ├── var │ ├── logs │ │ ├── pods │ │ │ ├── default_mypod_e7869b14-abca-11e8-9888-42010a8e020e │ │ │ │ ├── mypod │ │ │ │ │ ├── 0.log -> /etc/shadow │ │ │ │ │ │ 

现在,尝试使用客户端计算机上的kubectl logs下载日志,我们得到:

 $ kubectl logs mypod failed to get parse function: unsupported log format: "root:*:18033:0:99999:7:::\n" 

Kubelet跟随该链接并读取其指向的文件的内容(可以是节点上的任何文件)。

由于期望使用JSON,因此kubectl在第一行之后崩溃了,但是,通过运行带有–-tail=-<line_number>的命令,我们可以轻松读取shadow文件的特定行。

太神奇了 由于kubelet遵循符号链接,因此只需在pod内部创建符号链接,就可以使用其root特权来读取节点上的任何文件。

从吊舱逃脱


让我们走得更远。 我们知道在Kubernetes中启动Pod时会在其中安装ServiceAccount令牌。 因此,如果服务帐户允许访问日志,则我们可以直接访问节点上的kubelet和root特权。

我写了一个概念证明(POC)来证明这种攻击媒介:

  • 用挂载点/var/log部署pod;
  • 创建到主机根目录的符号链接;
  • 读取主机上用户的ssh私钥。

以下视频显示了在pod内运行的两个特殊命令:

  • lsh == ls (在主机文件系统上);
  • cath == cat (在主机文件系统上)。

注意事项 佩雷夫 :不幸的是,尽管我们已经解决了这个问题,但是他们并没有解决从集线器中插入来的内容的问题,因此我们不得不使用上面的简单链接将视频“嵌入”。

可以在相应的GitHub存储库中找到此POC涉及的所有文件。 还有另一个POC脚本,可以自动从主机文件系统收集私钥和ServiceAccount令牌。

挂载目录可能很危险


那么,这是一个漏洞还是一种不好的做法?

/var/log hostPathhostPath部署pod的情况很少(还有其他方法可以滥用在pod中装载主机密钥目录)。 但是,即使您知道mount /var/log是一个可疑的做法,您也可能没想到它会让您如此轻松地接管节点。

发布之前,我们联系了Kubernetes安全团队,以了解他们是否认为这是一个漏洞。 他们得出结论,这是装载具有写权限的私有主机目录的可悲结果:充分记录了所涉及的风险。 但是,此漏洞很容易利用。 世界上有许多使用此安装架的项目 。 如果使用的是这些项目之一,请记住,您的部署将容易受到这种劫持主机的方式的攻击。

该方法已经在Kubernetes 1.15和1.13上进行了测试,但是很可能会影响其他版本。

消除


仅当pod以root身份运行时,这种“转义”才有可能。 通常应避免这种情况 。 Aqua CSP允许您以最小的努力来设置策略,以防止容器在根目录下运行或仅向确实需要根目录的特定映像组授予权限。

另一种方法是不简单地在/var/log部署具有具有写许可权的hostPath 。 此方法不是默认设置,也不是一种常见做法,因此有必要自觉地确定它(但是,可能性仍然存在)。 但是如何检查?

我们在kube-hunter中添加了一个新脚本(hunter)-一种用于测试Kubernetes的轻量级开源工具-该工具可在集群中检查具有此类危险挂载点的Pod。 注意 :Kube-hunter出现在我们最近发布的有关K8s安全实用程序的评论中。)

Aqua用户可以通过使用运行时策略来防止他们挂载特定的卷,从而保护自己免受这种风险:



注意事项 佩雷夫 :使用Pod安全策略 ,即AllowedHostPaths可以解决部分问题。 但是,这也不是防止符号链接的保护措施。 最后,正如评论所建议的,我们可以简单地将启动限制为根,再次由PSP指导。

总结


Kubernetes是一个复杂的系统,在安全设置上有很多细微之处,对于普通甚至有经验的用户而言,并不总是很明显。 在本文中,我展示了在某些情况下无辜的日志记录如何导致潜在的漏洞。 在大多数情况下,这是不可能的,但是Kubernetes为用户提供了更大的行动自由,这可能会影响安全性。 重要的是要牢记这一点并实施适当的控制以防止此类错误。

译者的PS


另请参阅我们的博客:

Source: https://habr.com/ru/post/zh-CN466625/


All Articles