别让普罗米修斯偷走你的火焰
不安全的默认设置暴露了真实世界的秘密

背景
普罗米修斯是面向云应用程序的开源、基于度量的事件监控和警报解决方案。它被近800家云原生组织使用,包括Uber、Slack、Robinhood等。通过抓取来自各个端点的实时指标,Prometheus可以轻松观察系统状态,除了观察硬件和软件指标,如内存使用情况,网络使用情况和软件特定定义的指标(例如登录web应用程序失败的次数)。
由于Prometheus捕获的数值度量不被认为是敏感数据,因此Prometheus持有一种可以理解的策略,即避免内置对安全特性(如身份验证和加密)的支持,以便专注于开发与监视相关的特性。不到一年前(2021年1月),随着2.24.0版本的发布,引入了传输层安全(TLS)和基本身份验证支持,这种情况发生了变化。
由于身份验证和加密支持相对较新,许多使用Prometheus的组织还没有启用这些功能,因此许多Prometheus端点完全暴露在互联网上(例如,运行早期版本的端点),泄漏度量和标签数据。
那么,这些数据真的像我们假设的那样不敏感吗?
在这篇博客文章中,我们将展示大规模未经认证的抓取公开可用和不安全的普罗米修斯端点的结果,其中包含许多类型的敏感数据被暴露,通常在开发人员不知情的情况下.除了介绍我们在实际应用程序中发现的最常见的配置问题外,我们还演示了开发人员和其他用户如何以更安全的方式部署Prometheus。
体系结构
下图显示了Prometheus体系结构的简化结构。

Prometheus的检索工作,也称为scraper,从目标服务中提取数据,汇总数据,并将其传递到数据库。Prometheus的HTTP服务器使这些数据以JSON格式通过API端点可用,或以可视化HTML形式通过/图端点。
在最简单的情况下,Prometheus从调用的静态列表(或文件)中获取一个抓取目标(IP地址和端口)列表static_configs存在于Prometheus基于yaml的配置文件中。使用更复杂的动态环境,其中可能随时出现新实例服务发现机制,它提供了用于监视的机器列表,并显示了这些机器是如何组织的信息。
抓取目标会暴露它们的指标作为带有键值记录的文本文件,带有可选的“标签”数据。每条记录都有一个帮助热线,描述度量和类型定义的目的,指导普罗米修斯如何解释值。
# HELP go_info Go环境信息。# TYPE go_info gauge go_info{version="go1.16.7"} 1 # HELP go_memstats_alloc_bytes已分配且仍在使用的字节数。# TYPE go_memstats_alloc_bytes gauge go_memstats_alloc_bytes 6.9728224e+07#类型go_memstats_alloc_bytes_total计数器
通过使用Prometheus对可视化插件(如Grafana)的支持,聚合数据的视图可以根据用户的需要进行定制(下图示例)。

