Azure Kubernetes Service (AKS) Threat Hunting
随着更多企业从在专用虚拟机上运行工作负载转向使用Kubernetes等工作负载编排器在容器内运行它们,对手对这些目标越来越感兴趣。此外,Kubernetes为管理工作负载提供的好处也扩展到了对手。随着对手利用Kubernetes运行其工作负载,他们对这些平台如何工作以及如何被利用的理解也在增加。
考虑到这一点,本文的目标是帮助您了解组成集群的组件,如何获得对其活动的可见性,分享一些基于容器的威胁狩猎策略,以及如何首先保护您的集群免受攻击。
目录
- 为什么AKS是对手的好目标
- 了解您的AKS集群架构
- 集群活动的可见性
- 狩猎假设和查询
- 保护您的集群
为什么AKS是攻击者的好目标?
攻击者可能对针对在AKS上运行的工作负载感兴趣的几个原因。
首先,Kubernetes是一个分布式系统,允许我们抽象掉运行复杂工作负载的复杂性。这意味着在Kubernetes集群上运行的应用程序本身往往是分布式应用程序,与存储账户、密钥库和其他云资源有连接。访问这些资源所需的秘密对集群可用,并可以允许攻击者转向您Microsoft订阅中的其他资源。
其次,AKS是一个现成的“给我们您的代码,我们将运行它”的API。这正是大多数威胁行为者在获得对目标的初始访问后所寻找的,因为它消除了他们寻找执行恶意软件负载手段的需要。他们可以简单地将代码容器化,并告诉Kubernetes API服务器将其与现有的容器化工作负载一起运行。
最后,随着越来越多的公司依赖容器化工作负载编排器进行主流工作负载,它们作为攻击目标变得越来越普遍。基于容器的平台的相关性不断扩大,反映在可用云和第三方服务数量的增加上,如Azure Service Fabric,现在除了传统方式外,还提供将代码作为容器托管。
了解您的AKS集群架构
本节的目标是揭开创建Kubernetes集群时默认部署的Azure和Kubernetes对象的神秘面纱,以便您可以更好地保护它们。本节假设您熟悉基本的Kubernetes架构和组件。
在任何Kubernetes集群中进行威胁狩猎时,需要注意三个高价值资产:
Kubernetes API服务器 这是集中式API,处理集群工作节点发出的所有请求,并驻留在集群的控制平面中。这是防御者可以监控的关键节点,因为它提供了集群活动的单一门户。有权访问授权用户或服务账户令牌的对手可以与Kubernetes API服务器通信,读取有关集群的敏感信息,如集群配置、工作负载和秘密的信息,以及更改集群的能力。
Etcd 此组件也位于控制平面中,是一个键值存储,包含集群的所有状态配置。它是集群状态的最终真相来源,并包含有价值的数据,如云元数据和凭据。如果对手具有对etcd的写访问权限,他们可以修改集群的状态,同时绕过Kubernetes API服务器。具有读访问权限,对手可以访问集群的所有秘密和配置。您可以将其视为具有对Kubernetes API服务器的集群管理员读权限。
kubelet 每个工作节点都有一个kubelet,它与容器运行时通信以管理节点上pod和容器的生命周期。它不断轮询Kubernetes API服务器,以确保这些pod的当前状态与所需状态匹配。如果需要更新或创建新pod,它将指示容器运行时配置pod命名空间,然后启动容器进程。鉴于kubelet和containerd容器运行时的开源性质,它们容易受到资源充足的攻击者的供应链攻击。要实现这一点,攻击者需要成功发布kubelet或containerd的更新,并将该更新应用于现有的Kubernetes集群。对kubelet和containerd的这种后门访问将为攻击者提供与访问集群工作节点相同级别的访问权限。
当您部署AKS集群时,集群的控制平面由Azure管理,这意味着您无法访问控制平面内的组件。然而,这并不免除Kubernetes控制平面日志对我们的威胁狩猎至关重要,正如我们将在博客文章后面看到的那样。
AKS资源提供者(RP)和资源组
当您部署AKS集群时,您创建两个资源组:
第一个是您部署AKS集群时选择或创建的资源组,它包含代表您在Azure中的逻辑集群的Microsoft.ContainerService/managedCluster资源。
第二个资源组包含运行工作负载所需的所有基础设施,并具有MC__命名方案。这包括Kubernetes工作节点、虚拟网络、存储和托管服务标识(MSIs)。此资源组通常也称为“托管资源组”,指的是此资源组的内容由AKS资源提供者管理。
简单来说,AKS资源提供者是Azure控制平面REST API,允许客户创建、升级、缩放、配置和删除集群,以及轻松获取kubectl的凭据。在幕后,它还负责集群升级、修复不健康的集群以及维护您的Azure管理的控制平面服务。
代理节点池
这是虚拟机规模集(VMSS)或部署以运行容器化工作负载的Kubernetes节点。如果集群中有多个节点池,则可能存在多个VMSS,如果您使用虚拟节点,您可能还会看到Azure容器实例。
命名空间
命名空间是Kubernetes在集群内逻辑隔离不同工作负载的方式。创建AKS集群时,会为您创建以下命名空间:
- default - 这是默认创建Kubernetes对象的地方,也是未提供命名空间时kubectl查询的命名空间。
- kube-node-lease - 包含Kubernetes用于跟踪集群节点状态的节点租约对象。
- kube-public - 所有集群用户(包括未经身份验证的用户)都可读此命名空间,且AKS未使用。
- kube-system - 包含由Kubernetes和AKS本身创建的对象,以提供核心集群功能。
部署
Kubernetes部署是一组一个或多个相同的Pod和ReplicaSet。默认情况下,以下部署随您的AKS集群创建:
- coredns和coredns-autoscaler – 为集群工作负载提供DNS解析和服务发现,允许您在集群内访问http://myservice.mynamespace.cluster.local。
- metrics-server - 用于向Kubernetes提供资源利用率的指标服务器。
- omsagent-rs - 这是AKS的监控代理,用于提供容器见解。这是一个可选功能,除非您启用了容器见解,否则不会出现。
- tunnelfront – 在Azure管理的控制平面虚拟网络和承载AKS工作负载的客户管理数据平面之间提供反向SSH隧道连接。需要此隧道连接以允许Kubernetes控制平面在集群的数据平面上执行某些操作,如端口转发和日志收集。这正在被弃用,并将被konnectivity-agent取代。
- konnectivity-agent – 这将取代tunnelfront作为Kubernetes API服务器用于访问集群工作节点的机制。此pod包含Konnectivity服务器与之通信以向kubelet发送请求和执行命令的代理。您可以在此处了解有关Konnectivity实现的更多信息。
与这些部署相关的pod以及其他DaemonSet可以在下面看到,并部署到kube-system命名空间。
集群的可见性
部署AKS集群时,您可以选择创建Log Analytics工作区。如果部署,Azure将在此处发送与集群相关的日志。Log Analytics工作区还提供了一个界面,供您使用Kusto查询语言(KQL)查询这些日志。
默认日志可用性
默认情况下,Azure不为您的集群启用控制平面日志,但使您可以轻松配置所需的控制平面可见性级别。这是由于AKS控制平面可能生成的大量日志。控制平面日志包括对Kubernetes API服务器的请求,没有它们,监控对集群进行的重大配置更改和风险元数据请求可能非常困难。要为集群配置控制平面日志记录,请按照以下步骤操作:
- 在Azure门户中转到您的AKS集群,并在左侧边栏中找到诊断设置条目。
- 选择+添加诊断设置。
- 选择您感兴趣的记录日志类别(有关这些日志的更多信息见下文),然后在目标详细信息下选择发送到Log Analytics工作区,选择您之前创建的工作区。给它一个描述性名称并单击保存。
警告 AKS是一项托管服务,根据设计,包括Kubernetes API服务器在内的Kubernetes控制平面由Azure管理。这意味着您无法应用自己的审核策略来微调记录到kube-audit的事件(默认应用的审核策略可以在此处找到)。如果您担心成本,请确保对集群应用适当的诊断设置并在订阅上配置计费警报。
- kube-apiserver日志记录Kubernetes API服务器的操作活动。这些不包括对Kubernetes API服务器本身的请求,因此对于故障排除集群操作最有用,而不是作为安全日志。对于安全调查,kube-audit日志最有用。
- kube-audit日志提供集群中采取的所有操作的时间顺序序列,对于安全审核非常出色。它是kube-apiserver日志中包含信息的超集,包括在Kubernetes控制平面内触发的操作。这包括对Kubernetes API服务器进行的所有请求,以部署资源和执行命令(创建事件)、检索资源(列表和获取事件)、更新资源(发布和修补事件)以及删除资源(删除事件)。
- kube-audit-admin日志是kube-audit日志的子集,通过排除所有获取和列表审核事件来减少收集的日志量。这意味着通过获取和列表事件进行的枚举和侦察活动将不会被记录,但修改集群状态的请求将被记录(修补、发布、创建和删除事件)。
- guard日志提供Azure Active Directory(AAD)授权日志,如果您的集群与AAD集成或配置为使用Kubernetes RBAC(基于角色的访问控制)。
您可以在此处找到有关AKS上可用不同日志类型的更多信息,以及集群本身上日志文件的位置在此处。
Linux主机级审核日志记录
与上述日志源不同,在集群上启用auditd日志记录使您能够了解AKS工作节点和容器内核级活动,例如程序执行和命令行活动。它是高度可配置的,如果您运行多租户集群,则特别有价值。您可以在此处找到有关如何设置它的更多信息。
集群的安全警报
此外,您还可以配置Microsoft Defender for Containers以接收在集群上识别的可疑活动的安全警报,包括控制平面活动以及容器化工作负载本身。完整的警报列表可以在此处找到。本博客文章中提出的狩猎假设和查询假设您未启用此功能。
狩猎和攻击场景
潜在攻击路径
在高层次上,Kubernetes中有四种不同的攻击场景:
- 逃逸到运行工作负载的底层虚拟机规模集工作节点上,并执行主机级攻击。
- 使用Kubernetes API服务器在集群内横向移动 - 通过寻找其他K8s服务账户令牌慢慢升级您的权限。在许多情况下,这里的目标是部署额外的集群工作负载。
- 使用托管服务标识和可用于集群中pod和工作节点的秘密在Azure内横向移动。
- 规避K8s API服务器 - 如果您获得对控制平面节点的访问权限,您可以采取各种攻击路径,例如部署影子API服务器,以规避监控并绕过K8s API服务器实施的任何身份验证和授权控制。在AKS的情况下,攻击者应该不可能做到这一点,因为控制平面基础设施由Azure管理,并设计用于防止此类攻击。
下面的狩猎查询和假设涵盖了其中一些场景,重点是对手在获得对运行在集群上的pod的访问权限后可能如何行为。
狩猎假设和查询
在威胁狩猎操作期间,目标不是枚举对手可能做的每一个战术、技术和程序。这种方法通常会导致您在弱信号中分散注意力,并失去对关键攻击转折点的关注。相反,目标是识别对手在您的服务中需要跨越的关键节点,并监控这些行为。
为了支持您的AKS威胁狩猎,我们为您提供了一系列威胁狩猎假设和查询,向您展示通过集群日志记录可以识别哪种活动,并给您一些寻找什么的想法。在创建您自己的狩猎假设时,请考虑攻击者需要执行哪些操作来攻击您的工作负载。
注意 所有这些查询都作为您狩猎和调查的起点。它们包含可以扩展和调整以更适用于您自己环境的变量。狩猎查询要求您至少配置了kube-audit-admin日志,并且如果您想狩猎包括容器逃逸在内的主机级活动,则启用Linux主机级审核日志记录。
初始访问
狩猎假设
提示 在攻击者可以在容器上执行命令以寻找秘密或逃逸到底层主机之前,他们必须首先exec到容器中。
此假设使我们能够在攻击的关键节点寻找对手。使用kubectl exec在容器上执行命令对攻击者有几个好处:
- 正在运行的命令很少被记录,并且在pod定义中不可见,使防御者更难观察活动。
- 使他们能够访问该pod的服务账户令牌。默认情况下,每个pod都挂载了一个服务账户,并且服务账户的权限由角色绑定决定。
此查询识别使用kubectl对容器进行的任何命令执行请求。此查询是一个简单的堆栈计数,查看哪些容器由哪个经过身份验证的用户使用什么IP地址和用户代理执行了命令。
|
|
以下查询通过计算在基线期间和您进行威胁狩猎的活动期间执行容器命令执行的用户和服务账户之间的归一化偏移,提供对命令执行活动的更深入分析。查询显示执行容器命令执行的用户或服务账户与基线活动有20%不同的命令执行活动。您可以通过增加或减少Delta变量来调整查询的敏感性,分别显示更少或更多的结果。
|
|
权限提升
容器逃逸
默认情况下,容器使用Linux内核的cgroups和命名空间功能与主机系统的网络和内存地址空间隔离。如果pod是“特权”的,其容器基本上在没有这些隔离构造的情况下运行,这使容器具有与直接在主机上运行的进程相同的访问权限。
这可以给攻击者几个优势:
访问底层工作节点上的秘密:
- 这包括配置用于访问集群控制平面的秘密和证书,位于/etc/kubernetes和/etc/kubernetes/pki中。这包括kubelet用于向Kubernetes API服务器进行身份验证的客户端证书。
- /etc/kubernetes/azure.json包含具有对MC_资源组内资源的读访问权限的MSI或服务主体。
- 访问工作VM上的kubeconfig文件,其中包含kubelet的服务账户令牌。此服务账户令牌具有请求所有集群秘密的权限(取决于您的RBAC配置)。
- /var/lib/kubelet/pods包含为节点上所有pod挂载为秘密卷挂载的所有秘密。默认情况下,这些秘密由容器运行时挂载到容器上的tmpfs卷中(可在/run/secrets访问)。这些秘密不写入磁盘,但投影到底层主机上的/var/lib/kubelet/pods目录中。这是需要的,以便kubelet可以在pod的生命周期内管理秘密(创建和更新)。
它允许攻击者直接在底层主机上运行应用程序。通过这种方式,工作负载不是作为集群内的pod运行,而是直接在