OpenObserve: SSRF-Schutz prueft nur die erste URL, nicht die Weiterleitung

Der Schutz prueft die eingereichte Adresse, der HTTP-Klient folgt danach bis zu zehn Weiterleitungen, ohne dass erneut geprueft wird.

Advisory-ID: TP-2026-088
Produkt: OpenObserve (Plattform fuer Logs, Metriken und Traces, Rust)
Schwachstellentyp: Server-Side Request Forgery (CWE-918)
CVE: beantragt (GitHub CNA), Vergabe ausstehend
CVSS 3.1: 8.5 (Hoch) · CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:L/A:N
Betroffene Versionen: < 0.91.0
Hersteller-Advisory: GHSA-rhm9-hcf6-v2f5
Behoben in: 0.91.0
Gemeldet: 27. Mai 2026

Zusammenfassung

OpenObserve kann Alarme an externe Ziele schicken und bietet dafuer einen Testknopf, der die hinterlegte Adresse sofort abruft. Vor dem Abruf laeuft eine Pruefung, die Loopback, private Netze, den Link-Local-Bereich und die bekannten Metadaten-Adressen der Cloud-Anbieter ablehnt. Diese Pruefung sieht ausschliesslich die eingereichte Adresse. Der HTTP-Klient dahinter folgt anschliessend bis zu zehn Weiterleitungen, und bei keiner davon laeuft die Pruefung erneut. Wer eine oeffentliche Adresse angibt, die mit einer Weiterleitung auf eine interne antwortet, liest die Antwort des internen Dienstes im Klartext in der API-Antwort, und dafuer genuegt ein gewoehnliches Organisationskonto.

Ursache

Der Test-Handler ruft SsrfGuard::validate_url_with_config(url) allein auf der eingereichten Adresse auf (src/handler/http/request/alerts/destinations.rs:172). Direkt darunter entsteht der Klient mit reqwest::Client::builder().timeout(...).build() und ohne jede Weiterleitungsregel, weshalb reqwest seiner Voreinstellung folgt und bis zu zehn Spruenge mitgeht (:182). Die Pruefroutine selbst zerlegt und bewertet nur die uebergebene Zeichenkette und loest dabei keinen Namen auf, sodass auch ein oeffentlicher Name, der auf eine private Adresse zeigt, sie passiert (src/common/utils/ssrf_guard.rs:48,68). Der Rumpf der Antwort geht über response.text() als response_body an den Aufrufer zurueck, womit aus der blinden eine lesende Anfrage wird (:233). Der Alarm-Versand selbst haengt an derselben Ursache, dort allerdings blind.

Proof of Concept

# 1. Ein oeffentlicher Umleiter antwortet mit:
#    HTTP/1.1 302 Found
#    Location: http://169.254.169.254/latest/meta-data/iam/security-credentials/

# 2. Als gewoehnlicher Organisationsnutzer:
POST /api/{org}/alerts/destinations/test
{"url": "https://umleiter.example/zu-metadaten", "method": "get"}

# Die Pruefung sieht nur den oeffentlichen Namen, reqwest folgt der
# Weiterleitung, und response_body enthaelt die Antwort des internen Dienstes.

Dieselbe Wirkung erreicht ein oeffentlicher Name, dessen A-Eintrag auf eine private Adresse zeigt, denn die Pruefung loest Namen gar nicht erst auf.

Auswirkung

  • Lesender Zugriff auf interne HTTP-Dienste aus dem Netz des Servers heraus, mit der Antwort im Klartext in der API-Rueckgabe.
  • Abruf des Metadaten-Dienstes bei einem Betrieb in der Cloud und damit Zugriff auf die Rollen-Zugangsdaten der Instanz.
  • Kartierung des internen Netzes ueber die unterschiedlichen Antworten, ohne dass der Angreifer dort etwas erreichen muss.
  • Ausreichend ist ein gewoehnliches Organisationskonto, eine Administratorrolle wird nicht gebraucht.

Referenzen

Steckt so etwas in Ihrer Software?

Diese Schwachstelle hat unser Team im Rahmen seiner Arbeit gefunden. Lassen Sie Ihre Anwendungen von denselben Spezialisten prüfen, mit einem Penetrationstest von turingpoint.