问题的引入

在不具备其他特权的情况下,以容器化的方式实现对容器行为的监控,需要把agent放在容器或Pod内部。从这一思路出发,主要需解决三个问题:

  1. 如何把探针优雅地放进去?
  2. 探针能拿到什么数据?
  3. 探针自身的安全性如何?

如何把探针优雅地放进去?

我们可以提出多种方案,这些方案至少都是可行的:

  1. 在build镜像时放入agent:可以通过CI/CD方式自动化放入。
  2. sidecar共享目录把agent挂载进去:优势在于不改动业务镜像。
  3. 与2类似,agent以sidecar方式跑在同pod不同容器内,共享PID命名空间。

因此问题一较好解决。

探针能拿到什么数据?

  1. 进程一般性数据是可以拿到的(相当于容器内ps aux,可以满足基础的异常检测)。
  2. 进程系统调用数据能否拿到?不好拿到,因为:
    1. ptrace是不被允许的(否则可以用ptrace做,但是给普通容器加上ptrace权限可能导致容器逃逸,而且这样一来agent也算带有特权了)。
    2. 不考虑eBPF、内核tracepoint等(需要特殊权限),那只能从容器内lib库下手,劫持glibc,但这样无法拿到进程不经过glibc直接调用系统调用的情况,而且劫持glibc可能会导致性能相当程度上下降,且对不同库版本的兼容也比较复杂。

综上,可以拿到一些简单的进程数据,满足基本的异常检测需求。

探针自身的安全性如何?

考虑两种情况:

  1. agent为容器内root,攻击者为容器内普通用户(例如通过Web服务攻击获得web shell的情况,可能是低权限的www-data用户)。
  2. agent为容器内root,攻击者也为容器内root。

在第一种情况下,通过合理的权限设置,agent的保密性、完整性和可用性是能够得到保障的。这个场景近似等于传统的“宿主机上root agent监控普通用户进程行为”的情况。

在第二种情况下,agent和潜在攻击者之间是平等的。理论上来说,攻击者能够对agent造成影响,例如kill掉agent,甚至用恶意agent替换正常agent,实现进一步的攻击。

综上,只有在容器内agent为root,业务应用为非root的情况下,采用非特权的方式进行监控是比较合理的,否则将有安全隐患。

总结

只有权限设置为在容器内agent为root、业务应用为非root,且需求只有简单的进程一般性数据收集时,采用“非特权容器方式监控容器行为”的方式才比较可行。

否则,agent的权限需要比攻击者进入容器后可能获得的初始权限大一些,以满足自身安全性监控粒度(系统调用)等方面的需求。

容器异常行为监控场景和SkyWalking的监控场景有些不同,SkyWalking的监控对象是业务程序向上提供的受限服务调用,而容器异常行为监控的监控对象是业务程序进程本身。SkyWalking只需满足监控服务调用的需求,如果攻击者利用有漏洞的服务调用成功入侵容器,他的行为就不再完全处于SkyWalking的监控范围,而是进入了容器异常行为监控范围。

一个折中的思路是,采用最小权限原则,只给agent监控所需的最小权限,不给完全的特权,以取得监控能力和特权需求的平衡。