Prometheus API大规模暴露在互联网上|包括敏感信息

Prometheus API大规模暴露在互联网上|包括敏感信息

背景

Prometheus是一种开源的、基于指标的事件监控和警报解决方案,适用于云应用程序。它被近 800 家云原生组织使用,包括 Uber、Slack、Robinhood 等。通过从各个端点抓取实时指标,除了观察硬件和软件指标(例如内存使用情况、网络使用情况和软件特定定义的指标(例如,登录尝试失败的次数)之外,Prometheus 还可以轻松观察系统状态, Web应用程序等)。

由于 Prometheus 捕获的数字指标不被视为敏感数据,因此 Prometheus 采取了一种可以理解的策略,避免内置对身份验证和加密等安全功能的支持,以专注于开发与监控相关的功能。不到一年前(2021 年 1 月),在引入传输层安全性 (TLS) 和基本身份验证支持的 2.24.0 版发布时,这种情况发生了变化

Prometheus API大规模暴露在互联网上|包括敏感信息

由于身份验证和加密支持相对较新,许多使用 Prometheus 的组织尚未启用这些功能,因此许多 Prometheus 端点完全暴露在 Internet 上(例如运行早期版本的端点),泄漏指标和标签数据.

Prometheus API大规模暴露在互联网上|包括敏感信息
Prometheus官网截图

那么——这些数据真的像假设的那样不敏感吗?

在这篇博文中,我们将展示对公开可用和不安全的 Prometheus 端点进行大规模未经身份验证的抓取的结果,其中包含许多类型的敏感数据,这些数据通常在开发人员不知情的情况下暴露。除了介绍我们在实际应用程序中发现的最常见的配置问题,我们还演示了开发人员和其他用户如何以更安全的方式部署 Prometheus。

Prometheus架构

下图显示了 Prometheus 架构的简化结构。

Prometheus API大规模暴露在互联网上|包括敏感信息

Prometheus 的检索作业,也称为抓取器,从目标服务中提取数据,将其聚合,然后将其传递到数据库。Prometheus 的 HTTP 服务器通过 API 端点以 JSON 格式或通过端点以可视化 HTML 形式提供这些数据/graph

在最简单的情况下,Prometheus 从static_configsPrometheus 基于 YAML 的配置文件中存在的静态列表(或文件)中获取抓取目标(IP 地址和端口)列表。在更复杂的动态环境中,新实例可能随时出现,使用服务发现机制,该机制提供机器列表来监控并提供有关这些机器如何组织的信息。

抓取目标将其指标作为带有key值记录的文本文件公开,并带有可选的“标签”数据。每条记录都有一个帮助热线,描述度量和类型定义的目的,指导 Prometheus 如何解释值。

# HELP go_info 关于 Go 环境的信息。
# TYPE go_info 仪表
go_info{version="go1.16.7"} 1
# HELP go_memstats_alloc_bytes 已分配且仍在使用的字节数。
# TYPE go_memstats_alloc_bytes 仪表
go_memstats_alloc_bytes 6.9728224e+07
# HELP go_memstats_alloc_bytes_total 分配的总字节数,即使已释放。
# TYPE go_memstats_alloc_bytes_total 计数器

通过使用 Prometheus 对可视化插件(例如 Grafana)的支持,可以根据用户的需求自定义聚合数据的视图(下图示例)。

Prometheus API大规模暴露在互联网上|包括敏感信息

抓取 Prometheus 端点

如前所述,Prometheus 服务在历史上被假定为允许公众访问。这在Robust Perception 博客中有明确说明,官方文档说:

“据推测,不受信任的用户可以访问 Prometheus HTTP 端点和日志。他们可以访问数据库中包含的所有时间序列信息,以及各种操作/调试信息。”

因此,当我们开始寻找公开暴露的 Prometheus 端点时,我们期望它们中的大多数无需身份验证即可在世界范围内访问 – 我们是正确的。

使用ShodanZoomEye等搜索引擎,可以非常轻松地找到数以万计的 Prometheus 端点。我们在 Shodan 中看到的最有效的单一查询是通过 Web UI 的 favicon 查找 Prometheus 端点网页用户界面图标

这个特定的查询 ( http.favicon.hash:-1399433489) 在 Shodan 中返回近 27K 个主机,在 ZoomEye 中返回 43K 个主机。通过在这些暴露的端点上自动迭代,我们已经看到从这个查询返回的端点 100% 具有可公开访问的数据(意味着没有到位的身份验证机制)。

Prometheus API大规模暴露在互联网上|包括敏感信息

