HIGH🇬🇧 English

CVE-2026-69246

Guzzle: SSRF przez rozbieżność parsowania URI hosta (percent-encoding / IDNA)

CVSS 7.2v3.1pub. 2026-08-03upd. 2026-08-04

W bibliotece Guzzle (PHP HTTP client) w wersjach przed 7.15.2 i 8.0.1 istnieje podatność SSRF wynikająca z rozbieżności między tym, jak Guzzle waliduje hosta w URI, a tym, jak libcurl dekoduje i interpretuje ten host. Atakujący mogący kontrolować URI żądania może ominąć mechanizmy kontroli dostępu i skłonić aplikację do połączenia się z hostem, który ta miała wykluczyć.

Pokaż oryginał (EN)

Guzzle is an extensible PHP HTTP client. Prior to 7.15.2 and 8.0.1, Guzzle gives a transport the request URI as text and supplies the Host header separately. The cURL handlers set CURLOPT_URL to the URI exactly as written and push that Host into CURLOPT_HTTPHEADER; StreamHandler does the same through fopen(). libcurl then parses the authority itself, percent-decoding it and, on an IDN-capable build, applying IDNA mapping, and uses the result to resolve, connect, name the TLS peer and address a proxy CONNECT, while the supplied Host suppresses the aligned one libcurl would have generated. For a URI host written as 127.0.0.%31, filter_var() rejects the host as an IP literal, yet libcurl decodes it to 127.0.0.1 and reaches loopback with no DNS lookup while the server receives Host: 127.0.0.%31. An attacker who influences a fetched URI can therefore reach a host the application's checks excluded and read whatever the host exposes of the response. The same divergence moves Guzzle's own decisions onto a spelling the transport does not use: no_proxy selects proxy routing from the literal host, and RedirectMiddleware decides from it whether to strip Authorization and Cookie. Exploitation requires the application to build a request URI from untrusted input and to make a host decision before handing it to Guzzle. This issue is fixed in versions 7.15.2 and 8.0.1.

🤖 Analiza AI
Jak działa

Guzzle przekazuje URI żądania do warstwy transportowej (cURL lub StreamHandler) jako tekst, ustawiając CURLOPT_URL na URI dosłownie tak, jak zostało zapisane. libcurl następnie samodzielnie parsuje sekcję authority URI, wykonując percent-decoding oraz — na buildach z obsługą IDN — mapowanie IDNA, i używa wyniku do rozwiązywania nazwy, nawiązania połączenia, weryfikacji peera TLS oraz obsługi proxy CONNECT. Tymczasem Guzzle waliduje hosta na podstawie nieprzetworzonego, dosłownego zapisu URI: np. dla hosta zapisanego jako `127.0.0.%31` funkcja `filter_var()` odrzuci go jako nieprawidłowy literał IP, jednak libcurl zdekoduje go do `127.0.0.1` i nawiąże połączenie z loopbackiem bez żadnego zapytania DNS, przy czym serwer docelowy otrzyma nagłówek `Host: 127.0.0.%31`. Taka sama rozbieżność dotyczy logiki `no_proxy` (wybór trasowania przez proxy) oraz `RedirectMiddleware` (decyzja o usunięciu nagłówków `Authorization` i `Cookie` przy przekierowaniach) — obie operują na dosłownym zapisie hosta, który nie odpowiada hostowi faktycznie używanemu przez transport.

Skutki

Atakujący mogący wpływać na URI budowane przez aplikację może ominąć listy blokowanych hostów i dotrzeć do zasobów wewnętrznych (np. loopback, sieci prywatne), odczytując odpowiedzi serwera, do których dostęp miał być zablokowany. Dodatkowo może dojść do nieumyślnego przesyłania nagłówków uwierzytelniających (`Authorization`, `Cookie`) do niezaufanych hostów przy obsłudze przekierowań lub nieprawidłowego trasowania ruchu przez proxy.

Mitygacja

Należy zaktualizować Guzzle do wersji 7.15.2 (gałąź 7.x) lub 8.0.1 (gałąź 8.x). Patche dostępne są w oficjalnym repozytorium GitHub projektu (commity wskazane w referencjach). Jako obejście należy unikać budowania URI żądań na podstawie niezaufanych danych wejściowych bez uprzedniej normalizacji i dekodowania percent-encodingu po stronie aplikacji przed przekazaniem do Guzzle.

Kogo dotyczy

Guzzle w wersjach przed 7.15.2 (gałąź 7.x) oraz przed 8.0.1 (gałąź 8.x), gdy aplikacja buduje URI żądania na podstawie niezaufanych danych wejściowych i wykonuje walidację hosta przed przekazaniem żądania do Guzzle.

Uwagi

Podatność wymaga spełnienia dwóch warunków po stronie aplikacji: (1) budowania URI żądania z niezaufanych danych wejściowych oraz (2) podejmowania decyzji dotyczącej hosta przed przekazaniem żądania do Guzzle. Poprawki zostały wydane w pull requestach #3907 i #3908 w repozytorium guzzle/guzzle.

CVSS Vector
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:L/A:N
🔵
ZWERYFIKUJ U PRODUCENTA
Brak jednoznacznych danych o patchu. Sprawdź referencje od producenta.
CWE
Referencje