host header injection
| Po angielsku | host header injection / password reset poisoning |
|---|---|
| Którą formą pisać | po angielsku Polski odpowiednik istnieje, ale w praktyce nikt tak nie pisze. Zostaw angielski, polski trzymaj jako synonim. |
| Inne formy | password reset poisoning · atak na nagłówek Host · manipulacja nagłówkiem Host · zatrucie resetu hasła |
| Kategoria | Podatności i klasy błędów |
Host header injection to klasa ataków na aplikacje, które w niebezpieczny sposób obsługują wartość nagłówka Host z żądania HTTP [1]. Gdy serwer ufa temu nagłówkowi bez sprawdzenia, atakujący może podać w nim dowolną domenę i w ten sposób wpłynąć na działanie aplikacji [1]. Najbardziej znanym skutkiem jest password reset poisoning: strona generuje link resetu hasła wskazujący na domenę kontrolowaną przez atakującego [2].
Jak działa
Nagłówek Host wskazuje nazwę domeny, do której klient chce się dostać, i jest obowiązkowy od HTTP/1.1 [1]. Specyfikacja HTTP wymaga, by klient wysyłał go w każdym żądaniu HTTP/1.1, a serwer odpowiadał kodem 400 albo 505 na żądanie bez tego nagłówka lub z więcej niż jednym [3]. Nagłówek służy do wyboru właściwej strony, gdy wiele witryn dzieli jeden adres IP, na przykład na hostingu współdzielonym albo za reverse proxy [1].
Problem zaczyna się, gdy aplikacja używa tej wartości do budowania adresów: w linkach w mailach, w przekierowaniach, w adresach skryptów. Wartość pochodzi od klienta, więc klient może ją zmienić. Wytyczne testowe OWASP zwracają uwagę, że nawet przy walidacji samego Host aplikacja może przyjąć podstawioną domenę z nagłówka X-Forwarded-Host [4].
Przebieg password reset poisoning pokazuje schemat poniżej [2].
Atakujący zna adres e-mail albo login ofiary i wysyła w jej imieniu prośbę o reset, zmieniając w żądaniu nagłówek Host [2]. Ofiara dostaje prawdziwy mail z ważnym tokenem, ale link prowadzi do serwera atakującego [2]. Kliknięcie przekazuje mu token, którym ustawia nowe hasło na właściwej stronie [2]. Efektem jest przejęcie konta.
Odmiany
PortSwigger wymienia kilka rodzajów ataków, do których prowadzi niebezpieczna obsługa nagłówka Host [1].
| Odmiana | Mechanizm |
|---|---|
| password reset poisoning | link resetu budowany z nagłówka [2] |
| web cache poisoning | pamięć podręczna zapisuje odpowiedź z podstawioną domeną [4] |
| SSRF (Server-Side Request Forgery) oparty na routingu | pośrednik kieruje żądanie do wewnętrznego hosta [1] |
| obejście uwierzytelniania | dostęp zależny od wartości nagłówka [1] |
| klasyczne błędy po stronie serwera | np. SQL injection przez wartość Host [1] |
Web cache poisoning jest groźny, bo jedna podstawiona odpowiedź trafia do wszystkich, którzy później pobiorą ten sam zasób z pamięci podręcznej, także z CDN albo serwera pośredniczącego [4].
W WordPressie
Sekurak 4 maja 2017 roku opisał lukę CVE-2017-8295, którą odkrył Dawid Golunski [5]. Dotyczyła wszystkich wersji WordPressa do 4.7.4 włącznie [5]. W mailu resetującym hasło WordPress ustawiał nagłówki From i Return-Path na podstawie zmiennej SERVER_NAME, a tę w pewnych konfiguracjach dało się kontrolować nagłówkiem Host [5]. Nie chodziło więc o link, lecz o adres nadawcy: odpowiedź na mail albo zwrotka z linkiem resetu mogła trafić do atakującego [5]. Warunkiem był dodatkowo sposób przejęcia wiadomości, na przykład zasypanie ofiary prośbami o reset w nadziei, że odpowie na maila [5].
Zależność od serwera wynika z konfiguracji Apache. Dyrektywa UseCanonicalName ma domyślnie wartość Off, a wtedy zmienna SERVER_NAME przyjmuje wartość z nagłówka Host podanego przez klienta [7]. Przy On serwer bierze ją z dyrektywy ServerName [7]. Właśnie ustawienie UseCanonicalName On odkrywca zalecał jako obejście [5]. To przykład, jak błędna konfiguracja zabezpieczeń (security misconfiguration) serwera wzmacnia błąd w aplikacji.
W lipcu 2020 roku zmieniono w rdzeniu sposób ustalania domeny nadawcy w funkcji wp_mail(). Opis zmiany mówi, że SERVER_NAME nie daje pewnej nazwy hosta, więc używany jest adres z network_home_url(), pochodzący z ustawień witryny [6]. Wtyczki i motywy, które same składają adresy z $_SERVER['HTTP_HOST'], mogą jednak powtarzać ten sam błąd; zob. podatność we wtyczce.
Zagrożenia i skutki
Skutki zależą od tego, do czego aplikacja używa nagłówka. Przy resecie hasła jest to przejęcie konta, także administratora. Przy pamięci podręcznej jedna odpowiedź z podstawioną domeną może dotknąć wielu użytkowników [4]. Link w mailu kierujący na obcą domenę daje też materiał do phishingu, bo wiadomość przychodzi z prawdziwej strony. Oznaczenie konkretnych przypadków jako CVE ułatwia sprawdzenie, czy dana wersja oprogramowania jest podatna.
Jak się bronić
PortSwigger zaleca kilka zasad [1]:
- nie używać nagłówka
Hostw kodzie po stronie serwera, a gdzie się da, stosować adresy względne; - jeśli trzeba go użyć, sprawdzać wartość względem listy dozwolonych domen;
- nie obsługiwać nagłówków nadpisujących, zwłaszcza
X-Forwarded-Host; - ustawić równoważniki obciążenia i serwery pośredniczące tak, by przekazywały tylko żądania do dozwolonych domen;
- nie umieszczać stron wewnętrznych na tym samym serwerze co publiczne.
W WordPressie adresy należy budować z ustawień witryny, na przykład funkcją home_url(), a nie z danych żądania. Poniższy fragment ilustruje sprawdzenie nagłówka z listą dozwolonych domen.
$allowed = array( 'example.com', 'www.example.com' );
$host = strtolower( $_SERVER['HTTP_HOST'] ?? '' );
if ( ! in_array( $host, $allowed, true ) ) {
status_header( 400 );
exit;
}
Na poziomie serwera pomaga domyślny wirtualny host, który odrzuca żądania z nieznaną domeną, oraz UseCanonicalName On w Apache [7]. Reguły WAF i serwera pośredniczącego mogą dodatkowo odrzucać żądania z nagłówkiem X-Forwarded-Host pochodzącym spoza zaufanej infrastruktury, zgodnie z zaleceniem, by takich nagłówków nie obsługiwać [1].
Historia i przykłady
Przypadkiem tej klasy w rdzeniu WordPressa jest CVE-2017-8295, ujawniona 4 maja 2017 roku i dotycząca wersji do 4.7.4 [5]. Zmiana w wp_mail() z 24 lipca 2020 roku przestawiła ustalanie domeny nadawcy z SERVER_NAME na adres witryny z network_home_url() [6]. Opis tej zmiany nie wspomina o numerze CVE, więc nie należy jej traktować jako oficjalnej łatki tej konkretnej luki.
Przypisy
7- [1] HTTP Host header attacks · PortSwigger Web Security Academy
- [2] Password reset poisoning · PortSwigger Web Security Academy
- [3] RFC 9110: HTTP Semantics, sekcja 7.2 Host and :authority · IETF
- [4] Testing for Host Header Injection (WSTG v4.2) · OWASP
- [5] WordPress: możliwość resetu hasła dowolnemu użytkownikowi · Sekurak
- [6] Mail: Ensure that a server hostname can be set by using network_home_url() (commit 7504898) · WordPress (wordpress-develop, GitHub)
- [7] Apache HTTP Server 2.4: core — UseCanonicalName Directive · Apache Software Foundation