没有访问限制可能对指标数据有意义,因为从 DevOps 工程师的角度来看,大多数指标都是有用的数字,但通常对攻击者无用。例如,这些是描述 CPU 负载或发送到服务的请求数量的值:

node_cpu_seconds_total{cpu="0",mode="nice"} 2582.99
node_netstat_Udp_OutDatagrams 2.4580101e+07
node_memory_Cached_bytes 1.293774848e+09

在某些情况下,指标会暴露软件版本和主机名,攻击者可以使用这些信息在利用特定服务器之前进行低灵敏度侦察,或用于横向移动等后渗透利用技术:

Prometheus API大规模暴露在互联网上|包括敏感信息

然而,当代的 Prometheus 端点通常不是静态配置的,而是使用动态服务发现,甚至由云提供商(例如GKE)作为统包解决方案提供。在这些情况下,Prometheus 的部署可能会暴露组织端点的大量操作信息,包括更敏感的信息,我们现在将演示。

敏感操作信息的暴露

让我们回顾一些包含操作信息的真实示例,以更好地了解它们可能泄露哪些敏感信息以及为什么组织应该优先考虑 Prometheus 的安全部署。

我们将按从中抓取信息的端点对信息进行分组:

/api/v1/status/config

config端点返回加载(YAML)配置文件。

该文件还包含目标地址和警报/发现服务以及访问它们所需的凭据。通常,Prometheus 用占位符替换凭据配置配置字段中的密码<secret>(尽管这仍然会泄漏用户名):

Prometheus API大规模暴露在互联网上|包括敏感信息

但是,由于 Prometheus 不会直接监视、删除或以其他方式屏蔽 URL 字符串中提供的用户名和密码,因此这些敏感数据已完全泄露:

Prometheus API大规模暴露在互联网上|包括敏感信息

/api/v1/targets

UI 端点/targets公开属于基础设施的服务,包括它们的角色和标签:

Prometheus API大规模暴露在互联网上|包括敏感信息

API 端点/api/v1/targets(并以可解析的 JSON 格式)显示此信息的深度。除了显示目标机器地址之外,端点还公开目标提供者添加的元数据标签。这些标签旨在包含非敏感值,例如服务器的名称或其描述,但各种云平台可能会自动公开这些标签中的敏感数据,而且通常在开发人员不知情的情况下。

例如,在使用基于 GCE 的服务发现 ( gce_sd_configs) 时,导出的元数据的一部分是带有 SSH 公钥的标签,泄露了用户和机器名称:

Prometheus API大规模暴露在互联网上|包括敏感信息

一个更令人关注的标签是  __meta_gce_metadata_startup_script它包含用于 GCE VM的整个启动脚本。许多开发人员选择在这些脚本中初始化秘密,结果这些凭据被泄露:

Prometheus API大规模暴露在互联网上|包括敏感信息

另一个有问题的 GCE 标签是__meta_gce_metadata_kube_env,它包含 Kubelet 的环境变量,并且可能包含敏感凭据:

Prometheus API大规模暴露在互联网上|包括敏感信息

Kubernetes 服务发现机制 ( kubernetes_sd_configs) 在某些情况下可以直接暴露用户名和密码

Prometheus API大规模暴露在互联网上|包括敏感信息

