Qual è il modo migliore per prevenire il dirottamento della sessione?


124

In particolare ciò riguarda l'utilizzo di un cookie di sessione client per identificare una sessione sul server.

È la risposta migliore per utilizzare la crittografia SSL / HTTPS per l'intero sito Web e hai la migliore garanzia che nessun uomo in mezzo agli attacchi sarà in grado di annusare un cookie di sessione client esistente?

E forse il secondo migliore per usare una sorta di crittografia sul valore della sessione stessa che è memorizzato nel tuo cookie di sessione?

Se un utente malintenzionato ha accesso fisico a una macchina, può comunque guardare al filesystem per recuperare un cookie di sessione valido e utilizzarlo per dirottare una sessione?

Risposte:


140

La crittografia del valore della sessione non avrà alcun effetto. Il cookie di sessione è già un valore arbitrario, la crittografia genererà solo un altro valore arbitrario che può essere annusato.

L'unica vera soluzione è HTTPS. Se non vuoi fare SSL su tutto il tuo sito (forse hai problemi di prestazioni), potresti essere in grado di cavartela solo con SSL che protegge le aree sensibili. Per fare ciò, assicurati innanzitutto che la tua pagina di accesso sia HTTPS. Quando un utente accede, imposta un cookie sicuro (il che significa che il browser lo trasmetterà solo su un collegamento SSL) oltre al normale cookie di sessione. Quindi, quando un utente visita una delle tue aree "sensibili", reindirizzalo a HTTPS e verifica la presenza di quel cookie sicuro. Un vero utente lo avrà, un dirottatore della sessione no.

EDIT : questa risposta è stata originariamente scritta nel 2008. Adesso è il 2016 e non c'è motivo di non avere SSL nell'intero sito. Niente più HTTP in chiaro!


28
HTTPS impedirà solo lo sniffing. Ma se hai un XSS, o gli ID di sessione possono essere indovinati facilmente, o sei vulnerabile alla fissazione della sessione, o la memoria dell'ID di sessione è debole (iniezione SQL?), SSL non migliorerà affatto.
Calimo,

5
@Josh Se un utente malintenzionato ha accesso fisico a una macchina, può comunque guardare al filesystem per recuperare un cookie di sessione valido e usarlo per dirottare una sessione?
Pacerier,

72
Se un utente malintenzionato ha accesso fisico a un filesystem, non è necessario dirottare una sessione.
Josh Hinman,

25
@Josh. Non è vero, a volte un utente ha un tempo limitato di accesso fisico a un filesystem. Immagina un laptop lasciato sbloccato da un collega che si precipita in bagno, ora tutto quello che devo fare è andare su quel laptop, installare il plugin EditThisCookie, prendere i suoi cookie su plus.google.com usando la funzione di esportazione EditThisCookie e ora ho il suo account . Tempo impiegato: 18 secondi.
Pacerier,

1
Sono abbastanza sicuro che Google avrà una sorta di funzionalità di sicurezza integrata poiché questa è ovviamente la prima cosa che potresti pensare quando parli del dirottamento della sessione
xorinzor,

42

SSL aiuta solo con gli attacchi di sniffing. Se un utente malintenzionato ha accesso al tuo computer, suppongo che possano copiare anche il tuo cookie sicuro.

Per lo meno, assicurati che i vecchi cookie perdano il loro valore dopo un po '. Anche un attacco di dirottamento riuscito verrà contrastato quando il cookie smetterà di funzionare. Se l'utente dispone di un cookie di una sessione che ha effettuato l'accesso più di un mese fa, è necessario immettere nuovamente la password. Assicurati che ogni volta che un utente fa clic sul link "disconnetti" del tuo sito, l'UUID della vecchia sessione non possa più essere utilizzato.

Non sono sicuro se questa idea funzionerà, ma qui va: Aggiungi un numero seriale nel cookie della sessione, forse una stringa come questa:

SessionUUID, Numero di serie, Data / ora correnti

Crittografa questa stringa e usala come cookie di sessione. Modifica periodicamente il numero seriale, magari quando il cookie ha 5 minuti e quindi reinvia il cookie. Puoi anche riemetterlo su ogni visualizzazione di pagina se lo desideri. Sul lato server, tenere un registro dell'ultimo numero seriale emesso per quella sessione. Se qualcuno invia un cookie con un numero di serie errato, significa che un utente malintenzionato potrebbe utilizzare un cookie che ha intercettato in precedenza, invalidando l'UUID di sessione e chiedendo all'utente di reinserire la password e quindi riemettere un nuovo cookie.

