
Prometheus v3.15.0 - Élevé - À distance - Fuite d'identifiants - remote_write google_iam/azuread transmet le Bearer lors d'une redirection 3xx inter-hôtes
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · prometheus-bearer-redirect
Classe : Fuite d'identifiants Portée : Distante
Prometheus v3.15.0 (5241a27) - CNCF / Prometheus
prometheus/common v0.71.0 supprime déjà les identifiants de scrape / HTTPClientConfig lors des redirections inter-hôtes (isCrossHostRedirect, #901). NewWriteClient construit d'abord ce client, puis enveloppe azuread.NewAzureADRoundTripper ou googleiam.NewRoundTripper en dehors de cette suppression. follow_redirects reste à true par défaut.
Si l'URL remote_write configurée renvoie un 301/302/307 vers un autre hôte, Prometheus envoie Authorization: Bearer ainsi que le jeton Azure AD ou GCP monitoring.write à cet hôte. Go a déjà supprimé l'en-tête copié. Ces RoundTrippers le redéfinissent.
Pas CVE-2026-42151 (fuite de client_secret sur /-/config). Le prometheus.yml par défaut n'a pas de remote_write. Ceci est conditionné par azuread: ou google_iam:.
| ID | pas encore de CVE |
| Classe | Fuite d'identifiants (Bearer remote_write sur 3xx inter-hôtes) |
| Portée | Distante (sortante de Prometheus vers une cible 3xx) |
| CWE | CWE-201 |
| CVSS | Élevé : 8.6 CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:N/A:N |
| Produit | Prometheus |
| Affecté | v3.15.0 (5241a27fe3c6983549fccc32f6e65917408c63cd), image prom/prometheus:v3.15.0 |
| Auth | remote_write conditionné par la config avec azuread: ou google_iam: |
| Licence | GNU Affero GPL v3.0 |
| Lab | 127.0.0.1 uniquement |
L'opérateur a remote_write avec azuread: ou google_iam:. L'URL RW, ou un saut vers lequel elle redirige en 3xx, est un hôte contrôlé par l'attaquant.
| Privilège | Méthode / cible | Prouvé en lab ou déduit |
|---|---|---|
Lire le Bearer GCP monitoring.write en direct sur un 3xx inter-hôtes | POST remote_write google_iam, 307 vers un autre hôte | Prouvé en lab. L'oracle POST /write a reçu Authorization: Bearer lab-gcp-PROMETHEUS-BEARER-REDIRECT-WITNESS |
Même fuite pour azuread | azureADRoundTripper.RoundTrip fait toujours Header.Set("Authorization", "Bearer "+token) sans isCrossHostRedirect | Déduit du code source épinglé. Même site d'enveloppement dans NewWriteClient. Le lab a utilisé google_iam donc n'a pas appelé Azure |
| Rejouer ce jeton contre Azure Monitor / GCP Monitoring avec cette identité | Le jeton est un véritable identifiant cloud lorsque ces blocs d'auth sont configurés | Déduit. Le lab a généré un jeton factice ; il n'a pas appelé Azure ni GCP |
| Scrape / oauth2 / basic / bearer sur le même code épinglé | RoundTrippers HTTPClientConfig de common v0.71.0 | Prouvé en lab comme fermé. Le GET scrape oauth2 a suivi un 302 vers le même oracle sans Authorization |
| OSS par défaut | remote_write vide | Fermé |
remote_write.headers définissant Authorization | rejeté | Fermé |
/-/config exposant client_secret | CVE-2026-42151 ; le champ est typé Secret sur ce code épinglé | Fermé |
| Admin / cycle de vie Prometheus | flags désactivés par défaut | Fermé |
| RCE / un shell | pas ce résidu | Fermé |
J'ai épinglé le tag prometheus/prometheus v3.15.0 après la vague de rédaction des secrets et de plafonnement snappy des 3.11/3.12. Dix-neuf chasses. OSS par défaut : API admin, cycle de vie HTTP, récepteur remote-write et récepteur OTLP désactivés. Common #901 est dans v0.71.0. Le résidu, ce sont les deux enveloppes remote_write qui se trouvent en dehors de ce client.
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 est google.golang.org/api/transport/http -> oauth2.Transport, qui fait SetAuthHeader à chaque saut.
Fausses pistes déjà consignées : re-déclarer CVE-2026-42151 ; considérer le scrape oauth2 comme encore fuyant (ce n'est pas le cas) ; qualifier ceci de Élevé en installation par défaut (ce n'est pas le cas - remote_write est vide tant que vous ne l'activez pas). Théâtre : un reverse shell. L'oracle est un Bearer sur le POST redirigé.
python3 prometheus-bearer-redirect-Abraxas-Labs.py
ou
cd lab
./run.sh
Loopback uniquement : Prometheus http://127.0.0.1:19380, oracle http://127.0.0.1:19381. Image prom/prometheus:v3.15.0. run.sh écrit un gcp-sa.json de lab avec token_uri: http://hop:8080/token pour que google_iam ne parle jamais à 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
Ne pas attacher le Bearer Azure AD / Google IAM lorsque isCrossHostRedirect(req), comme pour common #901. Ne pas redéfinir Authorization après que Go l'a supprimé sur un 3xx inter-hôtes.
5241a27fe3c6983549fccc32f6e65917408c63cd)storage/remote/client.go · storage/remote/azuread/azuread.go · storage/remote/googleiam/googleiam.goGNU Affero GPL v3.0. Voir LICENSE. Lab en loopback uniquement. Aucune garantie.