In questo secondo capitolo vedremo tutte le possibilità che il browser ci mette a disposizione per proteggere il contenuto dei cookie, istruendo direttamente lo user agent dell'utente.

Se hai letto il primo capitolo, saprai che questa serie si chiama da F ad A perchè verifichiamo su securityheaders.com il punteggio ottento da blog.rev3rse.it. Se non sai di cosa sto parlando ti consiglio di leggere il primo capitolo qui.

Sicuramente se stai leggendo questo post sei consapevole del fatto che ogni cookie può essere definito e inviato al browser con specifici "flag", tra i più comuni: HttpOnly e Secure.

HttpOnly: è un flag che impedisce l’accesso "client side" ai cookie (esempio via JavaScript global variable document: document.cookie). Il beneficio maggiore di usare questo flag consiste in una protezione da attacchi che tentano di sfruttare vulnerabilità come XSS. HttpOnly, se presente, fa si che il browser restituisca una stringa vuota al posto del contenuto dei cookie (per proseguire l'esempio fatto prima, un valore vuoto verrà associato a document.cookie).

Set-Cookie: sessid=123; path=/; HttpOnly

Secure: Istruisce il browser in modo tale che invii il cookie solo attraverso una connessione sicura (HTTPS). Questo flag tenta di scongiurare la possibilità che il contenuto del cookie, se inviato in una connessione non sicura (http), possa essere intercettato da qualcosa/qualcuno posto in mezzo (vedi MITM).

Set-Cookie: sessid=123; path=/; Secure; HttpOnly

SameSite

Un altro flag interessante, anche se le sue specifiche sono ancora in draft, è SameSite che offre alcune protezioni interessanti nei confronti di vulnerabilità come CSRF e XSSI. SameSite ha due possibili configurazioni: Lax e Strict.

SameSite=lax: Istruisce il browser in modo che, in una cross site request, invii il cookie solo con alcuni metodi (es. GET e non POST).

Set-Cookie: sessid=123; path=/; SameSite=lax

SameSite=strict:Istruisce il browser in modo che non invii, in una cross site request, il cookie neanche per il metodo GET.

Set-Cookie: sessid=123; path=/; SameSite=strict

Per capire meglio gli effetti di SameSite possiamo fare un piccolo test. Ho creato un piccolo script PHP su rev3rse.it/test_cookie_set.php?setcookie=1 che invia il seguente cookie all'utente:

Set-Cookie: testcookie=foo; path=/; SameSite=strict

Navigando su rev3rse.it/test_cookie_set.php?showcookie=1 vengono mostrati i cookie inviati dal browser al sito. Partendo da rev3rse.it il risultato sarà sempre il seguente:

Cookie: session=foo; testcookie=foo;

Se creiamo una pagina HTML su localhost con un link che punta a rev3rse.it/test_cookie_set.php?showcookie=1 il cookie "testcookie" non sarà inviato dal browser perchè la request non proviene dallo stesso sito:

Cookie: session=foo;

Anche dopo un reload della pagina, il browser dell'utente continuerà a non inviare il cookie "testcookie", come spero si possa vedere dal video seguente:

Oltre ai flag, i cookie inviati al browser tramite response header "Set-Cookie" possono avere anche un prefisso. Principalmente i prefissi utilizzaibili sono __Secure e __Host e si posizionano appena prima del nome, ad esempio:

Set-Cookie: __Secure-testcookie=foo; path=/; domain=reve3rse.it; Secure

Set-Cookie: __Host-testcookie=foo; path=/; Secure

I cookie con prefix __Secure possono essere utilizzati dal browser solo se presente il flag Secure e solo su connessione sicura (HTTPS). Il cookie con questo prefix viene rifiutato dal browser se non viene inviato con il flag Secure.

I cookie con prefix __Host vengono accettati dal browser solo se presente il flag Secure, solo se sono validi per tutti i path, e quindi presentano il parametro path=/ e solo se non hanno il parametro domain.

__Secure prefix ma senza Secure flag:

Set-Cookie: __Secure-testcookie=foo; path=/; domain=reve3rse.it;

__Host prefix ma senza parametro __Host:

Set-Cookie: __Host-testcookie=foo; Secure

__Host prefix ma con parametro domain=rev3rse.it:

Set-Cookie: __Host-testcookie=foo; Secure; domain=reve3rse.it

Nginx non ha un modulo completo per poter intervenire sul Set-Cookie sia in termini di flag che di prefix (fatta eccezione per proxy_cookie_* che permette la gestione del parametro path e domain). Esiste un modulo che risolve il problema, clonabile da GitHub all'indirizzo https://github.com/AirisX/nginx_cookie_flag_module che ci permette di effettuare una configurazione di questo tipo:

location / {
    set_cookie_flag Secret HttpOnly secure SameSite;
    set_cookie_flag * HttpOnly;
    set_cookie_flag SessionID SameSite=Lax secure;
    set_cookie_flag SiteToken SameSite=Strict;
}

Video

Conclusione

Tutto questo non ci porta ad aumentare il voto di securityheaders.com perchè blog.rev3rse.it non invia cookie se non il tracking di cloudflare che è già configurato con i flag HttpOnly e Secure. Per il momento il voto rimane D ma sicuramente nei prossimi capitoli supereremo l’insufficienza.

Primo Capitolo: https://blog.rev3rse.it/security-headers-da-f-ad-a-content-security-policy/