Generazione di token di autenticazione da sessioni PHP

1

Ho un sito PHP tradizionale che usa sessioni. Ho sviluppato un'applicazione in tempo reale su nodejs e desidero autenticare gli utenti qui in base alla loro sessione PHP. La procedura dovrebbe essere simile a questa:

  1. Client AJAX è una pagina getAuthToken.php
  2. Il client si connette al server Websocket in modo anonimo
  3. Il client invia il proprio token di autenticazione
  4. Il server controlla il token, autentica l'utente

getAuthToken.php dovrebbe generare un token di autenticazione per il nome utente della sessione corrente usando una chiave simmetrica (condivisa dal server websocket) e restituirla.

Quale sarebbe il miglior algoritmo da usare qui? Ho poca esperienza con la crittografia e non sono sicuro di dove procedere.

Un approccio che viene in mente potrebbe essere quello di SHA-2, il nome utente e qualche chiave segreta. Passiamo quindi il nome utente e questo hash al server websocket che farebbe lo stesso e confrontare gli hash. Includi un timestamp con l'hash per garantire ogni volta un token univoco.

L'approccio sopra è sicuro? C'è un approccio migliore? Non sono interessato a nulla sul cavo, useremo SSL per tutte le comunicazioni - la mia unica preoccupazione è la capacità di impersonare altri utenti generando un token fasullo attraverso l'ispezione del proprio token. L'algoritmo deve essere supportato sia in PHP che in node.

Sicuramente esiste un modo standard per farlo?

    
posta Abovestand 26.01.2015 - 12:21
fonte

2 risposte

1

Invece di un semplice hash, devi crittografare alcuni valori che possono essere decodificati sia dal tuo sistema PHP che da quello Node.js.

I dati da includere potrebbero essere:

  • nome utente.
  • Data di scadenza del biglietto.

Tuttavia, dal momento che stai crittografando potresti includere dettagli aggiuntivi che dovresti essere disponibile e questi rimarrebbero privati all'utente finale.

Questi sarebbero cifrati usando AES e una chiave simmetrica a 256 bit che è nota solo alle tue applicazioni PHP e Node.js. Per una scadenza continua è necessario aggiornare la data di scadenza su ogni richiesta e emettere un nuovo biglietto. Per motivi di prestazioni è possibile aggiornare meno di questo (ad esempio una volta che il ticket ha raggiunto la metà della vita). Questo è il metodo di crittografia ASP.NET utilizza per i suoi ticket di autenticazione.

Quindi il tuo token potrebbe essere

AES-256(256bit secret key, username + "|" + (date-time + 20 mins))

Dopo la decrittografia puoi verificare che il valore di date-time sia compreso nell'intervallo accettabile (vale a dire i 20 minuti successivi); in caso contrario, dovresti registrarlo come un evento di sicurezza e questo fornirà una protezione ragionevole contro la forzatura bruta. Se stai memorizzando questo in un cookie e invialo tramite WebSockets, puoi far scadere il cookie nello stesso momento (tieni presente che non tutti avranno il loro orologio impostato correttamente, quindi potresti voler aggiungere un margine di manovra extra per la scadenza del cookie).

Se desideri un'ulteriore protezione, la crittografia non fornisce l'integrità come notato da @GZBK, quindi potresti voler garantire l'integrità del valore decrittografato. Questo può essere ottenuto con un HMAC dei dati con hash. Quindi il tuo token diventerebbe:

encrypted_data = AES-256(256bit secret key, username + "|" + (date-time + 20 mins))
ticket = encrypted_data + "|" + HMAC_SHA256(256bit secret key, encrypted_data)

Puoi utilizzare la codifica Base64 per rappresentare i valori all'interno del tuo ticket.

    
risposta data 27.01.2015 - 12:32
fonte
0

La crittografia dei dati non è un requisito: questa è solo sicurezza per offuscamento e non fornisce alcuna reale sicurezza supplementare.

Quello che stai creando è un ticket di sessione: il getAuthToken.php fornisce un ticket al visitatore, quindi il visitatore "mostra" il ticket al server websocket per procedere. Il websocket dovrà quindi eseguire due operazioni qui:

  • Verifica alcuni valori nel ticket (il timestamp non è troppo vecchio, l'utente ha il privilegio sufficiente per accedere a questo contenuto, l'IP di origine menzionato nel ticket corrisponde all'indirizzo IP di origine dalla connessione HTTP corrente, ecc.) . Questi valori sono completamente dipendenti dall'applicazione, possono essere memorizzati in un singolo cookie o in uno diverso, appaiono in forma chiara, tutto ciò non ha importanza.
  • Verifica che nessuno di questi valori sia stato modificato, qui si trova tutta la sicurezza del ticket, e questo può essere fatto usando un algoritmo di hashing ben noto (SHA2 per esempio, ma non provare ad inventarlo o personalizzarlo !) prendendo tutti i dati informativi di cui sopra e una chiave segreta come input. Questa sarà la firma che garantisce l'autenticità del ticket.

Per una maggiore sicurezza, se getAuthToken.php e websocket possono avere accesso a qualche database comune (non necessariamente a uno SQL), è possibile includere un identificatore casuale imprevedibile univoco nei dati del ticket e archiviarlo in questo database: questo aggiungerà un altro livello di sicurezza assicurando che il ticket sia stato generato sul lato server e non (anche molto improbabile finché la chiave segreta è abbastanza strong) forgiato sul lato client.

Modifica (altri consigli):

  • Assicurati che la chiave sia abbastanza lunga da non indebolire l'hash (almeno fino alla dimensione finale dell'hash, dovresti generarla usando un computer dato che il cervello umano di solito è piuttosto povero in termini di entropia, forse cambia qualche carattere in seguito se davvero non ti fidi del PRNG del tuo computer),
  • Alcune lingue forniscono una versione "hmac" delle funzioni di hashing specifiche per questo scopo (prendendo la chiave come argomento separato per una migliore sicurezza crittografica)
  • Anche se non è selezionato in un database, è possibile includere un ID di "sessione" casuale nei dati con hash: aggiungerà un po 'di rumore che impedirebbe qualsiasi statistica potenziale o analisi temporale poiché l'hacker non sarà in grado di prevedere la stringa esatta che verrà calcolata dal server,
  • Sentiti libero di cambiare la chiave segreta di volta in volta, a seconda della tua architettura potrebbe essere un'attività piuttosto semplice e di basso impatto che annulla qualsiasi lavoro in corso per rafforzare la tua chiave (la frequenza dipende completamente dal tuo livello di paranoia;) )
risposta data 26.01.2015 - 19:25
fonte

Leggi altre domande sui tag