Abusing Roles/ClusterRoles in Kubernetes
在这里,您可以找到一些潜在危险的角色和ClusterRoles配置。
请记住,您可以使用 kubectl api-resources
获取所有支持的资源
权限提升
在Kubernetes中,提权被称为以不同权限(在Kubernetes集群内或外部云中)获取对不同主体的访问权限的技术。在Kubernetes中,基本上有4种主要技术来提升权限:
能够冒充具有更高权限的其他用户/组/SAs在Kubernetes集群内或外部云中
能够创建/修补/执行Pods,在其中您可以找到或附加具有更高权限的SAs在Kubernetes集群内或外部云中
能够读取秘密,因为SAs令牌存储为秘密
能够从容器中逃逸到节点,在那里您可以窃取节点中运行的容器的所有秘密、节点的凭据以及节点在其运行的云中的权限(如果有的话)
值得一提的第五种技术是能够在Pod中运行端口转发,因为您可能能够访问该Pod中的有趣资源。
访问任何资源或动词(通配符)
通配符 (*) 允许对任何资源使用任何动词。管理员使用它。在ClusterRole中,这意味着攻击者可以滥用集群中的任何命名空间。
使用特定动词访问任何资源
在RBAC中,某些权限存在重大风险:
create
: 允许创建任何集群资源,存在特权升级风险。list
: 允许列出所有资源,可能泄露敏感数据。get
: 允许访问服务账号中的秘密,构成安全威胁。
创建 Pod - 窃取令牌
拥有创建 Pod 权限的攻击者可以将一个特权服务账户附加到 Pod 中,并窃取令牌以冒充该服务账户。有效地提升了权限。
以下是一个示例 Pod,将窃取 bootstrap-signer
服务账户的令牌并将其发送给攻击者:
Pod 创建与逃逸
以下列出了容器可以拥有的所有特权:
特权访问(禁用保护并设置功能)
禁用命名空间 hostIPC 和 hostPid,可帮助提升特权
禁用 hostNetwork 命名空间,使得可以访问窃取节点云特权和更好地访问网络
挂载主机的 / 到容器内部
使用以下命令创建 Pod:
来自这条推文的一句话,并附加一些内容:
现在,您可以逃逸到节点检查后渗透技术中:
隐身
您可能希望更加隐秘,在接下来的页面中,您可以看到如果创建一个仅启用前述模板中提到的某些特权的 pod,您将能够访问什么:
特权 + hostPID
仅特权
hostPath
hostPID
hostNetwork
hostIPC
您可以在 https://github.com/BishopFox/badPods 找到如何创建/滥用先前特权 pod 配置的示例
创建 Pod - 迁移到云
如果您可以创建一个pod(并可选地创建一个服务账户),您可能可以通过将云角色分配给一个 pod 或服务账户然后访问它来在云环境中获得特权。 此外,如果您可以创建一个具有主机网络命名空间的 pod,您可以窃取节点实例的 IAM 角色。
有关更多信息,请查看:
Pod Escape Privileges创建/修补 Deployment、Daemonsets、Statefulsets、Replicationcontrollers、Replicasets、Jobs 和 Cronjobs
可以滥用这些权限来创建一个新的 pod并像前面的示例中那样获得特权。
以下 yaml 创建一个 daemonset 并将 SA 的令牌外泄到 pod 中:
Pods Exec
pods/exec
是 Kubernetes 中用于在 Pod 内部的 shell 中运行命令 的资源。这允许 在容器内运行命令或获取 shell。
因此,可以 进入一个 Pod 并窃取 SA 的令牌,或者进入一个特权 Pod,逃逸到节点,并窃取节点上所有 Pod 的令牌并(滥用)该节点:
端口转发
此权限允许将一个本地端口转发到指定 pod 中的一个端口。这旨在使得能够轻松调试在 pod 中运行的应用程序,但攻击者可能滥用此权限来访问 pod 内部的有趣内容(如数据库)或易受攻击的应用程序(网站?)。
主机可写 /var/log/ 逃逸
正如这项研究所指出的,如果您可以访问或创建一个挂载了主机 /var/log/
目录的 pod,您就可以从容器中逃逸。
这基本上是因为当Kube-API 尝试获取容器的日志(使用 kubectl logs <pod>
)时,它会使用 Kubelet 服务的 /logs/
端点请求 pod 的 0.log
文件。
Kubelet 服务公开了 /logs/
端点,这基本上是暴露了容器的 /var/log
文件系统。
因此,一个具有写入容器 /var/log/ 文件夹权限的攻击者可以利用这种行为方式有两种:
修改其容器的
0.log
文件(通常位于/var/logs/pods/namespace_pod_uid/container/0.log
)为指向/etc/shadow
的符号链接。然后,您就可以执行以下操作来窃取主机的 shadow 文件:
如果攻击者控制任何具有读取
nodes/log
权限的主体,他可以在/host-mounted/var/log/sym
中创建一个符号链接指向/
,当访问https://<gateway>:10250/logs/sym/
时,他将列出主机的根文件系统(更改符号链接可以提供对文件的访问)。
可以在 https://blog.aquasec.com/kubernetes-security-pod-escape-log-mounts 找到一个实验室和自动化利用。
绕过readOnly保护
如果你足够幸运,并且高度特权的能力 CAP_SYS_ADMIN
可用,你可以重新将文件夹挂载为读写:
绕过 hostPath 的 readOnly 保护
如这项研究所述,可以绕过这种保护:
这是为了防止像之前那样的逃逸,而不是使用 hostPath 挂载,而是使用 PersistentVolume 和 PersistentVolumeClaim 来挂载容器中具有可写访问权限的主机文件夹:
冒充特权账户
拥有 用户冒充 权限,攻击者可以冒充一个特权账户。
只需在 kubectl
命令中使用参数 --as=<username>
来冒充一个用户,或者使用 --as-group=<group>
来冒充一个组:
或者使用 REST API:
列出秘密
列出秘密的权限可能允许攻击者实际读取秘密,访问 REST API 端点:
读取秘密 - 暴力破解令牌 ID
尽管拥有具有读取权限的令牌的攻击者需要确切的秘密名称才能使用它,与更广泛的_列出秘密_权限不同,仍然存在漏洞。系统中的默认服务账户可以被枚举,每个账户关联一个秘密。这些秘密具有名称结构:静态前缀后跟一个随机的五字符字母数字令牌(不包括某些字符),根据源代码。
令牌是从一个有限的 27 个字符集(bcdfghjklmnpqrstvwxz2456789
)生成的,而不是完整的字母数字范围。这种限制将总可能组合减少到 14,348,907(27^5)。因此,攻击者可以合理地执行暴力破解攻击来推断令牌,在几小时内可能导致通过访问敏感服务账户而提升权限。
证书签名请求
如果您在资源 certificatesigningrequests
中具有动词 create
(或至少在 certificatesigningrequests/nodeClient
中具有),您可以创建一个新节点的新 CeSR。
根据文档,可以自动批准这些请求,因此在这种情况下,您不需要额外权限。如果没有,您将需要能够批准该请求,这意味着在 certificatesigningrequests/approval
中进行更新,并在 signers
中使用资源名称 <signerNameDomain>/<signerNamePath>
或 <signerNameDomain>/*
进行批准。
一个具有所有所需权限的角色示例是:
所以,随着新节点 CSR 被批准,您可以滥用节点的特殊权限来窃取机密并提升权限。
在这篇文章和这篇中,GKE K8s TLS Bootstrap 配置被配置为自动签名,并被滥用以生成新 K8s 节点的凭据,然后通过窃取机密来提升权限。 如果您拥有提到的权限,您也可以做同样的事情。请注意,第一个示例绕过了阻止新节点访问容器内部机密的错误,因为节点只能访问挂载在其上的容器的机密。
绕过这种方式只需为挂载有有趣机密的容器的节点名称创建节点凭据(但请查看如何在第一篇文章中执行):
AWS EKS aws-auth configmaps
在 EKS 上的 kube-system 命名空间中可以修改 configmaps
的主体(需要在 AWS 中)集群可以通过覆盖 aws-auth configmap 获得集群管理员特权。
所需的动词是 update
和 patch
,或者如果 configmap 尚未创建,则是 create
:
您可以使用 aws-auth
来实现持久性,从而让用户从其他账户访问。
但是,aws --profile other_account eks update-kubeconfig --name <cluster-name>
无法从不同的账户运行。但实际上,如果您将集群的 ARN 放在那里,aws --profile other_account eks get-token --cluster-name arn:aws:eks:us-east-1:123456789098:cluster/Testing
就可以运行。
要使 kubectl
工作,只需确保配置受害者的 kubeconfig,并在 aws exec args 中添加 --profile other_account_role
,这样 kubectl 将使用其他账户配置文件来获取令牌并联系 AWS。
在 GKE 中升级
有两种方法将 K8s 权限分配给 GCP 主体。在任何情况下,主体还需要权限 container.clusters.get
来收集凭据以访问集群,否则您将需要生成自己的 kubectl 配置文件(请参阅下一个链接)。
当与 K8s api 端点通信时,将发送GCP auth 令牌。然后,通过 K8s api 端点,GCP 首先检查主体(通过电子邮件)是否在集群内有任何访问权限,然后再检查它是否通过 GCP IAM 有任何访问权限。 如果任何一个为真,则会响应。如果不是,则会给出一个建议通过 GCP IAM 授予权限的错误。
然后,第一种方法是使用 GCP IAM,K8s 权限具有其等效的 GCP IAM 权限,如果主体具有它,它将能够使用它。
GCP - Container Privesc第二种方法是将 K8s 权限分配给集群内的用户,通过其电子邮件进行标识(包括 GCP 服务帐户)。
创建 serviceaccounts 令牌
可以创建 TokenRequests(serviceaccounts/token
)的主体(来自此处的信息)。
ephemeralcontainers
可以**update
** 或 patch
pods/ephemeralcontainers
的主体可以获得对其他 pod 的代码执行权限,并且可能通过添加具有特权 securityContext 的临时容器来突破到其节点。
ValidatingWebhookConfigurations 或 MutatingWebhookConfigurations
具有 validatingwebhookconfigurations
或 mutatingwebhookconfigurations
上的 create
、update
或 patch
中的任何动词的主体可能能够创建此类 webhookconfigurations,以便升级权限。
有关 mutatingwebhookconfigurations
示例,请查看此文章的此部分。
升级
正如您可以在下一节中阅读的内容:内置特权升级预防,一个主体不能更新或创建角色或集群角色,而不具备这些新权限。除非他对**roles
** 或 clusterroles
具有**escalate
** 动词。
然后,他可以更新/创建具有比他拥有的更好权限的新角色、集群角色。
节点代理
具有访问 nodes/proxy
子资源的主体可以通过 Kubelet API 在 pod 上执行代码(根据此处)。有关 Kubelet 认证的更多信息,请参阅此页面:
您可以在此处找到如何在与 Kubelet API 授权通信时获取 RCE 的示例。
删除 pods + 无法调度的节点
可以删除 pods(pods
资源上的 delete
动词)、或驱逐 pods(pods/eviction
资源上的 create
动词)、或更改 pod 状态(访问 pods/status
)并且可以使其他节点无法调度(访问 nodes/status
)或删除节点(nodes
资源上的 delete
动词)并且对一个 pod 有控制权的主体,可以从其他节点窃取 pods,使它们在受损的节点中执行,攻击者可以从这些 pods 中窃取令牌。
服务状态 (CVE-2020-8554)
可以修改 services/status
的主体可能会将 status.loadBalancer.ingress.ip
字段设置为利用未修复的 CVE-2020-8554,并发起对集群的中间人攻击。对于 CVE-2020-8554 的大多数缓解措施仅防止外部 IP 服务 (根据 此处)。
节点和 Pod 状态
具有对 nodes/status
或 pods/status
的**update
** 或 patch
权限的主体,可以修改标签以影响强制执行的调度约束。
内置特权升级预防
Kubernetes 具有内置机制来防止特权升级。
该系统确保用户无法通过修改角色或角色绑定来提升其特权。即使 RBAC 授权器处于非活动状态,此规则的执行发生在 API 级别,提供了一种保障。
该规则规定,用户只能在拥有角色包含的所有权限的情况下创建或更新角色。此外,用户现有权限的范围必须与其尝试创建或修改的角色的范围相匹配:对于 ClusterRoles,要么是整个集群范围,要么是相同命名空间 (或整个集群) 范围。
前述规则有一个例外。如果主体对**roles
或clusterroles
具有escalate
**动词,他可以增加角色和集群角色的特权,即使他自己没有权限。
获取和修改 RoleBindings/ClusterRoleBindings
显然这种技术以前有效,但根据我的测试,由于前一部分解释的相同原因,它现在不再有效。如果你没有权限,你不能创建/修改一个 rolebinding 来给自己或不同的 SA 一些特权。
创建 Rolebindings 的特权允许用户将角色绑定到服务账户。这种特权可能导致特权升级,因为它允许用户将管理员特权绑定到一个受损的服务账户。
其他攻击
Sidecar 代理应用
默认情况下,Pod 之间的通信没有加密。双向互相认证,Pod 对 Pod。
创建一个 Sidecar 代理应用
创建你的 .yaml
编辑你的 .yaml 文件并添加取消注释的行:
查看代理的日志:
更多信息请访问:https://kubernetes.io/docs/tasks/configure-pod-container/security-context/
恶意准入控制器
一个准入控制器在对象持久化之前拦截对Kubernetes API服务器的请求,但是在请求经过认证 和授权之后。
如果攻击者以某种方式设法注入一个变异准入控制器,他将能够修改已经经过认证的请求。从而有可能提权,并更常见地在集群中持久存在。
示例来自 https://blog.rewanthtammana.com/creating-malicious-admission-controllers:
检查状态以查看是否准备就绪:
然后部署一个新的 Pod:
当您看到 ErrImagePull
错误时,请使用以下任一查询检查镜像名称:
正如您在上面的图片中所看到的,我们尝试运行镜像 nginx
,但最终执行的镜像是 rewanthtammana/malicious-image
。到底发生了什么!!?
技术细节
./deploy.sh
脚本建立了一个变异的 Webhook 准入控制器,根据其配置行修改对 Kubernetes API 的请求,从而影响所观察到的结果:
滥用 Kubernetes 中的角色和集群角色
上面的片段将每个 Pod 中的第一个容器镜像替换为 rewanthtammana/malicious-image
。
OPA Gatekeeper 绕过
Kubernetes - OPA Gatekeeper bypass最佳实践
禁用服务账户令牌的自动挂载
Pods 和服务账户: 默认情况下,Pods 挂载一个服务账户令牌。为了增强安全性,Kubernetes 允许禁用这个自动挂载功能。
如何应用: 在服务账户或从 Kubernetes 版本 1.6 开始的 Pods 配置中设置
automountServiceAccountToken: false
。
在 RoleBindings/ClusterRoleBindings 中限制用户分配
选择性包含: 确保只包含必要的用户在 RoleBindings 或 ClusterRoleBindings 中。定期审计并删除不相关的用户以保持严格的安全性。
命名空间特定角色优于整个集群范围的角色
Roles vs. ClusterRoles: 更倾向于在命名空间特定权限中使用 Roles 和 RoleBindings,而不是应用于整个集群的 ClusterRoles 和 ClusterRoleBindings。这种方法提供了更精细的控制并限制了权限的范围。
使用自动化工具
参考资料
Last updated