back to top

Sicurezza PHP: come archiviare password e creare sistemi di login sicuri

Le password sono la principale linea di difesa contro l’accesso non autorizzato alle informazioni dei propri account sul web e, fin troppo spesso, può capitare di trovarsi dietro un progetto che le archivia con un hashing debole oppure, peggio ancora, salvate in chiaro sul database, vuoi perché si tratta di un progetto vecchio e mai revisionato oppure a causa di informazioni datate reperite sul web da parte dello sviluppatore.

C’è da precisare innanzitutto che le fondamenta per la sicurezza della password iniziano dalla password stessa e se per un vostro utente la password ideale è 123456 allora nessun sistema di sicurezza, per quanto articolato, sarà in grado di difenderla efficacemente.

Da questo punto di vista è buona norma prendere in considerazione l’ipotesi di creare una pagina informativa per "educare" gli utenti alla scelta di password elaborate, Google ad esempio fornisce una serie di indicazioni utili per gli utenti su come creare una password forte.

L’argomento è molto vasto ma proveremo a riassumere in pillole quelli che sono gli errori più comuni e le buone pratiche da adottare per trattare le password nella vostra applicazione in modo sicuro. Quali sono, quindi, le cattive abitudini che uno sviluppatore deve evitare se vuole mettere in sicurezza i propri progetti?

Best practices per lo sviluppo di sistemi di login

  • Non reinventare le meccaniche di sicurezza – Innanzitutto non bisogna improvvisarsi esperti di sicurezza: è assolutamente da evitare la costruzione di meccanismi di codifica o di logiche personali di sicurezza.
  • Non adoperare MD5() – Non adoperate mai l’algoritmo md5 per l’hashing della password anche se precedentemente l’avete criptata con altri metodi più sicuri poiché, a causa della possibilità di collisione dell’algoritmo, sarebbe molto facile per un attaccante trovare velocemente una stringa che risulti come password valida anche se non è quella definita in partenza dall’utente, vanificando quindi tutti i vostri sforzi.
  • Non utilizzare un salt unico per tutte le password – La condizione ideale per proteggere le password è che, se anche l’intero sistema è conosciuto alla perfezione dal nostro attaccante (vuoi perché è riuscito a recuperare i sorgenti in qualche modo o altro motivo), senza la chiave crittografica risulti molto difficile risalire al dato originario, di conseguenza il salt non può essere un valore statico.
  • Mai archiviare una password su un cookie, anche se sotto hash – Il cookie è il posto più insicuro in cui archiviare la password, potrebbe essere facilmente intercettato da un attaccante al fine di recuperare il dato di interesse. Anche se la password fosse criptata, l’attaccante avrebbe tutto il tempo necessario per eseguire un attacco a forza bruta su una sua macchina ottimizzata a tal fine, oppure tentare l’utilizzo di attacchi a dizionario per scovare in tempi ragionevoli il dato.

Cosa fare per proteggere adeguatamente le password?

  • Utilizzare i mezzi appropriati – Fate affidamento sugli strumenti che PHP già offre. Utilizzare un algoritmo di hashing è l’opzione migliore che avete a disposizione e sfruttare funzioni come ad esempio il crypt oppure password_hash (PHP>=5.5) vi permetterà di implementare molto semplicemente una logica di sicurezza più che valida.
  • Adoperare un algortimo di hashing lento – Quando si parla di sicurezza non si parla di prestazioni e questo argomento deve finire in secondo piano: la lentezza dell’algoritmo farà si che un attacco a forza bruta impieghi molto più tempo per proporre tutte le possibili combinazioni. Personalmente suggerisco di adoperare il blowfish che php integra nativamente allo scopo.
  • Utilizzare un salt casuale crittograficamente sicuro – Il salt deve essere qualcosa che un possibile attaccante non può conoscere e che non può predire ma soprattutto deve essere casuale per ogni password con cui si usa. In questo modo nessuno degli hash memorizzati sul database sarà uguale a quello di un altro utente, anche se entrambi usano la stessa password. Inoltre un buon salt rende vano l’uso delle rainbow table da parte di un attaccante nel caso riesca a recuperare l’elenco degli hash associati agli utenti.
  • Utilizzare una connessione sicura quando possibile – Quando una password viaggia dal computer dell’utente al server lo fa in chiaro attraverso la rete. Questo renderebbe possibile per un attaccante, nelle giuste condizioni, la possibilità di intercettarla prima ancora che questa venga protetta dai vari processi di sicurezza della nostra applicazione. L’utilizzo di una connessione sicura garantirà invece che ogni informazione scambiata con l’utente viaggi criptata attraverso la rete, rendendo così impossibile questo genere di attacchi.

