2015-06-09 11 views
10

Oggi ho notato qualcosa di inquietante durante il controllo i file di sessione in storage/framework/sessions cartella creato da laravel 5.laravel - dati di sessione sopravvive log-out/log-in, anche per diversi utenti

Ecco cosa è successo:

  1. ho effettuato il login come utente a
  2. ho navigato a una pagina che memorizza variabile X nella sessione
  3. mi sono collegato fuori, ma non chiudere il browser.
  4. Il file di sessione in storage/framework/sessions era ancora lì e il cookie del browser era attivo.
  5. Ho effettuato l'accesso come utente B.
  6. Il vecchio file di sessione in storage/framework/sessions è stato eliminato e un nuovo file di sessione era lì.
  7. Ho esaminato il nuovo file di sessione: sorpresa! la variabile X è sopravvissuta alla disconnessione ed è ancora lì, accessibile per l'utente B!

conduce a problemi di sicurezza perché ora l'utente B ha accesso ai dati degli utenti A.

Durante il debug attraverso il codice sorgente laravel, ho scoperto che Session Store è non essere mai chiarito durante il logout/login processi. Solo le credenziali di accesso vengono rimosse nel metodo Illuminate\Auth\Guard::clearUserDataFromStorage(), ma tutti gli attributi di sessione archivio sono ancora lì, e successivamente quando viene chiamato $kernel->terminate($request, $response);, che a sua volta conduce a Illuminate\Session\Middleware\StartSession::terminate() chiamando Store::save(), che salva ciecamente $this->attributes nella nuova sessione, ignorando il fatto che ora appartiene a un altro utente.

Da un lato, sembra logico - Laravel non ha ipotesi sui miei dati e se voglio che scadano insieme con l'autenticazione o meno. Ma sarebbe bello averlo documentato da qualche parte con una soluzione per collegare alcuni dati sensibili all'oggetto di autenticazione e scadere insieme ad esso.

Questo significa che io come programmatore sono responsabile per tutto spazzare via tutti i dati sensibili dalla sessione corrente in caso di nuove (o lo stesso) utente accede a.

Clearing il logout non sarebbe affidabile, perché l'utente potrebbe non fare mai clic sul collegamento Disconnettersi ma attendere che la sessione scada, il che per Laravel non cancella ancora la sessione.

Un'ultima cosa da tenere a mente: non dovrei cancellare la sessione troppo presto: c'è il token AntiForgery che deve essere presente, altrimenti il ​​modulo di login fallirà sempre.

ho trovato un argomento del forum, che cerca anche di risolvere il problema in qualche modo simile:

http://laravel.io/forum/04-27-2014-how-to-expire-session-data

mi sono confuso da questo:

avevo un altro andare a oggi e realizzato ciò che il problema era: Session :: flush() non elimina i dati di sessione creati dall'app, come i dettagli del carrello acquisti

Se questo è vero, l'unico modo per liberarsi completamente della sessione sarebbe utilizzare PHP nativo session_unset() e session_destroy() ma non vorrei andare in quel modo - preferirei trovare una soluzione Laravel-ish più pulita, se possibile.

Come comunicare a Laravel che desidero rimuovere i miei vecchi dati di sessione insieme ai dati di autenticazione utente quando l'autenticazione scade o l'utente si disconnette?

risposta

4

Nel laravel docs si dice che si può:

rimozione di un elemento dalla sessione

Session::forget('key'); 

Rimozione tutti gli articoli dalla sessione

Session::flush(); 

Si potrebbe navigare al tratto AuthenticatesAndRegistersUsers.php e riscrivere

/** 
    * Log the user out of the application. 
    * 
    * @return \Illuminate\Http\Response 
    */ 
    public function getLogout() 
    { 
     $this->auth->logout(); 

     return redirect(property_exists($this, 'redirectAfterLogout') ? $this->redirectAfterLogout : '/'); 
    } 

a

/** 
    * Log the user out of the application. 
    * 
    * @return \Illuminate\Http\Response 
    */ 
    public function getLogout() 
    { 
     Session::flush(); 

     $this->auth->logout(); 

     return redirect(property_exists($this, 'redirectAfterLogout') ? $this->redirectAfterLogout : '/'); 
    } 

Non ho idea se questo in realtà il lavoro, ma fare un tentativo :)

Aggiornamento

According to this answer here on Stack Overflow, è possibile impostare il sessione per scadere alla chiusura del browser o dopo XXX minuti. Utilizzato insieme alla soluzione di cui sopra, dovrebbe risolvere il problema?

in config/session.php

/* 
    |-------------------------------------------------------------------------- 
    | Session Lifetime 
    |-------------------------------------------------------------------------- 
    | 
    | Here you may specify the number of minutes that you wish the session 
    | to be allowed to remain idle before it expires. If you want them 
    | to immediately expire on the browser closing, set that option. 
    | 
    */ 

    'lifetime' => 120, 

    'expire_on_close' => false 
+1

Sì, questo dovrebbe funzionare quando l'utente si disconnette di proposito. Ma nel caso in cui se solo mantiene il browser aperto fino alla scadenza della sessione, dovrò chiamare manualmente quelle funzioni di dimenticanza e scarico. Sembra, non sono l'unico ad aver scoperto questo potenziale problema di sicurezza: https://github.com/laravel/framework/issues/8661 – JustAMartin

+0

Aggiornamento della risposta. Questo risolve il problema per te? – MartinJH

+0

Sì, se l'utente chiude il browser, funziona sempre correttamente e non ci sono problemi. Il problema è solo se l'utente se ne va e poi molto più tardi arriva un altro utente e accede - quindi sono presenti le vecchie variabili di sessione. Immagino, dovrò convivere con queste chiamate flush() durante il logout e l'accesso, mentre non c'è una soluzione integrata migliore in Laravel per specificare che non voglio che alcune variabili di sessione rimangano in vita dopo che la sessione è cambiata . – JustAMartin