上一篇文章介绍了在VPC横向移动,在这一篇将分析 Kubernetes 和云域之间横向移动的潜在攻击向量,并检查它们在主要云厂商之间的差异。最后,给出一些最佳实践来帮助企业减少或防止关键的横向流动风险。
尽管有不少案例记录,威胁组织(如 TeamTNT)使用 pod 逃逸并从实例元数据服务端点获取访问令牌,但许多黑客并不熟悉从 Kubernetes 到云的横向移动技术。传统方法都是单独针对 Kubernetes 或云域,但从不考虑它们之间的关系。
例如,Wiz 研究团队调查了大量使用托管 Kubernetes 集群的云环境,发现大约 40% 的环境至少有一个这样的pod,在它的容器映像存储着和IAM/AAD云身份相关的明文长期密钥。
从托管 Kubernetes 集群向云的横向移动攻击,黑客使用多种技术, 包括实例元数据服务、IAM/AAD 身份、长期云密钥和 pod 逃逸。
托管 K8s 服务为集群中的每个工作节点分配预定义的角色、服务帐户或身份,并具有必要的权限,使 kubelet 守护进程能够调用 云厂商 API 来执行与集群稳定性相关的管理任务(例如自动缩放). 因此,工作节点可以查询 IMDS 端点获取实例元数据,这个元数据通常在 IPv4 本地链路地址 169.254.169.254, 来确定预定义的身份。
因此,黑客入侵了托管 K8s 集群中公开的容器, 通常会查询 IMDS 端点, 获取工作节点的 IAM/AAD 身份凭证,并利用它们访问集群外的云资源,例如存储桶和数据库。然而,此类攻击的渗透半径取决于每个云厂商中角色的配置:
EKS亚马逊云 需要将多个内置托管策略赋予到 EKS 集群中工作节点的角色。这三个策略是AmazonEKSWorkerNodePolicy, AmazonEC2ContainerRegistryReadOnly, 和 AmazonEKS_CNI_Policyor或自定IPv6。每个策略关联的默认权限会有单独的攻击向量。
AmazonEKSWorkerNodePolicy:允许工作节点描述节点加入集群所需的 EC2 资源。黑客可以列出帐户中的所有 EC2 实例并获取敏感数据(如安全组、AMI、IP 地址、VPC 和任何关联的子网或路由表), 并滥用该信息来映射整个云网络。
# AmazonEKSWorkerNodePolicy{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "ec2:DescribeInstances", "ec2:DescribeInstanceTypes", "ec2:DescribeRouteTables", "ec2:DescribeSecurityGroups", "ec2:DescribeSubnets", "ec2:DescribeVolumes", "ec2:DescribeVolumesModifications", "ec2:DescribeVpcs", "eks:DescribeCluster" ], "Resource": "*" } ]}
AmazonEC2ContainerRegistryReadOnly:允许工作节点对容器注册表进行完全读取访问,来进行镜像拉取。黑客可以利用它来枚举容器注册表及其中镜像,这些镜像可能包含云密钥和密码等敏感信息。此外,他们可以调用ecr:DescribeImageScanFindings接口来识别镜像的关键漏洞。
# AmazonEC2ContainerRegistryReadOnly{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "ecr:GetAuthorizationToken", "ecr:BatchCheckLayerAvailability", "ecr:GetDownloadUrlForLayer", "ecr:GetRepositoryPolicy", "ecr:DescribeRepositories", "ecr:ListImages", "ecr:DescribeImages", "ecr:BatchGetImage", "ecr:GetLifecyclePolicy", "ecr:GetLifecyclePolicyPreview", "ecr:ListTagsForResource", "ecr:DescribeImageScanFindings" ], "Resource": "*" } ]}
AmazonEKS_CNI_Policy:允许 VPC CNI ( amazon-vpc-cni-k8s) 及其修改工作节点 IP 地址配置的权限。黑客可以利用该策略列出活动的 EC2 实例并删除它们的网络接口,从而导致该帐户的集群和实例的 DoS 攻击。
# AmazonEKS_CNI_Policy{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "ec2:AssignPrivateIpAddresses", "ec2:AttachNetworkInterface", "ec2:CreateNetworkInterface", "ec2:DeleteNetworkInterface", "ec2:DescribeInstances", "ec2:DescribeTags", "ec2:DescribeNetworkInterfaces", "ec2:DescribeInstanceTypes", "ec2:DetachNetworkInterface", "ec2:ModifyNetworkInterfaceAttribute", "ec2:UnassignPrivateIpAddresses" ], "Resource": "*" }, { "Effect": "Allow", "Action": [ "ec2:CreateTags" ], "Resource": [ "arn:aws:ec2:*:*:network-interface/*" ] } ]}
GKE谷歌云会自动将计算引擎默认服务帐户赋予到新的工作节点,该帐户具有过于宽松的IAM 基本编辑角色。黑客可以利用此角色访问项目中的密钥、操纵服务帐户,甚至删除运行集群的计算实例。
部署 AKS 群集时,管理入口负载均衡器和文件 CSI 驱动程序等群集资源的提供程序管理标识会自动添加到群集的控制平面。用户或 pod 不能使用此身份。另一方面,工作节点的虚拟机规模集 (VMSS) 可以接受两个身份:系统分配身份和用户分配身份,名为<AKS Cluster Name>-agentpool。前者默认禁用,后者启用但不具有任何作用。因此,即使黑客可以在集群中驻留,查询 IMDS 端点,并采用节点的用户分配托管身份,他们也不会有任何权限。
然而,这些限制取决于用户选择的配置。例如,在 VMSS 上启用系统分配身份并授予其权限将允许黑客采用该身份并使用其特权访问云资源。或者,如果用户将角色分配给节点的用户管理身份,则知道身份 ID 的黑客可以采用该身份并渗透云资源。
为了减轻横向移动的风险,三大云厂商提供一种替代方案,分配IAM/AAD 身份给 K8s pod 服务帐户,而不是给IMDS端点。此功能反映了最小权限原则,因为它限制了对云资源的非必要 Pod 访问;它在 亚马逊云、谷歌云 和 Azure 中分别叫IAM Roles for Service Accounts、Workload Identity或Azure AD workload identity。
尽管这是一种将集群资源与云资源集成的安全方式,但黑客入侵了这种方案下pod, 可能会冒充服务帐户的身份并滥用其访问相关云资源的权限。事实上,Wiz 的研究团队发现,托管 K8s 集群的云环境大约有10%, 至少有一个具有可利用的致命或高危漏洞的公开 pod 和一个具有高特权 IAM/AAD 身份的 K8s 服务帐户。
长期云密钥(例如 Azure 服务主体凭据)通常存储在 K8s 密钥对象中,因此 pod 中运行的程序可以在本地访问它们或通过服务帐户执行任务。
这些云密钥存在问题,因为它们有不确定的保质期:除非手动撤销,否则黑客可以使用窃取的密钥反复冒充关联的 IAM 访问密钥、服务帐户或 AAD 服务主体。例如,黑客入侵了一个公开的容器,它关联的服务帐户可能有对命名空间密钥的完全读取访问权限,他就会列出所有密钥,并调用 K8s API 来提取任何存储敏感数据。如果某个密钥持有强大的凭据,例如有所有者权限的 AAD 服务主体,这可能会导致整个订阅被接管。
黑客可以通过致命的错误配置或漏洞从pod逃逸,进入宿主机,并访问同在宿主机的其它pod。如果 pod 关联了有IAM 身份的服务帐户,黑客可能会冒充这些身份。
然而,从pod 逃逸到宿主机的影响也受到 kubelet 的 RBAC 权限的影响。这些权限因云提供商而异:
尽管权限不同,但在三个云厂商中,kubelet都通过 Kubernetes Rest API(非资源 URL /api/*)拥有对所有集群资源的完全读取访问权限,因此可以抽取到集群的任何密钥,包括 IAM/AAD 身份的明文长期密钥和高权限的 K8s 服务帐户令牌。
此外,AKS kubelet RBAC 权限授予对关键 Kubernetes 对象的写入权限。这允许 kubelet 更新节点并创建或删除在其上运行的 pod。
在有入侵节点和写入权限的情况下,黑客可以创建一个新的 pod,将AAD 用户管理的身份赋予到现有的 K8s 服务帐户,请求 AAD 访问令牌,然后采用该身份。
6 个关键 K8s 到云的最佳实践:
遵守最小特权原则,防止黑客查询 IMDS 端点获取访问令牌。
限制 pod 获取节点的角色访问令牌的第一步是, 为服务帐户启用 IAM 角色 (IRSA),并仅向与 K8s 服务帐户关联的每个角色授予必要的权限。然而,IRSA 不会限制 pod 对节点的 IMDS 端点的网络访问。为了防止 pod 访问端点,它们需要在与节点实例不同的网络命名空间中运行。这可以通过强制执行 IMDSV2、将每个工作节点上的跳数 (TTL) 修改为 1 并禁用pod 属性hostNetwork限制共享网络名称空间。可以在相关工作节点上使用以下 cli 命令执行此操作:
aws ec2 modify-instance-metadata-options –instance-id <value> --http-tokens required –http-put-response-hop-limit 1
如果使用的是 Autopilot 托管集群部署,则无需阻止 IMDS 端点,因为 Autopilot 使用工作节点身份 (WI)。相反,如果要部署标准 GKE 集群,则应手动启用 WI并仅向每个K8s服务帐户关联的 IAM 服务帐户分配所需的权限。赋予具有最小权限的服务帐户(例如Kubernetes 引擎节点服务帐户角色)至关重要,因为 谷歌云 会自动将过于宽松的 IAM 基本编辑器角色的计算引擎默认服务帐户分配给工作节点。
如果集群需要访问 Azure 云工作节点,可以通过启用Azure AD 工作节点身份来限制pod 获取节点托管身份访问令牌。然后,仅向每个K8s服务帐户关联的用户授予最小权限。由于工作节点身份不限制对节点的 IMDS 端点的网络访问,还应该应用 Kubernetes 网络策略来阻止在特定命名空间中运行的 pod 访问元数据:
apiVersion: networking.k8s.io/v1kind: NetworkPolicymetadata: name: deny-metadata-access namespace: examplespec: podSelector: {} policyTypes: - Egress egress: - to: - ipBlock: cidr: 0.0.0.0/0 except: - 169.254.169.254/32
在 Kubernetes 1.25 中,Pod Security Admission (PSA) 正式取代了 Pod Security Policies。PSA 是一个内置的,实现了Pod 安全标准(PSS)安全要求的准入控制器。PSS 定义了三种策略——特权、基线和受限——从最宽松到最严格。PSA 通过操作模式将这些策略应用于特定的名称空间。
强烈建议, 至少对敏感环境(如生产)的命名空间实施基线策略。这将防止最常见的权限升级,并在高权限的错误配置的 pod 中防止逃逸。可以通过运行以下kubectl命令来应用 PSS 策略:
kubectl label –overwrite ns <namespace> pod-security.kubernetes.io/<mode>=<policy-type>
避免将reading secrets,workload creation和 exec into pod 权限授予非管理 K8s 主体。凭借reading secrets权限,入侵 K8s 主体的黑客可以列出命名空间或集群中的密钥并泄露敏感数据。如果 K8s 主体有权创建新的工作节点或到 pod 中执行,黑客可能能够生成新的工作节点或将 shell 放入IAM/AAD 角色、服务帐户或托管身份关联的工作节点中. 然后他们可以获得临时凭证,从而允许他们以 IAM/AAD 身份执行 API。
如果 Kubernetes 工作节点需要访问云服务,请考虑为托管集群实施高度安全的集成标准,例如服务帐户的 IAM 角色 (EKS)、工作节点身份 (GKE) 或 Azure AD 工作节点身份 (AKS)。
公开的有严重漏洞的容器可能会给组织带来重大安全风险,因为它会为黑客提供托管的 K8s 集群的入口。确保持续扫描容器映像并修复公开的容器上的任何严重漏洞。
在 Kubernetes 中,默认情况下 pod 可以自由地相互通信。因此,入侵Web 应用程序提供服务的 pod 可以使黑客将流量定向到集群中的其他 pod。在 pod 级别的网络策略可以控制是否允许基于第二个 pod 的身份、命名空间和 IP 地址范围的入口/出口流量。这有助您隔离 pod,从而限制入侵的范围。