La sicurezza non si basa però solo sul modo in cui si conserva il dato. Pertanto è consigliabile:

  • Richiedete l’immissione di password più articolate – Vietate agli utenti l’utilizzo di password lunghe meno di 8 caratteri e suggerite l’uso di lettere maiuscole, minuscole, numeri e qualche carattere speciale. Non c’è motivo di limitare la lunghezza della password o di bloccare determinati caratteri, tutt’anzi.
  • Limitare il numero di tentativi dei login – Limitate ad un numero ragionevole i tentativi falliti di login, se quel numero viene raggiunto bloccate l’account e obbligatelo a riattivarlo con una conferma tramite email.
  • Proporre agli utenti la modifica periodica della password – Una cosa che bisogna aver chiaro è che nessuna password, criptata in qualsiasi modo, è al sicuro per sempre: a seconda del metodo utilizzato un elaboratore può impiegare anche diversi mesi a compiere i tentativi necessari per scovare una password, di conseguenza è importante segnalare agli utenti la necessità di impostare una nuova password dopo un ragionevole periodo di 6 mesi dall’ultima modifica.

Memorizzazione e verifica password utente con PHP

PHP fortunatamente ci mette a disposizione diversi strumenti utili, in particolare ecco come generare un hash da una password mediante la funzione crypt:

// Password fornita dall'utente tramite form
$password = 'Password utente';

// Generiamo un salt casuale crittograficamente sicuro
$salt = mcrypt_create_iv(32, MCRYPT_DEV_URANDOM);

// Rendiamo il salt compatibile con la sintassi dell'hash che stiamo per usare
$salt = '$2a$10$' . strtr(base64_encode($salt), '+', '.');

// Codifichiamo la password in un hash a 60 caratteri di lunghezza
$hash = crypt($password, $salt);

// A questo punto è $hash che bisogna salvare nel database

Se invece avete a disposizione PHP v5.5 o superiore, potete semplificare il processo in questo modo:

// Password fornita dall'utente tramite form
$password = 'Password utente';

// Codifichiamo la password in un hash a 60 caratteri di lunghezza
$hash = password_hash($password, PASSWORD_BCRYPT);

// A questo punto $hash è il dato da archiviare nel database.

E fin qui abbiamo visto come produrre un hash sicuro. Vediamo adesso in che modo eseguire i controlli di verifica come, ad esempio, nella procedura di login della vostra applicazione.

// Hash recuperato dal database e password fornita dall'utente tramite modulo form
$hash = '...';
$password = 'Password utente';

if (crypt($password, $hash) === $hash) {
  // Password corretta!
} else {
  // Password invalida!
}

Con PHP v5.5 o superiore, esiste invece la funzione password_verify:

// Hash recuperato dal database e password fornita dall'utente tramite modulo form
$hash = '...';
$password = 'Password utente';

if (password_verify($password, $hash)) {
  // Password corretta!
} else {
  // Password invalida!
}

In ultimo, una regola d’oro da tenere in considerazione è di avere sempre a portata la documentazione ufficiale di PHP delle funzioni coinvolte per avere ben presente le varie possibilità e i comportamenti previsti nei vari casi di utilizzo.

Pubblicitร 

Leggi anche...

Autenticazione a due fattori (2FA): cos’è e come funziona

L'autenticazione a due fattori (in inglese Two Factor Authentication...

Authcode: cos’è e come funziona

Con il termine Authcode (o Auth-code) si fa riferimento...

HTTP Security Headers: aumentare la sicurezza del sito con .htaccess

Esistono diverse tecniche per innalzare il livello di sicurezza...

Criptare (e decriptare) file su Linux con OpenSSL

OpenSSL è un'implementazione rilasciata sotto licenza Open Source dei...

Cos’è una Botnet?

Con il termine botnet si fa riferimento ad una...

DDoS: cos’è, come funziona e come difendersi

Un DDoS (acronimo di Distribuited Denial of Service) รจ...
Pubblicitร