Przedstawiamy pierwszy z serii artykułów poruszających kwestie nagłówków HTTP oraz flag dla ciasteczek mających na celu zwiększenie bezpieczeństwa web-aplikacji. W tym odcinku o fladze HttpOnly, która jest jednym ze sposobów częściowej ochrony przed atakami typu XSS.
Piszemy też o HSTS czyli HTTP Strict Transport Security.
Jeżeli atakujący znajdzie w aplikacji webowej podatność Cross-Site Scripting, może za pomocą wstrzykniętego skryptu JavaScript odczytać wartość ciasteczek. Jeżeli uda mu się dostać do ciasteczek sesyjnych, to może podszyć się pod użytkownika.
Ponieważ w większości web-aplikacji utrzymywanie sesji jest zapewniane przez ciasteczka, poznanie ich wartości równoznaczne jest z ukradnięciem tożsamości ofiary.
Jak w interakcji z serwerem przeglądarka widzi takie zabezpieczone ciasteczko? W momencie zalogowania się np. do google’a serwer wysyła nam odpowiedź z różnymi nagłówkami, m.in. z poleceniami ustawienia wartości ciasteczek. Na poniższym przykładzie, cookie SSID posiada ustawioną flagę HttpOnly, co wskazuje prawdopodobnie na to, że jest to cookie sesyjne.
HTTP/1.1 200 OK
Cache-Control: private, max-age=0
Content-Encoding: gzip
Content-Length: 3166
Content-Type: text/html; charset=UTF-8
Date: Thu, 27 Jun 2013 17:19:07 GMT
Expires: Thu, 27 Jun 2013 17:19:07 GMT
Server: GSE
Set-Cookie: GoogleAccountsLocale_session=pl; Secure
Set-Cookie: GAPS=1:4gDZvK5g:o5fM52umoiFpi0So;Path=/;Expires=Sat, 27-Jun-2015 17:19:06 GMT;Secure;HttpOnly
Set-Cookie: HSID=AeH9gHkGSn4x2JsR9;Domain=.google.com;Path=/;Expires=Sat, 27-Jun-2015 17:19:06 GMT;HttpOnly
Set-Cookie: SSID=AXftJqsxaxsASWe77;Domain=.google.com;Path=/;Expires=Sat, 27-Jun-2015 17:19:06 GMT;Secure;HttpOnly
Strict-Transport-Security: max-age=2592000; includeSubDomains
X-Content-Type-Options: nosniff
x-frame-options: Deny
x-xss-protection: 1; mode=block
X-Firefox-Spdy: 3
Flaga HttpOnly wpływa na bezpieczeństwo w ten sposób, że blokuje próby odczytu cookie z tą flagą przez API inne niż HTTP. Oznacza to, że np. JavaScript nie może odczytać takiego cookie. Atrybut jest case insensitive.
Można ją ustawić na kilka różnych sposobów. Pierwszym miejscem jest kod strony, np. w C# wyglądało by to tak:
<%@ Page Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
</script runat="server">
void Page_Load(object sender, EventArgs e)
{
// Stworz nowe ciasteczko
HttpCookie myHttpOnlyCookie = new HttpCookie("LastVisit", DateTime.Now.ToString());
// Ustaw flagę HttpOnly na true, uwaga domyslna wartość to false!!
myHttpOnlyCookie.HttpOnly = true;
myHttpOnlyCookie.Name = "MyHttpOnlyCookie";
Response.AppendCookie(myHttpOnlyCookie);
}
</script>
Można też włączyć ustawienie tej flagi domyślnie dla wszystkich cookies modyfikując odpowiedni parametr w pliku web.config (domyślnie jest to ustawione na false):
<system.web>
<httpCookies httpOnlyCookies="true">
</system.web>
Z kolei dla języka PHP, odpowiednie ustawienie można zrealizować w konfiguracji php.ini:
session.cookie_httponly = True
Warto również w tym miejscu ustawić dyrektywę, która mówi, że do utrzymywania sesji moduł będzie używać tylko cookies. Od PHP 5.3.0 jest to ustawione domyślnie na True.
session.use_only_cookies = True
Inny sposobem jest użycie mod_headers i skonfigurowanie go w taki sposób:
<IfModule headers_module>
Header always edit Set-Cookie ^(.*)$ $1;HttpOnly
</IfModule>
Warto pamiętać że flaga HttpOnly chroni nas tylko do pewnego stopnia przed jednym skutkiem wykorzystania XSS (wykradzeniem ciasteczek sesyjnych). Chroni do pewnego stopnia, ponieważ jeżeli aplikacja jest podatna na XSS, to atakujący nie musi koniecznie celować w kradzież ciasteczek. Może być to choćby dynamiczna podmiana wyglądu strony, czy uruchomienie w przeglądarce keyloggera. Cały czas podstawową metodą ochrony przed XSS pozostaje odpowiednia walidacja danych, które wyświetlamy w aplikacji.
Od redakcji: dziękujemy Piotrowi Bratkowskiemu (naszemu czytelnikowi) za podzielenie się tekstem i czekamy na kolejne odcinki :-)
–Piotr Bratkowski (Piotrek.Bratkowski<at>gmail.com)
W PHP można również przed wywołaniem funkcji session_start() użyć funkcji session_set_cookie_params która jako ostatni parametr opcjonalny przyjmuje bool $httponly
http://www.php.net/manual/en/function.session-set-cookie-params.php