2009-09-01 4 views
5

Come scrivere/mettere insieme un accesso sicuro in PHP? Il website developer guide ha detto che non dovrei fare il mio, quindi riferirsi agli esempi disponibili tramite Google è inutile.Accesso protetto con autenticazione corretta in PHP

Come lo fanno i professionisti? Diciamo che stai costruendo un'app di classe mondiale nei binari, sarebbero utilizzabili le stesse librerie/tecniche qui?

Grazie

+0

Si consiglia di dare un'occhiata a https://github.com/delight-im/PHP-Auth, che è sia agnostic framework e indipendente dal database. – caw

risposta

20

In Rails, generalmente si utilizza una libreria preesistente. L'autenticazione è facile da sbagliare e il problema è stato risolto così tante volte che raramente vale la pena risolverlo. Se sei interessato a scrivere la tua implementazione, descriverò come funziona l'autenticazione moderna.

Il metodo ingenuo di autenticazione di un utente consiste nel memorizzare la password in un database e confrontarla con la password che l'utente invia. Questo è semplice ma incredibilmente insicuro. Chiunque sia in grado di leggere il tuo database può visualizzare la password di chiunque. Anche se si inseriscono i controlli di accesso al database, l'utente (e i suoi utenti) sono vulnerabili a chiunque vi si avvicini.

Il modulo corretto consiste nell'utilizzare una funzione di hash crittografica per elaborare la password quando viene scelta e quindi ogni volta che viene inoltrata. Una buona funzione di hash è praticamente irreversibile: non è possibile prendere un hash e trasformarlo in una password. Quindi, quando l'utente esegue il login, si prende la password inviata, l'hash e la si confronta con l'hash nel database. In questo modo, non memorizzi mai la password stessa. Sul lato negativo, se l'utente dimentica la propria password, è necessario ripristinarla invece di inviarla a loro.

Anche questo, tuttavia, è vulnerabile a determinati attacchi. Se un utente malintenzionato si impadronisce degli hash delle password e sa come si hash le tue password, allora può attaccare un dizionario: prende semplicemente ogni parola nel dizionario e blocca quella parola, mantenendola con l'originale. Questa struttura dati è chiamata tabella arcobaleno. Quindi, se uno qualsiasi degli hash delle parole del dizionario corrisponde a un hash della password, l'utente malintenzionato può concludere che la password è la parola del dizionario che esegue il hash su quella password. In breve, un utente malintenzionato in grado di leggere il tuo database può comunque accedere agli account con password deboli.

