Il web è ormai il punto d’accesso principale ad una vasta gamma di servizi, la maggior parte dei quali richiede autenticazione, cioè la capacità di determinare l’identità di chi effettua un determinato accesso o richiesta. Si tratti di e-banking, e-commerce o social network, un numero sempre crescente di servizi ci richiede ormai di “presentarci” tramite la sottomissione di credenziali di accesso, tipicamente nella forma di nome utente e password. Si parla molto di protezione delle password, di come sia importante scegliere sempre password lunghe ed imprevedibili, nonché di evitare il riuso della stessa password presso servizi diversi. I browser più moderni inoltre ci avvisano del pericolo di inviare la propria password su HTTP, cercando di spingere un’adozione più pervasiva di HTTPS. Tutto questo è fondamentale per garantire la sicurezza del proprio account, perché un attaccante in grado di presentare la nostra password presso un servizio online è effettivamente in grado di impersonarci presso di esso, acquisendo i nostri stessi privilegi.
L’anatomia di una sessione web
Proteggere appropriatamente la propria password è necessario per la sicurezza informatica del proprio account, ma purtroppo non è sufficiente. Per capirne il motivo, è importante osservare una caratteristica fondamentale del protocollo HTTP(S), su cui tutto il web è costruito: l’assenza di stato. Tecnicamente questo significa che due richieste HTTP(S) ricevute da uno stesso servizio appaiono sempre scorrelate tra loro, come se fossero due richieste indipendenti. Una conseguenza importante della natura stateless di HTTP(S) è che, dopo aver verificato la nostra password, i servizi online si “dimenticano” di noi, perché le richieste successive non comprendono più le nostre credenziali d’accesso. Questo problema può essere risolto implementando un’opportuna logica sul servizio online, tipicamente basata sull’utilizzo di cookie. Un cookie non è altro che un piccolo pezzo di informazione, rappresentato come una coppia chiave-valore, che può venire salvato da un servizio online all’interno del nostro browser. Il browser provvederà poi a ripresentare il cookie automaticamente in ogni richiesta HTTP(S) diretta al servizio che lo ha registrato. Se un cookie contiene abbastanza informazione per identificare un utente in maniera univoca, esso può essere utilizzato come un meccanismo di autenticazione alternativo alla password, consentendo di stabilire una sessione di richieste correlate. Più concretamente, una tipica sessione web è stabilita come segue:
- Un utente (chiamiamolo Alice) fornisce le proprie credenziali di accesso al servizio online nella forma di nome utente e password;
- Il servizio online verifica la correttezza delle credenziali ricevute, quindi genera un nuovo cookie e lo salva nel browser di Alice. Tale cookie, spesso chiamato cookie di sessione, contiene un valore casuale ed imprevedibile, che consente di identificare Alice nelle richieste successive;
- Il browser di Alice allega automaticamente il cookie a tutte le richieste al servizio online, che è così in grado di autenticare nuovamente Alice.
Questo paradigma è così popolare sul web che tutti i framework di sviluppo più utilizzati forniscono supporto nativo per la gestione delle sessioni. Per esempio PHP utilizza la chiave PHPSESSID per identificare il proprio cookie di sessione, mentre ASP impiega di default la chiave ASPSESSIONID.
L’importanza di proteggere i cookie e sessione
Poiché i cookie di sessione sono utilizzati come meccanismo di autenticazione, proteggerli in modo appropriato è fondamentale. Ci sono molti attacchi contro le sessioni web, di diversa complessità e pericolosità, ma il più intuitivo da capire è senza dubbio il furto di un cookie di sessione, perché un attaccante in grado di rubare un nostro cookie di sessione sarà in grado di impersonarci presso il servizio che ha registrato il cookie nel nostro browser. Questo problema è ben noto ed infatti i browser implementano meccanismi atti a garantire la confidenzialità dei cookie di sessione. La prima linea di difesa è fornita dalla Same Origin Policy (SOP), che isola in lettura e scrittura contenuti web forniti da servizi “scorrelati” fra loro. Per esempio uno script in esecuzione nell’homepage di https://www.evil.com non sarà in grado di leggere o scrivere i cookie impostati da https://www.bank.com. Purtroppo però la SOP non è sufficiente per impedire il furto dei cookie di sessione ed i web developer più accorti sono costretti ad utilizzare due ulteriori meccanismi di protezione per irrobustire le proprie sessioni: HttpOnly e Secure, due attributi assegnabili ai cookie per richiedere al browser garanzie di sicurezza aggiuntive sul loro utilizzo.
L’attributo HttpOnly
Se un cookie è marcato HttpOnly, esso diventa inaccessibile da ogni script, anche quelli cui normalmente la SOP consentirebbe l’accesso. Per esempio, neppure gli script in esecuzione in una pagina di https://www.bank.com possono leggere i cookie HttpOnly impostati da tale servizio. Questo è fondamentale per chiudere due vettori d’attacco:
- Script malevoli caricati da terze parti: se https://www.bank.com importa uno script da https://www.evil.com, tale script viene eseguito con gli stessi privilegi di uno script che è stato caricato direttamente da https://www.bank.com ed ottiene quindi accesso ai cookie impostati da tale servizio;
- Cross Site Scripting (XSS): se https://www.bank.com non sanitizza adeguatamente i propri input, un attaccante può essere in grado di iniettare contenuti arbitrari su tale servizio, che otterrebbero quindi accesso ai cookie impostati da esso. (Discutere in dettaglio gli XSS è al di là dello scopo di questo articolo.)
Visto quanto è comune importare script da terze parti, per esempio per motivi di profiling o advertisement, e la diffusione “in the wild” di vulnerabilità XSS, marcare i cookie di sessione come HttpOnly è un’ottima pratica per evitare di indebolire l’autenticazione.
L’attributo Secure
Normalmente i cookie impostati da https://www.bank.com sono allegati a tutte le richieste verso www.bank.com, indipendentemente dal fatto che tali richieste siano su HTTP oppure su HTTPS. Questo implica che un attaccante in grado di controllare il traffico di rete può rubare i cookie di sessione utilizzati dal servizio nel momento in cui il browser della vittima invia almeno una richiesta al servizio su HTTP. Si noti che un attaccante con il controllo della rete può forzare la generazione di tale richiesta HTTP anche se il servizio è implementato interamente su HTTPS, per esempio manipolando il traffico HTTP ricevuto da un altro servizio in modo da forzare un redirect verso http://www.bank.com: anche se tale servizio non fosse disponibile, il browser proverebbe a contattarlo allegando i cookie. Per ovviare a questo problema, è possibile marcare i cookie di sessione come Secure, chiedendo così al browser di allegare tali cookie solo a richieste HTTPS.
Per concludere
L’importanza di proteggere le password è un punto ormai ben chiaro e stabilito, ma non si deve sottostimare l’importanza di proteggere adeguatamente i cookie di sessione. Purtroppo uno studio del 2015 evidenzia che gli attributi HttpOnly e Secure non sono molto utilizzati “in the wild”, anche se un’analisi preliminare dei siti più popolari di Alexa sembra suggerire che la situazione stia migliorando negli ultimi anni. Il mondo delle sessioni web è complesso ed esposto ad un numero sorprendentemente elevato di attacchi, di cui il furto dei cookie di sessione rappresenta solo una sfaccettatura. Un survey del 2017 fornisce una panoramica comprensiva delle superfici d’attacco più popolari contro le sessioni web.
Riferimenti
Lo studio del 2015 è “Bugliesi, Calzavara, Focardi, Khan – CookiExt: patching the browser against session hijacking attacks”, pubblicato sul Journal of Computer Security. Il survey del 2017 è “Calzavara, Focardi, Squarcina, Tempesta – Surviving the Web: a journey into web session security”, pubblicato su ACM Computing Surveys.