abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · prometheus-bearer-redirect
分析文章:https://abraxaslabs.tech/research/prometheus-bearer-redirect
类别: 凭据泄露 影响范围: 远程
Prometheus v3.15.0 (5241a27) - CNCF / Prometheus
prometheus/common v0.71.0 已在跨主机重定向时剥离 scrape / HTTPClientConfig 凭据(isCrossHostRedirect,#901)。NewWriteClient 先构建该客户端,然后在剥离逻辑之外包装 azuread.NewAzureADRoundTripper 或 googleiam.NewRoundTripper。follow_redirects 仍默认为 true。
如果配置的 remote_write URL 以 301/302/307 重定向到另一台主机,Prometheus 会把 Authorization: Bearer 以及 Azure AD 或 GCP 的 monitoring.write 令牌发送到该主机。 Go 已经丢弃了复制的请求头。这些 RoundTripper 又把它重新设置上了。
不是 CVE-2026-42151(在 /-/config 上泄露 client_secret)。默认的 prometheus.yml 没有 remote_write。此问题以配置了 azuread: 或 google_iam: 为前提。
| ID | 暂无 CVE |
| 类别 | 凭据泄露(跨主机 3xx 时泄露 remote_write Bearer) |
| 影响范围 | 远程(从 Prometheus 向 3xx 目标发起出站请求) |
| CWE | CWE-201 |
| CVSS | 高危:8.6 CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:N/A:N |
| 产品 | Prometheus |
| 受影响版本 | v3.15.0 (5241a27fe3c6983549fccc32f6e65917408c63cd),镜像 prom/prometheus:v3.15.0 |
| 认证 | 需配置 remote_write 且包含 azuread: 或 google_iam: |
| 许可证 | GNU Affero GPL v3.0 |
| 实验环境 | 仅 127.0.0.1 |
运维人员配置了带 azuread: 或 google_iam: 的 remote_write。RW URL,或它 3xx 重定向到的某一跳,是攻击者控制的主机。
| 权限 | 方法 / 目标 | 实验验证或推断 |
|---|---|---|
在跨主机 3xx 时读取实时的 GCP monitoring.write Bearer | google_iam remote_write POST,307 重定向到另一台主机 | 实验验证。Oracle 的 POST /write 收到了 Authorization: Bearer lab-gcp-PROMETHEUS-BEARER-REDIRECT-WITNESS |
azuread 存在同样的泄露 | azureADRoundTripper.RoundTrip 总是执行 Header.Set("Authorization", "Bearer "+token),没有 isCrossHostRedirect 检查 | 根据该版本源码推断。NewWriteClient 中包装位置相同。实验使用 google_iam,因此未调用 Azure |
| 以该身份将令牌重放到 Azure Monitor / GCP Monitoring | 配置了这些认证块时,令牌是真实的云凭据 | 推断。实验铸造的是桩令牌;未调用 Azure 或 GCP |
| 同一版本上的 scrape / oauth2 / basic / bearer | 来自 common v0.71.0 的 HTTPClientConfig RoundTripper | 实验验证已关闭。oauth2 scrape GET 跟随 302 到同一 oracle,未携带 Authorization |
| 默认 OSS | remote_write 为空 | 已关闭 |
remote_write.headers 设置 Authorization | 被拒绝 | 已关闭 |
/-/config 泄露 client_secret | CVE-2026-42151;该版本中字段类型为 Secret | 已关闭 |
| Prometheus 管理 / 生命周期 | 标志默认关闭 | 已关闭 |
| RCE / 获取 shell | 不是此遗留问题 | 已关闭 |
在 3.11/3.12 的密钥脱敏和 snappy 上限浪潮之后,我锁定了 prometheus/prometheus 标签 v3.15.0。共进行了十九次排查。默认 OSS:admin API、生命周期 HTTP、remote-write receiver 和 OTLP receiver 均关闭。Common #901 已包含在 v0.71.0 中。遗留问题是位于该客户端之外的两个 remote_write 包装器。
func (rt *azureADRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
accessToken, err := rt.tokenProvider.getAccessToken(req.Context())
// ...
req.Header.Set("Authorization", bearerAccessToken)
return rt.next.RoundTrip(req)
}
googleiam.NewRoundTripper 是 google.golang.org/api/transport/http -> oauth2.Transport,它在每一跳上执行 SetAuthHeader。
已记录的误判:重新提交 CVE-2026-42151;认为 scrape oauth2 仍然存在泄漏(实际并非如此);将其称为默认安装下的高危问题(实际并非如此——在你启用之前 remote_write 是空的)。作秀手段:反向 shell。判定依据是重定向后的 POST 请求上的 Bearer。
python3 prometheus-bearer-redirect-Abraxas-Labs.py
或
cd lab
./run.sh
仅回环地址:Prometheus http://127.0.0.1:19380,oracle http://127.0.0.1:19381。镜像 prom/prometheus:v3.15.0。run.sh 会写入一个实验用 gcp-sa.json,其中 token_uri: http://hop:8080/token,因此 google_iam 永远不会与 Google 通信。
SUCCESS prometheus-bearer-redirect how=live rw-method=POST rw-bearer=yes token-has-witness=yes scrape-method=GET scrape-bearer=no PROMETHEUS-BEARER-REDIRECT-WITNESS
当 isCrossHostRedirect(req) 为真时,跳过附加 Azure AD / Google IAM Bearer,与 common #901 的做法一致。不要在 Go 于跨主机 3xx 响应中丢弃 Authorization 后重新设置它。
5241a27fe3c6983549fccc32f6e65917408c63cd)storage/remote/client.go · storage/remote/azuread/azuread.go · storage/remote/googleiam/googleiam.goGNU Affero GPL v3.0。参见 LICENSE。仅限回环实验环境。不提供任何担保。