这种发现机制还暴露了最后应用的配置标签(_meta_kubernetes_pod_annotation_kubectl_kubernetes_io_last_applied_configuration
它也可以通过配置的环境变量泄漏敏感信息:

Prometheus API大规模暴露在互联网上|包括敏感信息

/api/v1/status/flags

flags端点提供了一个完整路径的配置文件。如果文件存储在主目录中,则可能会泄漏用户名:

Prometheus API大规模暴露在互联网上|包括敏感信息

更麻烦——暴露的管理接口

除了由于开发人员和组织对 Prometheus 的非安全部署而导致的敏感数据暴露问题之外,重要的是要提到一个更大的潜在安全问题——Prometheus 提供了一个可选的管理 API,可以通过命令行标志web.enable-admin-apiweb.enable-lifecycle. 这些端点分别允许删除所有保存的指标和关闭监控服务器。

这些端点默认是禁用的,但在非安全部署中,攻击者可以从 API 端点 /api/v1/status/flags 查询这些设置的状态,以检查它们是否已手动启用:

{
    "status": "success",
        "data": {
            "web.enable-admin-api": "true",
            "web.enable-lifecycle": "false",
        }
}

在我们未经身份验证的抓取工作中,我们发现约 15%的公开 Prometheus 端点启用了 API 管理,约 4%启用了数据库管理。这意味着,未经身份验证的攻击者可以立即关闭和/或删除这些 Prometheus 端点的指标。虽然我们的调查清楚地表明了这种能力,但为了避免对这些端点的用户造成伤害或损害,作为本研究的一部分,我们并未尝试导致此类关闭或删除。

Prometheus API大规模暴露在互联网上|包括敏感信息

如何安全地部署 Prometheus

如前所述,虽然 Prometheus 过去没有任何内置安全功能,但在 2.24.0 版本中添加了基本身份验证和 TLS。对于部署 Prometheus 的开发人员和组织,这些功能提供了重要的保护,以防止敏感数据泄漏,如前几节所示。当一起使用,部署甚至可以抵抗本地网络攻击者的此类数据泄漏。下面,我们详细介绍了实现 Prometheus 2.24.0 及更高版本中提供的身份验证和 TLS 功能可以采取的步骤。

启用基本身份验证

目前,Prometheus 支持的唯一身份验证类型是基本身份验证,所以让我们启用它。这将为 Web UI 和所有 Prometheus API 端点启用基本身份验证。首先,我们需要使用bcrypt生成密码哈希。在 Linux 上执行此操作的最简单方法是使用 htpasswd 工具,该工具可在以下软件包之一(取决于您的软件包管理器)中使用 – apache2-utils、httpd-tools 或 apache-tools。

htpasswd 可以按如下方式执行 –

$ htpasswd -nBC 12 "" | tr -d ':\n'
New password:
Re-type new password:
$2y$12$ZcEJGmnIDSMKaeJhZsYeNukC.aJ.RhIfypct/pK5psrHEh6cB79L6

生成密码哈希后,创建一个 Prometheus web配置 YAML 文件(这是一个不同于标准 Prometheus 配置 YAML 文件的文件)并添加一个用户名(例如myuser),然后生成的密码哈希在basic_auth_users key

basic_auth_users:
  myuser: $2y$12$ZcEJGmnIDSMKaeJhZsYeNukC.aJ.RhIfypct/pK5psrHEh6cB79L6

运行 Prometheus 时,应使用 –web.config.file 命令行选项指定此 YAML 的路径:

$ ./prometheus --web.config.file=web.yml

启用 TLS

第二步,我们将在 Web UI 和 API 端点上启用传输层加密。即使已启用基本身份验证,这也是一项重要的任务,因为如果网络流量未加密,本地网络攻击者可能能够从网络流量中嗅探基本身份验证凭据。

启用 TLS 的先决条件是生成(或使用现有的)TLS 证书。由于这是一个众所周知的过程,我们不会在这篇博文中详细说明。这可以通过在线证书颁发机构轻松自由地完成,例如Let’s Encrypt。如果需要,可以在本地生成自签名证书,尽管这不适合生产环境,因为它不能保证身份验证并且容易受到 SSL中间人攻击。

假设你有证书和密钥文件,它们应该被复制到运行 Prometheus 的机器上,并添加到前面提到的 web 配置 YAML 文件下tls_server_config key,例如:

tls_server_config:
  cert_file: /path/to/mycert.pem
  key_file: /path/to/mykey.pem

总而言之,同时启用基本身份验证和 TLS 的正确 Web YAML 可能如下所示:

tls_server_config:
  cert_file: /path/to/mycert.pem
  key_file: /path/to/mykey.pem
basic_auth_users:
  myuser: $2y$12$ZcEJGmnIDSMKaeJhZsYeNukC.aJ.RhIfypct/pK5psrHEh6cB79L6

结论

自从动态服务发现机制和动态标签出现以来,开发人员和 IT 服务团队越来越难以跟踪 Prometheus 实际公开的运营数据(并且这些数据可能会在没有通知的情况下发生变化)。因此,我们强烈建议在部署 Prometheus 时使用身份验证和加密机制,以帮助防止敏感信息的无意泄漏。由于 Prometheus 团队在一月份添加的内置支持,在 Prometheus 2.24.0 及更高版本中实现这些功能比以往任何时候都容易。

除了启用这些机制之外,我们还强烈建议任何拥有 Prometheus 部署的人查询前面提到的端点,以帮助验证在实施身份验证和 TLS 功能之前是否可能已经暴露了敏感数据(甚至向经过身份验证的用户)在prometheus。

请注意,需要比 Prometheus 提供的身份验证或加密更强大的高级用户也可以设置单独的网络实体来处理安全层。例如 – Prometheus 前面的 nginx 反向代理可以根据需要提供增强的身份验证选项,例如承载 HTTP 身份验证(而不是基本身份验证)。

转载请注明出处及连接

Leave a Reply

您的电子邮箱地址不会被公开。 必填项已用 * 标注