2022年KubeCon会议的议题之一:本文在演示环境中执行了所有测试。原文链接:https://sysdig.com/blog/exposed-prometheus-exploit-kubernetes-kubeconeu/
会议速达
暴露在外的 Prometheus
在此向大家科普一下 Prometheus(了解的请跳过):
Prometheus是继Kubernetes之后,第二个从云原生计算基金会(CNCF)毕业的项目。Prometheus是Google监控系统BorgMon类似实现的开源版,整套系统由监控服务、告警服务、时序数据库等几个部分,及周边生态的各种指标收集器(Exporter)组成,是在当下主流的云原生监控告警系统。
在渗透测试过程中,最重要的步骤之一是:收集尽可能多的从目标获得的信息。检查某些内容是否在互联网上公开的最快方法是查询 Google。收集信息的特定查询被称为Google Dorking,在我们的例子中,对于真正暴露的 Prometheus 来说是微不足道的。
查找暴露的 Prometheus 服务器的一种更好的方法是使用搜索引擎。我们使用最常见的来检查我们可以访问多少台服务器:
| 搜索引擎 | 暴露的 Prometheus 服务器数量 |
| ------ | ------ |
| Shodan | 31,679 |
| Censys | 61,854 |
| Fofa | 161,274 |
Prometheus 的出口商和 Kubernetes指纹
Prometheus是Kubernetes 中的监控标准。控制平面的所有 Kubernetes 组件都可以开箱即用地生成 Prometheus 指标,许多 Kubernetes 发行版都默认安装了 Prometheus,包括一系列标准导出器,通常:
- 基础设施和主机指标的节点导出器。
- 用于 Kubernetes 对象状态指标的 KSM 导出器
寻找云提供商
假设www.example.com是一个有用户的网页和一个小的电子商务组成的,在该域下,可以找到一个公开的 Prometheus。您可以做的第一件事是尝试识别托管站点 的云提供商:
您可以使用来自 Node Exporter 的node_dmi_info指标。这个指标提供了有关每个节点的信息:
- 系统供应商:它公开了云供应商的名称。一些示例值可能是“ Amazon EC2”或“ Tencent Cloud.”
- 产品名称:有助于识别云提供商和使用的产品,因为我们可以从 AWS EC2 目录(如“ m5.xlarge”)或其他供应商的产品中找到一些流行的产品名称。
可以通过以太网搜集更多的信息(因为通常,它们是主机识别为物理网络连接的连接,用于连接主机与外界和其他机器。)
node_network_info{device=~'eth.+'}
可以查询出一下信息:
- 每个主机的 IP 地址。
- 设备ID。
- 云提供商的可用区。
- VPC(虚拟私有云)的ID。
举一个查询出来的例子:
address="06:d5:XX:XX:XX:XX"
broadcast="ff:ff:ff:ff:ff:ff"
device="eth0"
instance="172.31.XX.XX:9100"
instance_az="us-west-2a"
instance_id="i-XXXXX"
instance_name="XXX-XXX"
instance_type="c5.xlarge"
instance_vpc="vpc-XXXXXXX"
operstate="up"
探索 pod
这都是关于物理信息的,但是我们如何从网页外部获取到集群中的 pod?这个问题的答案在ingress和services中。
Kubernetes 中 的入口控制器充当反向代理,并允许将 URL 的不同路径重定向到不同的 Kubernetes 服务,这些服务通常充当一组 pod 前面的负载平衡器。来自 KSM的指标kube_ingress_path将为您提供有关集群中入口控制器的 URL 路径和相关服务的信息。
这样,你就可以知道路径/api/users/login到了users-loginnamespace的 Kubernetes 服务api。
负载均衡器服务是一种特殊的 Kubernetes 服务。云提供商使用这些负载均衡器服务将服务公开给外界。例如,当您在 AWS Kubernetes 集群中创建负载均衡器服务时,它会创建一个绑定到该服务的 ELB(弹性负载均衡器)实例。
promQL查询将为您提供有关Kubernetes 集群中所有负载均衡器服务的信息:
kube_service_info * on (service) group_left group by (service,type) (kube_service_spec_type{type="LoadBalancer"})
要继续探索pod的方式:
可以从 KSM的kube_pod_labels 检查指标
这些标签是服务通常用来选择服务请求的 pod 的标签,但不幸的是,在纯 KSM 中没有直接的方法来获取 pod 和服务之间的关联。
如果你足够幸运,集群将安装 OpenCost 导出器
OpenCost 导出器是一个帮助基础设施工程师了解云使用成本的工具。这个导出器会生成一个有趣的度量service_selector_labels,它直接为您提供服务与标签之间的关联,pod 必须成为该特定服务的一部分。
promQL查询将为您提供服务中用于匹配的每个工作负载的标签:
avg by (namespace,label_app,owner_name)(kube_pod_labels{app="cost-model"} * on(namespace,pod) group_left(owner_name) kube_pod_owner{job="kube-state-metrics"})
而另一个将为您提供每个服务用于查找 pod 的标签:
avg by (namespace,label_app, service)(service_selector_labels)
总结: Kubernetes 指纹
目前收集了以下信息:
- 云提供商。
- Kubernetes 控制平面组件版本。
- 从外部到 pod 的网络路径。
- 节点主机名和 IP。
- 操作系统和内核版本。
- 集群命名空间、工作负载和 Pod 的逻辑结构。
- 用于容器的图像,从源存储库到图像标签。
- 集群秘密的注释和名称。
所有这些信息足以对集群进行较好的攻击分析。
无痕查询
我们收集了所有这些信息,很可能,我们为获取它所做的所有查询都没有痕迹。Prometheus 可以注册查询日志,但默认情况下是禁用的。您甚至可以使用此指标检查您的活动是否被记录:
prometheus_engine_query_log_enabled
攻击者思路
在演讲中,我们展示了三个示例,在每个示例中,所利用的工具和服务都不同。重要的是我们已经知道入口点在哪里。
泄露敏感数据
在第一种情况下,暴露的应用程序运行在 Kubernetes 集群上,攻击者可以在未经授权的情况下访问数据。
首先:攻击者可以尝试是否可通过正常的渗透测试技术进行获取,例如:SQL注入
如果不成功,还可以尝试其他的方式:
- 攻击者可以检查容器是否具有易受攻击的依赖项,或者使用的图像是否可以被利用,然后查看组件或节点本身是否可以利用。
- 通用CVE漏洞等
若以上都失败了,但是Prometheus 暴露了攻击者访问的镜像和注册表(存在两种情况),还可以尝试:
加密采矿
在这种情况下,这是过去几年与云时代最相关的场景之一,攻击者希望访问部署应用程序或 Kubernetes 集群的云帐户。攻击者可以采取两条路径:
路径比较长的方式是识别一个通过 Ingress-controller 暴露的应用程序,该应用程序可以通过 HTTP 轻松利用已知漏洞,并在容器内获取远程代码执行。例如:臭名昭著的log4shell
一旦攻击者可以访问容器,他们甚至不需要收集有关集群或节点的更多信息,因为 Prometheus 也暴露了这些信息。由此,我们可以直接利用另一个漏洞逃到容器中并获得对节点的完全访问权限,而无需使用更多工具或扫描,从而避开了典型的防御方法。
如下图攻击者已经完全控制了节点,他们将能够部署容器来运行加密矿工,或者在配置文件或环境变量中找到云凭证以获得初始访问权限。
勒索软件
Kubernetes 中的勒索软件并不典型,但并非不可能。场景与上一个类似。我们需要获得写访问权,为此,我们需要在命名空间之间跳转或移动。
在这种情况下,我们找到另一个具有不同漏洞的应用程序Spring Cloud,但目的相同:在容器内获取 shell。
一旦进入,我们就知道 Kubernetes 组件是一个旧的易受攻击的版本,我们可以利用它来访问 etcd,并由此获得对命名空间的完全访问权限。
结论
防御方式: