NFsec Logo

HTTP Cache Poisoning via Host Header Injection

27/06/2013 w Ataki Internetowe, Bezpieczeństwo Brak komentarzy.  (artykuł nr 417, ilość słów: 745)

P

owszechną praktyką wśród programistów piszących własne webaplikacje oraz webowych frameworków odkrywających koło od nowa jest poleganie na wartościach zwracanych w nagłówku HTTP Host. Jest to bardzo wygodny sposób na gwarancję, że ta sama aplikacja zostanie uruchomiona na localhoście, serwerach środowiska: developerskiego, testowego, produkcyjnego, innych domenach i subdomenach itd., bez wprowadzania modyfikacji w kod aplikacji. Prosty przykład w PHP:

Link do logowania:

<a href="<?php echo $_SERVER['HTTP_HOST'] ?>/logowanie">Login</a>

Link do stylów CSS:

<link rel="stylesheet" type="text/css" href="<?php echo $_SERVER['HTTP_HOST'] ?>/st.css">

Link do skryptów JS:

<script src="<?php echo $_SERVER['HTTP_HOST'] ?>/jquery.js?v=1.2.3">  

Okazuje się, że to bardzo zły pomysł – niezależnie od języka programowania. Wartość nagłówka Host w protokole HTTP jest dowolnym tekstem kontrolowanym i przekazywanym przez klienta, ale czasami traktuje się go tak, jakby był bezpieczną zmienną – a nią nie jest. Za przykład może tutaj posłużyć mechanizm HTTP cache umieszczony gdzieś po drodze pomiędzy webaplikacją, a użytkownikami. Może to być dowolne proxy typu cache zainstalowane na tym samym serwerze WWW, co aplikacja lub odseparowany CDN (ang. Content Delivery Network), którego zadaniem jest także rozkładanie ruchu i buforowanie zapytań. Jeśli konfiguracja samej aplikacji jest nieprawidłowa, a także serwera WWW i akceleratora HTTP – atakujący jest w stanie wstrzyknąć w taki system naczyń połączonych dowolny nagłówek HTTP typu Host i przepisać adresy na każdej stronie tak, aby kierowały do jego spreparowanych zasobów (np. szkodliwego oprogramowania). Tego typu akcja nie będzie jednorazowa ponieważ mechanizm cache – mający określony czas wygaśnięcia obiektów – będzie przez jakiś czas zwracał użytkownikom podrobione adresy. Po jego wygaśnięciu i odświeżeniu – atakujący może ponownie dokonać wstrzyknięcia nagłówka – i tak cyklicznie przedłużać atak. Przykładowy scenariusz takiego ataku:

$ telnet startup.com 80
Trying 1.2.3.4...
Connected to startup.com.
Escape character is '^]'.
GET /index.html HTTP/1.1
User-Agent: X-Agresor
Host: attacker.com

HTTP/1.1 200 OK
Date: Wed, 10 Jun 2013 00:27:45 GMT
Server: Apache
Cache-Control: max-age=9600
Expires: Wed, 17 Jun 2014 00:27:45 GMT
Content-Length: 2959
Content-Type: text/html; charset=utf-8

<html>
  <head>
    <title>StartUP</title>
  </head>
  <body>
    <a href="http://attacker.com/logowanie">Login</a>
    <link rel="stylesheet" type="text/css" href="http://attacker.com/st.css">
    <script src="http://attacker.com/jquery.js?v=1.2.3"> 
[... dalszy kod strony...]
   </body>
</html>

Tak spreparowana strona (nagłówek Host: startup.com został zamieniony na Host: attacker.com) zostanie wstrzyknięta do pamięci cache i serwowana użytkownikom. Istnieje jeszcze duże prawdopodobieństwo, że dzięki nagłówkom takim jak: Cache-Control oraz Expires zostanie ona dodatkowo zapisana w pamięci cache przeglądarki użytkownika.

Jak zabezpieczyć się przed tego typu sytuacją? Zaczynając od naszej webaplikacji – jeśli koniecznie chcemy korzystać z dynamicznie dostarczanego nagłówka – powinna powstać lista dozwolonych jego wartości, która za pomocą walidacji by dopuszczała tylko prawidłowe adresy (również ich składnie). Przykładem może być mechanizm host header validation użyty w frameworku Django. Niektóre webaplikacje zamiast zmiennej $_SERVER['HTTP_HOST'] wykorzystują jako zamiennik $_SERVER['SERVER_NAME'], co teoretycznie jest bezpieczniejsze, jeśli użyjemy odpowiedniej konfiguracji serwera WWW – w przypadku serwera Apache chodzi o włączenie opcji UseCanonicalName, która czyni wartość SERVER_NAME bardziej zaufaną. W serwerze Nginx osiągniemy to określając dokładną (nie wildcardową) wartość server_name. Bardzo dobrym pomysłem jest również używanie hostów wirtualnych typu catch-all. Są to vhosty, do których odwołują się serwery WWW, jeśli w żądaniu klienta pojawi się nierozpoznany / niezdefiniowany nagłówek typu Host. Powinny być one pierwszym zdefiniowanym vhostem w naszym serwerze (instrukcje dla serwera Apache oraz Nginx). Analogiczną walidację dozwolonych nagłówków typu host powinniśmy wprowadzić dla używanej warstwy cache. Na przykład w serwerze Varnish mógłby to być zapis:

if (req.http.host !~ "^(?i)startup.com$") {
 error 500;
}

Zatruwanie pamięci cache jest tylko jednym z przykładów, jakie daje możliwość wstrzyknięcia tego nagłówka HTTP. W zależności od mechanizmów webaplikacji, które są podatne na tego rodzaju atak możliwe jest również przeprowadzenie takich ataków jak: Cross-Site Scripting (XSS), HTTP: Response Smuggling, Splitting oraz Request Smuggling, czy File Download Injection.

Więcej informacji: HTTP Cache Poisoning via Host Header Injection, Practical HTTP Host header attacks, Divide and Conquer – HTTP Response Splitting, Web Cache Poisoning Attacks, and Related Topics, What About HTTP Header Injection?

Kategorie K a t e g o r i e : Ataki Internetowe, Bezpieczeństwo

Tagi T a g i : , , , , , , , , ,

Komentowanie tego wpisu jest zablokowane.