Quando effettui il login su un sito web, normalmente non devi inserire username e password ogni volta che apri una nuova pagina. L'applicazione riconosce la tua sessione e ti permette di continuare a utilizzare il servizio.
Questa comodità dipende da un meccanismo fondamentale: la gestione delle sessioni.
Se progettata correttamente, permette di mantenere l'accesso in modo sicuro. Se invece presenta configurazioni deboli, può consentire a un attaccante di impersonare un utente, accedere ai suoi dati o mantenere un accesso non autorizzato più a lungo del previsto.
Per questo motivo, la sicurezza delle sessioni web è un elemento importante nella protezione di siti WordPress, applicazioni PHP, e-commerce e piattaforme SaaS.
Che cos'è una sessione web?
Una sessione web consente a un'applicazione di riconoscere lo stesso utente tra più richieste HTTP.
Il protocollo HTTP, infatti, è sostanzialmente stateless: ogni richiesta è indipendente, a meno che l'applicazione non utilizzi meccanismi per collegarla alle precedenti.
Dopo un'autenticazione riuscita, il server può creare una sessione e assegnarle un identificativo. Il browser conserva normalmente un cookie contenente tale identificativo e lo invia nelle richieste successive verso il dominio previsto.
Il server utilizza il cookie per recuperare le informazioni associate alla sessione e stabilire se l'utente è ancora autenticato.
È importante distinguere il cookie di sessione dal contenuto della sessione stessa: il cookie può contenere soltanto un identificativo, mentre le informazioni associate vengono conservate lato server. Altre architetture utilizzano token che contengono informazioni firmate o altri meccanismi, con caratteristiche e rischi differenti.
In ogni caso, le informazioni che consentono di mantenere un accesso autenticato devono essere protette con attenzione.
Perché il furto di una sessione è pericoloso
Se un attaccante riesce a ottenere un identificativo di sessione valido o un token di accesso riutilizzabile, potrebbe riuscire a utilizzare il servizio con i privilegi della vittima.
Questo tipo di problema viene spesso definito session hijacking, cioè dirottamento della sessione.
Le conseguenze dipendono dai privilegi dell'account e dalle protezioni implementate. Potrebbero includere l'accesso a dati personali, la modifica delle impostazioni, l'esecuzione di operazioni per conto dell'utente o, nei casi più gravi, il controllo di un account amministrativo.
Non è necessario conoscere la password originale se il sistema accetta una credenziale di sessione valida senza richiedere ulteriori verifiche.
Ecco perché i cookie di autenticazione devono essere trattati come credenziali sensibili.
1. Configurare correttamente i cookie di sessione
I cookie che mantengono un utente autenticato dovrebbero utilizzare attributi di sicurezza appropriati.
Tre attributi particolarmente importanti sono Secure, HttpOnly e SameSite.
Secure
L'attributo Secure indica al browser di inviare il cookie soltanto attraverso connessioni HTTPS.
È una protezione importante perché impedisce che quel cookie venga trasmesso normalmente attraverso una connessione HTTP non cifrata.
Naturalmente, HTTPS deve essere configurato correttamente su tutto il percorso interessato: il solo attributo del cookie non sostituisce una configurazione TLS adeguata.
HttpOnly
L'attributo HttpOnly impedisce al normale codice JavaScript della pagina di leggere direttamente il cookie tramite le API del browser.
Questo riduce il rischio che un attacco XSS possa sottrarre il cookie attraverso uno script che tenta di accedere a document.cookie.
Non significa, però, che XSS diventi innocuo: uno script malevolo potrebbe comunque eseguire azioni nel contesto dell'utente, leggere informazioni accessibili alla pagina o tentare altre forme di abuso.
SameSite
L'attributo SameSite controlla quando il browser invia il cookie in richieste originate da contesti differenti.
I valori più comuni sono:
Strict: limita maggiormente l'invio del cookie nei contesti cross-site.Lax: consente alcuni invii cross-site, in particolare determinate navigazioni di primo livello.None: permette l'invio anche in contesti cross-site e richiede l'attributoSecurenei browser moderni.
La scelta dipende dal funzionamento dell'applicazione. Per esempio, flussi di autenticazione federata o integrazioni esterne potrebbero richiedere una configurazione specifica.
SameSite contribuisce alla protezione contro alcune richieste cross-site indesiderate, ma non sostituisce una strategia completa contro CSRF.
Un esempio indicativo di cookie di sessione potrebbe essere:
Set-Cookie: session_id=<valore-casuale>; Path=/; Secure; HttpOnly; SameSite=Lax
Il valore mostrato è un segnaposto, non un identificativo reale. Il dominio, il percorso e la politica di scadenza devono essere configurati in base alle esigenze dell'applicazione.
2. Utilizzare identificativi di sessione imprevedibili
Un identificativo di sessione deve essere sufficientemente casuale da rendere impraticabile indovinarlo.
Se il valore è prevedibile, viene generato con un algoritmo debole o contiene informazioni facilmente ricostruibili, un attaccante potrebbe tentare di ottenere una sessione valida senza conoscere le credenziali dell'utente.
Le applicazioni dovrebbero utilizzare i meccanismi di sessione e i generatori crittografici forniti da piattaforme e librerie affidabili.
È inoltre importante non inserire nei cookie di sessione dati personali, password o informazioni riservate non necessarie.
L'identificativo dovrebbe funzionare come una credenziale opaca: il suo valore non deve rivelare informazioni utili e deve essere protetto come un segreto.
3. Rigenerare la sessione dopo il login
Un problema noto è la session fixation.
In questo scenario, un attaccante cerca di fare in modo che la vittima utilizzi un identificativo di sessione conosciuto o controllato in precedenza. Se l'applicazione mantiene lo stesso identificativo anche dopo l'autenticazione, potrebbe permettere all'attaccante di utilizzare quella sessione.
Una misura fondamentale consiste nel rigenerare l'identificativo della sessione quando cambia il livello di autenticazione, in particolare dopo un login riuscito.
La stessa attenzione è utile quando un utente passa a privilegi più elevati o completa operazioni che modificano sensibilmente il contesto di sicurezza.
In PHP, per esempio, session_regenerate_id() consente di rigenerare l'identificativo della sessione. Tuttavia, la chiamata deve essere inserita correttamente nel flusso applicativo, gestendo anche la sessione precedente e le eventuali richieste concorrenti.
Rigenerare l'identificativo non sostituisce gli altri controlli, ma riduce il rischio che una sessione preesistente venga riutilizzata in modo improprio.
4. Definire scadenze appropriate
Una sessione non dovrebbe necessariamente rimanere valida per sempre.
Le applicazioni devono stabilire per quanto tempo mantenere attivo un accesso e quando richiedere nuovamente l'autenticazione.
È utile distinguere due concetti.
Timeout di inattività: la sessione viene invalidata dopo un periodo senza attività rilevante.
Scadenza assoluta: la sessione viene invalidata dopo un intervallo massimo dalla sua creazione, anche se l'utente continua a utilizzarla.
Una sessione con soltanto un timeout di inattività potrebbe restare valida molto a lungo se viene mantenuta continuamente attiva. Una scadenza assoluta limita invece la durata complessiva dell'accesso.
I tempi appropriati dipendono dal servizio. Un portale che mostra informazioni pubbliche e un sistema che gestisce dati finanziari o amministrativi non hanno necessariamente le stesse esigenze.
Anche la funzione "ricordami" deve essere progettata con attenzione, utilizzando credenziali persistenti dedicate, scadenze definite e procedure sicure di revoca.
5. Gestire correttamente il logout
Fare clic su "Esci" dovrebbe invalidare la sessione sul server, non limitarsi a nascondere alcune informazioni nel browser.
Se il server continua ad accettare l'identificativo precedente, una copia del cookie potrebbe restare utilizzabile fino alla sua scadenza.
Una procedura di logout robusta dovrebbe quindi:
- invalidare la sessione lato server;
- eliminare o rendere inutilizzabile la credenziale di autenticazione;
- cancellare il cookie nel browser con attributi coerenti con quelli usati per crearlo;
- gestire correttamente eventuali token di refresh o credenziali persistenti;
- impedire che la sessione revocata possa essere riutilizzata.
Nelle architetture basate su token, la revoca può richiedere strategie specifiche, perché alcuni token restano validi fino alla scadenza se il sistema non prevede controlli aggiuntivi.
Il logout dovrebbe essere testato anche su dispositivi condivisi e dopo operazioni sensibili.
6. Proteggere le sessioni dagli attacchi CSRF
Il Cross-Site Request Forgery (CSRF) si verifica quando un attaccante induce il browser di una vittima autenticata a inviare una richiesta che l'applicazione interpreta come legittima.
Il rischio nasce perché il browser può allegare automaticamente i cookie di autenticazione alle richieste dirette verso il sito interessato, in base alle regole applicabili.
Se un'applicazione non verifica adeguatamente l'intenzione dell'utente, potrebbe accettare operazioni non desiderate, come la modifica di alcune impostazioni.
Le difese possono includere:
- token anti-CSRF verificati sul server;
- attributi
SameSiteappropriati; - controlli sull'origine della richiesta, quando applicabili;
- richieste di conferma o riautenticazione per operazioni particolarmente sensibili;
- corretta gestione dei metodi HTTP e delle operazioni che modificano dati.
Non tutte le tecniche sono intercambiabili. Per esempio, i controlli sull'header Origin devono essere progettati considerando i client supportati e il flusso applicativo.
Un'altra regola importante è evitare che operazioni che modificano lo stato, come cancellazioni o cambiamenti delle credenziali, siano eseguibili semplicemente attraverso una richiesta GET.
7. Proteggere le sessioni dalle vulnerabilità XSS
Un attacco Cross-Site Scripting consente di eseguire codice JavaScript non previsto nel contesto di una pagina.
Se il codice malevolo viene eseguito all'interno di un'applicazione autenticata, può tentare di compiere azioni utilizzando i privilegi della vittima.
L'attributo HttpOnly rende più difficile sottrarre direttamente i cookie attraverso JavaScript, ma non impedisce a uno script malevolo di interagire con la pagina.
Per ridurre questo rischio è necessario prevenire XSS attraverso la corretta gestione degli input e degli output, l'uso di API sicure per manipolare il DOM e, dove appropriato, una Content Security Policy.
La sicurezza delle sessioni e quella dell'applicazione devono quindi essere considerate insieme.
8. Esempio di configurazione in PHP
In PHP è possibile impostare alcuni attributi dei cookie di sessione prima di avviare la sessione:
<?php
session_set_cookie_params([
'lifetime' => 0,
'path' => '/',
'secure' => true,
'httponly' => true,
'samesite' => 'Lax',
]);
session_start();
In questo esempio:
lifetime => 0richiede un cookie di sessione del browser, ma non costituisce da solo una politica completa di scadenza lato server;secure => truerichiede HTTPS per l'invio del cookie;httponly => trueimpedisce l'accesso diretto al cookie tramite JavaScript;samesite => 'Lax'applica una politica che limita alcuni invii cross-site.
Questo è soltanto un esempio di configurazione iniziale. In produzione bisogna anche impostare una gestione coerente delle scadenze lato server, rigenerare l'identificativo dopo il login, invalidare correttamente le sessioni e proteggere le operazioni sensibili.
La configurazione deve essere compatibile con il modo in cui l'applicazione gestisce autenticazione, sottodomini e integrazioni esterne. Inoltre, secure => true presuppone che l'applicazione sia utilizzata attraverso HTTPS.
9. Checklist per verificare la sicurezza delle sessioni
Se gestisci un sito web o una piattaforma SaaS, puoi utilizzare questa checklist come punto di partenza:
- [ ] I cookie di autenticazione utilizzano
SecureeHttpOnly? - [ ] Il valore di
SameSiteè coerente con le esigenze applicative? - [ ] Gli identificativi di sessione sono imprevedibili?
- [ ] L'identificativo viene rigenerato dopo il login e gli altri cambiamenti rilevanti dei privilegi?
- [ ] Sono previsti timeout di inattività e scadenze assolute?
- [ ] Il logout invalida realmente la sessione lato server?
- [ ] Le sessioni possono essere revocate dopo un cambio password o un evento di sicurezza?
- [ ] Le operazioni sensibili sono protette contro CSRF?
- [ ] L'applicazione protegge gli output per ridurre il rischio di XSS?
- [ ] I cookie e i token non vengono inseriti nei log o esposti in URL?
- [ ] Sono previsti controlli specifici per account amministrativi e operazioni ad alto rischio?
La checklist non sostituisce una revisione completa del codice, ma aiuta a individuare configurazioni deboli e comportamenti da approfondire.
Conclusione
Una sessione web sicura non dipende da un singolo attributo del cookie. Richiede identificativi imprevedibili, scadenze appropriate, rigenerazione dopo l'autenticazione, logout effettivo e protezioni contro vulnerabilità come CSRF e XSS.
Con MiHakero puoi analizzare i domini, le applicazioni web, le API e i servizi pubblici per individuare configurazioni e problemi rilevabili dall'esterno. Per verificare l'intera gestione delle sessioni, è utile affiancare queste analisi a test applicativi autorizzati e a una revisione delle procedure di autenticazione e logout.