Ricorda che il tuo utente potrebbe avere più di un computer, quindi potrebbe avere più di una sessione attiva. Non fare qualcosa che li costringe ad accedere nuovamente ogni volta che passano da un computer all'altro.


So che questo è un vecchio post, ma volevo solo includere che se un utente malintenzionato dovesse dirottare la sessione all'interno della finestra assegnata dal "numero di serie", questo non lo influenzerebbe.
schiaccia il

@crush, ma poi l'attaccante sarebbe bloccato dopo la finestra assegnata, giusto? Quindi almeno la finestra di attacco è piccola (ehm).
Johanneke,

2
L'unico problema è che se l'utente lascia il tuo sito Web per 5 minuti, dovrà accedere nuovamente
elipoultorak

21

Hai mai pensato di leggere un libro sulla sicurezza di PHP? Altamente raccomandato.

Ho avuto molto successo con il seguente metodo per i siti non certificati SSL.

  1. Disabilita più sessioni con lo stesso account, assicurandoti di non verificarlo solo tramite l'indirizzo IP. Piuttosto controlla tramite token generato al momento dell'accesso che viene archiviato con la sessione degli utenti nel database, nonché l'indirizzo IP, HTTP_USER_AGENT e così via

  2. Utilizzo di collegamenti ipertestuali basati su relazioni Genera un collegamento (ad es. Http://example.com/secure.php?token=2349df98sdf98a9asdf8fas98df8 ) Il collegamento viene aggiunto con una stringa MD5 salata casuale x-BYTE (dimensione preferita), al reindirizzamento della pagina generato casualmente il token corrisponde a una pagina richiesta.

    • Alla ricarica, vengono eseguiti diversi controlli.
    • Indirizzo IP di origine
    • HTTP_USER_AGENT
    • Token di sessione
    • ottieni il punto.
  3. Cookie di autenticazione di sessione a breve durata. come pubblicato sopra, una buona idea è un cookie contenente una stringa sicura, che è uno dei riferimenti diretti alla validità delle sessioni. Far scadere ogni x minuti, riemettere quel token e risincronizzare la sessione con i nuovi dati. In caso di errata corrispondenza dei dati, disconnettere l'utente o far autenticare nuovamente la sessione.

Non sono affatto un esperto in materia, ho avuto un po 'di esperienza in questo particolare argomento, spero che un po' di questo aiuti qualcuno là fuori.


4
Ci sono dei libri che consiglieresti?
Rikki,

1
Soprattutto dato che l'OP non ha indicato nulla in particolare su PHP, direi che è meglio guardare solo un libro di sicurezza generale (soprattutto perché la sicurezza tra lingue diverse differisce solo nei dettagli di implementazione, ma i concetti rimangono gli stessi).
1

nel 2017, anche Facebook / Gmail ecc. consente più sessioni con lo stesso account (soprattutto con dispositivi mobili) a meno che non odi i tuoi utenti, il numero 1 è un po 'obsoleto.
cowbert,

20
// Collect this information on every request
$aip = $_SERVER['REMOTE_ADDR'];
$bip = $_SERVER['HTTP_X_FORWARDED_FOR'];
$agent = $_SERVER['HTTP_USER_AGENT'];
session_start();

// Do this each time the user successfully logs in.
$_SESSION['ident'] = hash("sha256", $aip . $bip . $agent);

// Do this every time the client makes a request to the server, after authenticating
$ident = hash("sha256", $aip . $bip . $agent);
if ($ident != $_SESSION['ident'])
{
    end_session();
    header("Location: login.php");
    // add some fancy pants GET/POST var headers for login.php, that lets you
    // know in the login page to notify the user of why they're being challenged
    // for login again, etc.
}

Ciò che fa è catturare informazioni "contestuali" sulla sessione dell'utente, informazioni che non dovrebbero cambiare durante la vita di una singola sessione. Un utente non sarà al computer negli Stati Uniti e in Cina allo stesso tempo, giusto? Quindi, se l'indirizzo IP cambia improvvisamente all'interno della stessa sessione, il che implica fortemente un tentativo di dirottamento della sessione, quindi si protegge la sessione chiudendo la sessione e costringendo l'utente a riautenticare. Questo ostacola il tentativo di hacking, ma anche l'attaccante è costretto a effettuare il login invece di accedere alla sessione. Avvisare l'utente del tentativo (ajax un po '), e vola, leggermente infastidito + utente informato e la loro sessione / informazione è protetta.

Aggiungiamo User Agent e X-FORWARDED-FOR per fare del nostro meglio per catturare l'unicità di una sessione per i sistemi dietro proxy / reti. Potresti essere in grado di utilizzare più informazioni allora, sentiti libero di essere creativo.

Non è al 100%, ma è dannatamente efficace.

C'è altro che puoi fare per proteggere le sessioni, farle scadere, quando un utente lascia un sito Web e torna, forse costringe ad accedere nuovamente. Puoi rilevare un utente che esce e ritorna catturando un HTTP_REFERER vuoto (il dominio è stato digitato nella barra dell'URL) o verificare se il valore in HTTP_REFERER è uguale al tuo dominio o meno (l'utente ha fatto clic su un collegamento esterno / predisposto per raggiungere il tuo posto).

Scade le sessioni, non lasciare che rimangano valide a tempo indeterminato.

Non fare affidamento sui cookie, possono essere rubati, è uno dei vettori di attacco per il dirottamento della sessione.


3
Mi sono imbattuto in una situazione prima in cui un determinato ISP (abbastanza grande, ma tecnicamente arretrato) avrebbe cambiato l'IP del browser dell'utente di volta in volta in base al reinstradamento delle connessioni dei suoi utenti. Ciò ha reso il controllo REMOTE_ADDR restituito falsi negativi per noi.
goofballLogic

Perché preoccuparsi di creare un hash? $_SESSION['ident'] = $aip . $bip . $agent;sarebbe altrettanto sicuro.
Dan Bray,

2
Se hai utenti di dispositivi mobili che utilizzano il tuo sito Web in movimento e si spostano da un punto di accesso all'altro, i loro IP continueranno a cambiare e continueranno a essere disconnessi dal loro account.
Kareem,

Che dire di proxy e VPN? Chiunque utilizzi un proxy TOR verrà costantemente disconnesso dai propri account .. in effetti ogni pochi minuti.
Bradley il

Anche se lo trascuri, gli indirizzi IP possono essere manipolati dal client, quindi questo non farebbe molto per dissuadere un attaccante.
Bradley il

9

Prova il protocollo Secure Cookie descritto in questo documento da Liu, Kovacs, Huang e Gouda:

Come indicato nel documento:

Un protocollo cookie sicuro che corre tra un client e un server deve fornire i seguenti quattro servizi: autenticazione, riservatezza, integrità e anti-replay.

Per quanto riguarda la facilità di implementazione:

In termini di efficienza, il nostro protocollo non prevede alcuna ricerca nel database o crittografia a chiave pubblica. In termini di implementabilità, il nostro protocollo può essere facilmente implementato su un server Web esistente e non richiede alcuna modifica alla specifica dei cookie di Internet.

In breve: è sicuro, leggero, funziona perfettamente per me.


9
Il tuo link è una specifica del protocollo - hai un link a un'implementazione? Sarebbe grandioso, grazie.
Adam,

9

Non esiste alcun modo per impedire il dirottamento della sessione al 100%, ma con un certo approccio possiamo ridurre il tempo impiegato da un utente malintenzionato a dirottare la sessione.

Metodo per prevenire il dirottamento della sessione:

1 - usa sempre la sessione con certificato ssl;

2 - invia cookie di sessione solo con httponly impostato su true (impedisce a javascript di accedere ai cookie di sessione)

2 - usa ID rigenerazione sessione all'accesso e alla disconnessione (nota: non utilizzare rigenerazione sessione ad ogni richiesta perché se hai una richiesta Ajax consecutiva hai la possibilità di creare più sessioni.)

3 - imposta un timeout di sessione

4 - memorizza l'agente utente del browser in una variabile $ _SESSION e confronta con $ _SERVER ['HTTP_USER_AGENT'] ad ogni richiesta

5 - imposta un cookie token e imposta il tempo di scadenza di quel cookie su 0 (fino alla chiusura del browser). Rigenera il valore del cookie per ogni richiesta (per la richiesta Ajax non rigenerare il cookie token). EX:

    //set a token cookie if one not exist
    if(!isset($_COOKIE['user_token'])){
                    //generate a random string for cookie value
        $cookie_token = bin2hex(mcrypt_create_iv('16' , MCRYPT_DEV_URANDOM));

        //set a session variable with that random string
        $_SESSION['user_token'] = $cookie_token;
        //set cookie with rand value
        setcookie('user_token', $cookie_token , 0 , '/' , 'donategame.com' , true , true);
    }

    //set a sesison variable with request of www.example.com
    if(!isset($_SESSION['request'])){
        $_SESSION['request'] = -1;
    }
    //increment $_SESSION['request'] with 1 for each request at www.example.com
    $_SESSION['request']++;

    //verify if $_SESSION['user_token'] it's equal with $_COOKIE['user_token'] only for $_SESSION['request'] > 0
    if($_SESSION['request'] > 0){

        // if it's equal then regenerete value of token cookie if not then destroy_session
        if($_SESSION['user_token'] === $_COOKIE['user_token']){
            $cookie_token = bin2hex(mcrypt_create_iv('16' , MCRYPT_DEV_URANDOM));

            $_SESSION['user_token'] = $cookie_token;

            setcookie('user_token', $cookie_token , 0 , '/' , 'donategame.com' , true , true);
        }else{
            //code for session_destroy
        }

    }

            //prevent session hijaking with browser user agent
    if(!isset($_SESSION['user_agent'])){
        $_SESSION['user_agent'] = $_SERVER['HTTP_USER_AGENT'];
    }

    if($_SESSION['user_agent'] != $_SERVER['HTTP_USER_AGENT']){
      die('session hijaking - user agent');
    }

nota: non rigenerare il cookie token con la richiesta ajax nota: il codice sopra è un esempio. nota: se gli utenti si disconnettono, il token cookie deve essere distrutto e la sessione

6 - non è un buon approccio usare l'ip utente per prevenire il dirottamento della sessione perché l'ip di alcuni utenti cambia con ogni richiesta. CHE INTERESSANO GLI UTENTI VALIDI

7 - personalmente memorizzo i dati della sessione nel database, dipende da te quale metodo adotti

Se trovi errori nel mio approccio, per favore correggimi. Se hai altri modi per prevenire l'hyjaking della sessione, per favore dimmelo.


ciao, sto cercando di prevenire il dirottamento della sessione (in ASP.NET) e ho considerato tutti i passaggi sopra indicati. Funziona approssimativamente ma quando uso la modalità browser InPrivateBrowsing / incognito la sessione viene dirottata. Potete per favore suggerire qualche cosa aggiuntiva da aggiungere nella stringa sessionId?
Vishwanath Mishra,

4

Assicurarsi di non utilizzare numeri interi incremting per gli ID di sessione. Molto meglio usare un GUID o qualche altra stringa di caratteri generata in modo casuale lungo.


3

Esistono molti modi per creare protezione contro il dirottamento della sessione, tuttavia tutti riducono la soddisfazione degli utenti o non sono sicuri.

  • Controlli IP e / o X-FORWARDED-FOR. Funzionano e sono abbastanza sicuri ... ma immagina il dolore degli utenti. Arrivano in un ufficio con WiFi, ottengono un nuovo indirizzo IP e perdono la sessione. Devi accedere di nuovo.

  • Controlli dell'agente utente. Come sopra, la nuova versione del browser è fuori uso e si perde una sessione. Inoltre, questi sono davvero facili da "hackerare". È banale per gli hacker inviare stringhe UA false.

  • token localStorage. All'accesso generare un token, archiviarlo nella memoria del browser e archiviarlo in cookie crittografato (crittografato sul lato server). Ciò non ha effetti collaterali per l'utente (localStorage persiste attraverso gli aggiornamenti del browser). Non è così sicuro - come è solo la sicurezza attraverso l'oscurità. Inoltre, potresti aggiungere un po 'di logica (crittografia / decrittografia) a JS per oscurarla ulteriormente.

  • Ristampa dei cookie. Questo è probabilmente il modo giusto per farlo. Il trucco è consentire a un solo client di utilizzare un cookie alla volta. Pertanto, l'utente attivo riceverà nuovamente i cookie ogni ora o meno. Il vecchio cookie viene invalidato se viene emesso uno nuovo. Gli hack sono ancora possibili, ma molto più difficili da fare: sia un hacker che un utente valido riceveranno l'accesso rifiutato.


1

Consideriamo che durante la fase di accesso client e server possono concordare un valore salt segreto. Successivamente il server fornisce un valore di conteggio ad ogni aggiornamento e si aspetta che il client risponda con l'hash del (salt + segreto). Il potenziale dirottatore non ha alcun modo per ottenere questo valore salato segreto e quindi non può generare l'hash successivo.


3
Ma come vuoi conservare questo sale sul lato client che nessuno potrebbe rubarlo?
Dcortez,

1

AFAIK l'oggetto sessione non è accessibile sul client, poiché è memorizzato sul server web. Tuttavia, l'id di sessione viene memorizzato come cookie e consente al server Web di tenere traccia della sessione dell'utente.

Per impedire il dirottamento della sessione utilizzando l'id di sessione, è possibile memorizzare una stringa con hash all'interno dell'oggetto sessione, creata utilizzando una combinazione di due attributi, addr remoto e porta remota, a cui è possibile accedere sul server Web all'interno dell'oggetto richiesta. Questi attributi associano la sessione utente al browser in cui l'utente ha effettuato l'accesso.

Se l'utente accede da un altro browser o da una modalità di navigazione in incognito sullo stesso sistema, l'indirizzo IP rimarrà lo stesso, ma la porta sarà diversa. Pertanto, quando si accede all'applicazione, all'utente verrà assegnato un ID sessione diverso dal server Web.

Di seguito è riportato il codice che ho implementato e testato copiando l'id di sessione da una sessione a un'altra. Funziona abbastanza bene. Se c'è una scappatoia, fammi sapere come l'hai simulata.

@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    HttpSession session = request.getSession();
    String sessionKey = (String) session.getAttribute("sessionkey");
    String remoteAddr = request.getRemoteAddr();
    int remotePort = request.getRemotePort();
    String sha256Hex = DigestUtils.sha256Hex(remoteAddr + remotePort);
    if (sessionKey == null || sessionKey.isEmpty()) {
        session.setAttribute("sessionkey", sha256Hex);
        // save mapping to memory to track which user attempted
        Application.userSessionMap.put(sha256Hex, remoteAddr + remotePort);
    } else if (!sha256Hex.equals(sessionKey)) {
        session.invalidate();
        response.getWriter().append(Application.userSessionMap.get(sessionKey));
        response.getWriter().append(" attempted to hijack session id ").append(request.getRequestedSessionId()); 
        response.getWriter().append("of user ").append(Application.userSessionMap.get(sha256Hex));
        return;
    }
    response.getWriter().append("Valid Session\n");
}

Ho usato l'algoritmo SHA-2 per eseguire l'hashing del valore usando l'esempio fornito da Hashing SHA-256 su baeldung

In attesa di vostri commenti.


@zaph Mi dispiace, ma non ho aggiunto la risposta per ottenere un rappresentante. Il punto non è nemmeno la crittografia SHA-2. Ma il fatto che sono stato in grado di rilevare l'uso dell'ID sessione di un altro utente nella sessione di un altro utente, vale a dire il dirottamento della sessione come nella domanda originale. Ho testato la mia soluzione e ho scoperto che funziona. Ma non sono un esperto in questo, quindi vorrei che la community verificasse se la mia risposta fosse abbastanza buona. Forse puoi vedere cosa fa il mio frammento di codice e decidere se risponde alla domanda. Grazie!
Jzf,

@zaph Grazie per aver segnalato l'errore. Ho aggiornato la mia risposta secondo il tuo suggerimento. Rimuovi il tuo voto negativo se ritieni che la risposta sia utile.
Jzf,

0

Per ridurre il rischio è anche possibile associare l'IP di origine alla sessione. In questo modo un utente malintenzionato deve trovarsi all'interno della stessa rete privata per poter utilizzare la sessione.

Anche il controllo delle intestazioni dei referer può essere un'opzione, ma possono essere falsificati più facilmente.


7
no, non è possibile utilizzare l'IP di origine, poiché potrebbe cambiare - tramite IP dinamici, modificato quando un utente viene temporaneamente disconnesso o tramite l'uso (implicito o esplicito) di una proxy farm. Inoltre, i dirottatori di sessione provenienti dallo stesso ISP possono utilizzare lo stesso proxy e IP di un utente legittimo ...
Olaf Kock,

1
PHP-Nuke ha una buona pagina sul loro approccio alla sessione e parla in dettaglio di come l'aggancio all'IP non funziona con tutti gli ISP phpnuke.org/…
Sembiance,

4
Cambiare Ip è molto comune con i provider di servizi Internet mobili. Con Vodafone, il mio IP cambia con OGNI richiesta.
Blaise,

1
Un po 'un vecchio post, ma per promuovere questo. Gli IP sono come detto una cattiva idea. Come accennato, gli utenti mobili tendono a vagare per gli IP. Alcuni ISP in passato avevano anche IP in roaming (come AOL), tuttavia questo approccio sta diventando più popolare ora con la carenza di IP IPv4. Tali ISP includono Plus net e BT
Peter

-15

Proteggi da:

$ip=$_SERVER['REMOTE_ADDER'];
$_SESSEION['ip']=$ip;

12
Non riesco a vedere cosa stai facendo qui.
samayo,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.