
Prometheus v3.15.0 - 높음 - 원격 - 자격 증명 유출 - remote_write google_iam/azuread가 교차 호스트 3xx에서 Bearer를 전달함
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은 이미 교차 호스트 리다이렉트 시 스크레이프 / 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 |
| 인증 | 설정에 따라 azuread: 또는 google_iam:이 있는 remote_write |
| 라이선스 | 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은 항상 isCrossHostRedirect 없이 Header.Set("Authorization", "Bearer "+token) 수행 | 고정 소스에서 추론. NewWriteClient의 동일한 래핑 지점. 실습에서는 google_iam을 사용했으므로 Azure를 호출하지 않음 |
| 해당 토큰을 해당 ID로 Azure Monitor / GCP Monitoring에 재사용 | 해당 인증 블록이 설정된 경우 토큰은 실제 클라우드 자격 증명임 | 추론. 실습에서는 스텁 토큰을 발급했으며 Azure 또는 GCP를 호출하지 않음 |
| 동일 고정 버전에서 scrape / oauth2 / basic / bearer | common v0.71.0의 HTTPClientConfig RoundTripper | 실습 입증, 종료됨. oauth2 scrape GET이 Authorization 없이 동일한 oracle로 302를 따라감 |
| 기본 OSS | remote_write 비어 있음 | 종료됨 |
remote_write.headers에서 Authorization 설정 | 거부됨 | 종료됨 |
/-/config에서 client_secret 덤프 | CVE-2026-42151; 이 고정 버전에서 필드는 Secret 타입임 | 종료됨 |
| Prometheus admin / 라이프사이클 | 플래그 기본값 꺼짐 | 종료됨 |
| RCE / 셸 | 이 잔여 문제가 아님 | 종료됨 |
3.11/3.12 비밀 정보 마스킹 및 snappy 상한 물결 이후 prometheus/prometheus 태그 v3.15.0을 고정했습니다. 열아홉 번의 탐색. 기본 OSS: admin API, 라이프사이클 HTTP, remote-write 수신기, OTLP 수신기 꺼짐. 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를 여전히 누출이 있다고 취급하는 것(그렇지 않음); 이를 기본 설치 시 High로 부르는 것(그렇지 않음 - remote_write는 활성화하기 전까지 비어 있음). 극적 요소: 리버스 셸. 오라클은 리다이렉트된 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는 token_uri: http://hop:8080/token이 포함된 랩용 gcp-sa.json을 작성하여 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
공통 #901과 동일하게, isCrossHostRedirect(req)일 때 Azure AD / Google IAM Bearer 첨부를 건너뜁니다. Go가 교차 호스트 3xx에서 Authorization을 제거한 후 다시 설정하지 않습니다.
5241a27fe3c6983549fccc32f6e65917408c63cd)storage/remote/client.go · storage/remote/azuread/azuread.go · storage/remote/googleiam/googleiam.goGNU Affero GPL v3.0. LICENSE를 참조하세요. 루프백 랩 전용. 보증 없음.