La soluzione è che prima che una password sia sottoposta a hash, viene combinata (di solito concatenata o xor'd) con un valore chiamato sale che è univoco per ciascun utente. Può essere generato casualmente, o può essere un timestamp di creazione di un account o alcuni di questi. Quindi, un utente malintenzionato non può utilizzare una tabella arcobaleno poiché ogni password viene essenzialmente sottoposta a un hashing leggermente diverso; avrebbe dovuto creare una tabella arcobaleno separata per ogni singolo sale distinto (praticamente per ciascun account), il che sarebbe proibitivo dal punto di vista computazionale.

Risponderemo ai consigli degli altri rispondenti: non si tratta di cose semplici, e non è necessario farlo perché è già stato fatto prima, e se lo fai tu stesso hai ottime possibilità di fare un errore e compromettere inavvertitamente la sicurezza del sistema. Ma se, per una ragione qualsiasi, lo vuoi davvero scrivere davvero tu stesso, spero di aver fornito uno schema (incompleto!) Di come è stato fatto.

+2

+1 - Per una risposta molto bella. –

+1

+1 - Bello ma lungo e sconclusionato. : brividi: sono in una sala conferenze con pannelli di quercia ?! –

+1

hashing salted password non è veramente difficile. – Herbert

-2

La mia risposta è "Non farlo"

Questa è una zona molto complessa, piena di potenziali di sicurezza gotcha. Se non sei un esperto in questo campo, allora stai solo chiedendo problemi e problemi lungo la strada.

Suggerirei di cercare una soluzione esistente da fare. Purtroppo non conosco nessuno che sarei felice di raccomandare, oltre a Openid. Sono sicuro che otterrete alcuni buoni suggerimenti qui ...

4

Zend Framework ha uno 'Auth' module che sarebbe un buon punto di partenza. Oppure, se il tuo sito ospiterà un'installazione di WordPress o PHPBB, ci sono modi per sfruttare i moduli di autenticazione di tali tecnologie per accedere ad altre pagine di un sito.

+0

Il modulo Zend Auth non risolve la domanda degli OP.Inoltre, gli esempi utilizzano più pratiche non sicure. In conclusione: Zend Auth è un sistema di sicurezza orribile. – Jacco

+0

Insicuro? È uno strumento che dipende da come lo si usa; cura di dare esempi/discussioni su come è insicuro? Zend_Auth è un modulo di autenticazione esistente con una cronologia, che è l'opposto di "rolling your own" che è la domanda originale; come non lo soddisfa? – MidnightLightning

+0

[Uso avanzato per esempio] (http://zendframework.com/manual/en/zend.auth.adapter.dbtable.html) utilizza MD5, invia la password al database invece di eseguire il controllo sul lato PHP (che può perché la password appaia nei registri delle query), ecc. La cosa con i ragazzi zend è che si considerano esperti e ignorano i commenti. – Jacco

2

Una cosa da considerare quando si tenta di autenticare è qual è il tuo vero obiettivo.

Ad esempio, su SO uso il mio account di accesso di Google, e questo funziona, poiché hanno solo bisogno di sapere chi sono, e possono fidarsi che Google abbia un'idea. Quindi, se quel modello funzionasse per te, allora guarda usando OpenID, dato che ci sono vari strumenti per farlo.

Se devi fare da solo, allora ci saranno vari test per garantire che sia sicuro, ancora una volta, a seconda di come paranoico vuoi essere.

  • Mai fidarsi di nulla da parte dell'utente, a meno che non sia stata utilizzata una verifica rigorosa.
  • Utilizzare https per proteggere la password dell'utente, li si deve molto.

Finirò la mia risposta qui mentre Thom ha fatto una risposta fantastica.

0

da Soulmerge:

penso che il accepted answer in your other question afferma abbastanza bene. Hash le password con un sale. Oltre a questo, ci sono alcune idee di sicurezza sul livello di trasporto:

  • Utilizzare https quando si inviano le password. Questo assicura che nessuno possa prenderli sul filo (man-in-the-middle attack o il client utilizza un proxy malvagio)
  • Un'alternativa è quella di hash la password utilizzando javascript quando viene inviato il modulo di accesso. Questo assicura che la password non venga mai trasportata in chiaro. Dovresti rifare il valore hash con un salt sul server. (md5($_POST['postedPwHash'] . $salt))
-1

un buon metodo per garantire in qualche modo la transazione client-server (se non ssl è disponibile) è quello di utilizzare una chiave casuale di una volta per creare un hash univoco dalle credenziali, quindi inviare solo quella unica hash al server. il server confronta quindi questo hash con il proprio hash generato anziché confrontarlo con le credenziali reali. questo fornirebbe una buona difesa contro l'attacco man-in-the-middle. il lato negativo è che per fare ciò l'utente deve avere abilitato JS (almeno non conosco un buon metodo per crittografare i dati lato client senza di esso). questo significa che avrai bisogno di un fallback sufficiente quando non è attivo. puoi persino creare il modulo in JS per assicurarti che sia abilitato.

this library è una semplice libreria che ho scritto una volta che fa la procedura che ho descritto, anche se probabilmente ha bisogno di alcuni miglioramenti.

notare che questo è in aggiunta all'utilizzo di metodi "salting" e altre misure di sicurezza lato server. è anche piuttosto vulnerabile agli attacchi di dizionario poiché l'intero processo di hashing è per definizione procedurale, prevedibile e visibile all'utente (come sempre JS).