不要让普罗米修斯偷走你的火
不安全的默认值暴露了现实世界中的秘密

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

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

刮掉普罗米修斯的端点
如前所述,普罗米修斯服务历来被假定为允许公共访问。这一点在鲁棒感知博客,官方文件说:
“我们假定不受信任的用户可以访问Prometheus HTTP端点和日志。他们可以访问数据库中包含的所有时间序列信息,以及各种操作/调试信息。”
因此,当我们开始寻找公开暴露的普罗米修斯端点时,我们期望它们中的大多数都可以在没有身份验证的情况下访问世界——我们是正确的。
使用搜索引擎Shodan或ZoomEye很容易找到成千上万的普罗米修斯端点。我们在Shodan中看到的最有效的单个查询是通过Web UI的图标查找普罗米修斯端点
.
这个特定的查询(http.favicon.hash: -1399433489)在Shodan返回近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用占位符替换凭证配置字段中的密码<秘密>(尽管这仍然泄露了用户名):

然而,由于普罗米修斯不会直接监控、删除或屏蔽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提供配置文件的完整路径。如果文件存放在主目录,可能会泄露用户名:

甚至更多的麻烦暴露的管理接口
除了由于开发人员和组织对Prometheus的不安全部署而导致的敏感数据暴露问题之外,还有一个更大的潜在安全问题——Prometheus提供了一个可选的管理API,可以通过命令行标志启用web.enable-admin-api和web.enable-lifecycle.这些端点允许删除所有已保存的指标和关闭监控服务器,分别。
默认情况下端点是禁用的,但在非安全部署中,攻击者可以从API endpoint / API /v1/status/flags查询这些设置的状态,以检查它们是否已被手动启用:
{"status": "success", "data": {"web。Enable-admin-api ": "true", "web. api"。Enable-lifecycle ": "false",}}
在我们未经认证的抓取工作中,我们发现~ 15%暴露的Prometheus端点中有一半启用了API管理,并且~ 4%启用了数据库管理。这意味着,未经身份验证的攻击者可以立即关闭和/或删除这些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':重新输入新密码:$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时,这个YAML的路径应该用-web.config来指定。文件命令行选项:
$ ./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. confPem key_file: /path/to/mykey.pem
综上所述,一个正确的web YAML可以同时启用基本身份验证和TLS:
Tls_server_config: cert_file: /path/to/mycert. confPem key_file: /path/to/mykey.pembasic_auth_users: myuser: $2y$12$ZcEJGmnIDSMKaeJhZsYeNukC.aJ.RhIfypct/pK5psrHEh6cB79L6
结论
由于动态服务发现机制和动态标签的出现,开发人员和it服务团队越来越难以跟踪Prometheus实际公开了哪些操作数据(并且这些数据可以在不通知的情况下更改)。因此,我们强烈建议在部署Prometheus时使用身份验证和加密机制,以帮助防止敏感信息的意外泄露。由于Prometheus团队在1月份添加了内置支持,在Prometheus 2.24.0及以后的版本中实现这些特性比以往任何时候都更容易。
除了启用这些机制外,我们还强烈建议使用Prometheus部署的任何人查询前面提到的端点,以帮助在实现Prometheus中的身份验证和TLS特性之前验证敏感数据是否已经暴露(甚至对经过身份验证的用户)。
请注意,需要比Prometheus提供的更强的身份验证或加密的高级用户也可以设置一个单独的网络实体来处理安全层。例如,Prometheus前面的nginx反向代理可以根据需要提供增强的身份验证选项,例如承载HTTP身份验证(而不是基本身份验证)。
请继续关注
除了暴露新安全漏洞通过自动安全扫描,JFrog为开发人员和安全团队提供了轻松访问其软件最新相关信息的方法JFrog x光.继续关注我们的产品更新,包括扫描配置文件(如Prometheus YAML配置文件),以自动识别软件配置安全漏洞。
问题吗?想法吗?如有任何疑问,请通过research@www.si-fil.com与我们联系。