抓取普罗米修斯的端点
如前所述,普罗米修斯服务在历史上被认为是允许公众访问的。这一点在健壮的感知博客,官方文件说:
“假定不受信任的用户可以访问Prometheus HTTP端点和日志。他们可以访问数据库中包含的所有系列信息,以及各种操作/调试信息。”
因此,当我们开始寻找公开暴露的普罗米修斯端点时,我们期望它们中的大多数不需要身份验证就可以在世界范围内访问——我们是正确的。
使用搜索引擎Shodan或ZoomEye找到成千上万的普罗米修斯端点是非常容易的。我们在Shodan中看到的最有效的单个查询是通过Web UI的favicon寻找Prometheus端点
.
这个特定的查询(http.favicon.hash: -1399433489Shodan中返回近27K主机,ZoomEye中返回43K主机。通过在这些公开的端点上自动迭代,我们已经看到该查询返回的所有端点都具有可公开访问的数据(意味着没有身份验证机制)。

对于度量数据来说,没有访问限制可能是有意义的,因为从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端点通常不是静态配置的,而是使用动态服务发现,甚至由云提供商作为交钥匙解决方案提供(例如。GKE).在这些情况下,部署Prometheus可能会在组织的端点上暴露大量的操作信息,包括更加敏感的信息,正如我们现在将要演示的那样。
暴露敏感的操作信息
让我们回顾一些包含操作信息的真实示例,以更好地理解它们可能泄漏哪些敏感信息,以及为什么组织应该优先考虑Prometheus的安全部署。
我们将根据获取信息的端点对信息进行分组:
/ api / v1 /地位/配置
的配置端点返回加载的(YAML)配置文件。
该文件还包含目标和警报/发现服务的地址以及访问它们所需的凭据。通常,Prometheus将凭据配置配置字段中的密码替换为占位符<秘密>(尽管这仍然泄露用户名):

然而,由于Prometheus不直接监控,删除或以其他方式屏蔽URL字符串中提供的用户名和密码,这些敏感数据完全泄露了:

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

API端点/ api / v1 /目标以可解析的JSON格式深入显示此信息。除了显示目标计算机地址外,端点还会公开由目标提供程序添加的元数据标签.这些标签旨在包含非敏感值,如服务器名称或其描述,但各种云平台可能会自动在这些标签中暴露敏感数据,通常在开发人员不知情的情况下。
例如,当使用基于gce的服务发现时(gce_sd_configs),部分导出的元数据是一个带有SSH公钥的标签,泄漏了用户和机器名:

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

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

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

此发现机制还公开了最后应用的配置标签(_meta_kubernetes_pod_annotation_kubectl_kubernetes_io_last_applied_configuration),也会透过已配置的环境变量泄露敏感资料:

/ api / v1 /地位/旗帜
的旗帜Endpoint提供配置文件的完整路径。如果文件保存在home目录下,可能会泄露用户名:

甚至有更多问题暴露的管理接口
除了由于开发人员和组织对Prometheus的不安全部署而导致的敏感数据暴露问题之外,还必须提到一个更大的潜在安全问题——Prometheus提供了一个可选的管理API,可以通过命令行标志启用web.enable-admin-api而且web.enable-lifecycle.这些端点允许删除所有保存的指标而且正在关闭监控服务器,分别。
这些端点在默认情况下是禁用的,但在非安全部署中,攻击者可以从API端点/ API /v1/status/flags中查询这些设置的状态,以检查它们是否已被手动启用:
{"status": "success", "data": {"web. "启用-admin-api": "true", "web。Enable-lifecycle ": "false",}}
在我们未经验证的搜索中,我们发现~ 15%公开的Prometheus端点启用了API管理,以及~ 4%已启用数据库管理。这意味着未经身份验证的攻击者可以立即关闭和/或删除这些普罗米修斯端点的度量。虽然我们的调查清楚地表明了这种能力,但为了避免对这些终端的用户造成伤害或损害,我们没有试图在研究中造成这种关闭或删除。

如何安全部署普罗米修斯
如前所述,尽管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'新密码:重新输入新密码:$2y$12$ZcEJGmnIDSMKaeJhZsYeNukC.aJ.RhIfypct/pK5psrHEh6cB79L6
在生成密码哈希之后,创建一个Prometheus网络配置YAML文件(这是一个不同于标准Prometheus配置YAML文件的文件),并添加一个用户名(例如。myuser),则生成的密码散列在basic_auth_users关键:
basic_auth_users: myuser: $2y$12$ZcEJGmnIDSMKaeJhZsYeNukC.aJ.RhIfypct/pK5psrHEh6cB79L6
运行Prometheus时,应该使用-web.config指定这个YAML的路径。文件命令行选项:
$ ./prometheus——web.config.file=web.yml
支持TLS
作为第二步,我们将在Web UI和API端点上启用传输层加密。即使已经启用了基本身份验证,这也是一项重要的任务,因为如果网络流量未加密,本地网络攻击者可能能够从网络流量中嗅出基本身份验证凭据。
启用TLS的先决条件是生成(或使用现有的)TLS证书。由于这是一个众所周知的过程,我们不会在这篇博文中详细说明。这可以通过在线证书颁发机构轻松而自由地完成,例如让我们加密.如果需要,自签名证书可以在本地生成,尽管这不适合生产环境,因为它不保证身份验证,并且容易受到SSL的影响中间人攻击。
假设您拥有证书和密钥文件,应该将它们复制到运行Prometheus的机器上,并将其添加到前面提到的web配置YAML文件中tls_server_config关键,例如:
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.pembasic_auth_users: myuser: $2y$12$ZcEJGmnIDSMKaeJhZsYeNukC.aJ.RhIfypct/pK5psrHEh6cB79L6
结论
自从动态服务发现机制和动态标签出现以来,开发人员和it服务团队就越来越难以跟踪Prometheus实际暴露了哪些操作数据(而且这些数据可以在没有通知的情况下更改)。因此,我们强烈建议在部署Prometheus时使用身份验证和加密机制,以帮助防止敏感信息的意外泄露。在Prometheus 2.24.0及后续版本中实现这些特性比以往任何时候都容易,这是由于Prometheus团队在1月份添加了内置支持。
除了启用这些机制外,我们还强烈建议任何使用Prometheus部署的人查询前面提到的端点,以帮助验证在Prometheus中实现身份验证和TLS特性之前,敏感数据是否已经暴露(甚至对已验证的用户)。
请注意,高级用户需要比Prometheus提供的更强的身份验证或加密,也可以设置一个单独的网络实体来处理安全层。例如,Prometheus前面的nginx反向代理可以根据需要提供增强的身份验证选项,例如承载HTTP身份验证(而不是基本身份验证)。
请继续关注
除了曝光新安全漏洞和威胁,JFrog提供开发人员和安全团队轻松访问最新的相关信息,为他们的软件与自动安全扫描JFrog x光.请继续关注我们的产品更新,包括扫描配置文件(如Prometheus YAML配置文件),以自动识别软件配置安全漏洞。
问题吗?想法吗?如有任何疑问,请通过research@m.si-fil.com与我们联系。
