PARTE I: Come accedere
Supponiamo che tu sappia già come creare un modulo HTML login + password che POST invii i valori a uno script sul lato server per l'autenticazione. Le sezioni seguenti tratteranno i modelli per un'autentica pratica pratica e come evitare le più comuni insidie della sicurezza.
A HTTPS o non a HTTPS?
A meno che la connessione non sia già sicura (ovvero, tunneling tramite HTTPS tramite SSL / TLS), i valori del modulo di accesso verranno inviati in chiaro, il che consente a chiunque di intercettare sulla linea tra browser e server Web sarà in grado di leggere gli accessi mentre passano attraverso. Questo tipo di intercettazioni telefoniche viene eseguito di routine dai governi, ma in generale non affronteremo i fili "di proprietà" se non per dirlo: basta usare HTTPS.
In sostanza, l'unico modo pratico per proteggere dalle intercettazioni telefoniche / sniffing dei pacchetti durante l'accesso è utilizzare HTTPS o un altro schema di crittografia basato su certificati (ad esempio TLS ) o uno schema di risposta alla sfida collaudato (ad esempio Diffie-Hellman basato su SRP). Qualsiasi altro metodo può essere facilmente aggirato da un attaccante intercettativo.
Naturalmente, se sei disposto a diventare un po 'poco pratico, potresti anche utilizzare una qualche forma di schema di autenticazione a due fattori (ad esempio l'app Google Authenticator, un libro di codici fisico in stile "guerra fredda" o un dongle di generatore di chiavi RSA). Se applicato correttamente, potrebbe funzionare anche con una connessione non protetta, ma è difficile immaginare che uno sviluppatore sarebbe disposto a implementare l'autenticazione a due fattori ma non SSL.
(Non) Roll-your-own crittografia / hashing JavaScript
Dati i costi percepiti (sebbene ora evitabili ) e la difficoltà tecnica di impostare un certificato SSL sul tuo sito Web, alcuni sviluppatori sono tentati di implementare i propri schemi di hashing o crittografia nel browser per evitare di passare accessi in testo non crittografato su un filo non protetto.
Sebbene questo sia un pensiero nobile, è essenzialmente inutile (e può essere un difetto di sicurezza ) a meno che non sia combinato con uno dei precedenti - ovvero, proteggere la linea con una crittografia avanzata o utilizzare una risposta alla sfida collaudata meccanismo (se non sai di cosa si tratta, sappi solo che è uno dei concetti più difficili da dimostrare, più difficili da progettare e più difficili da implementare nella sicurezza digitale).
Sebbene sia vero che l'hashing della password può essere efficace contro la divulgazione della password , è vulnerabile a ripetere gli attacchi, gli attacchi / dirottamenti Man-In-The-Middle (se un attaccante può iniettare qualche byte nella tua pagina HTML non protetta prima che raggiunga il tuo browser, possono semplicemente commentare l'hash nel JavaScript) o attacchi di forza bruta (dato che stai consegnando all'aggressore sia username, salt che hash password).
CAPTCHAS contro l'umanità
CAPTCHA ha lo scopo di contrastare una specifica categoria di attacco: dizionario automatizzato / prova di forza bruta e errore senza operatore umano. Non c'è dubbio che questa sia una vera minaccia, tuttavia, ci sono modi per gestirla senza problemi che non richiedono un CAPTCHA, schemi di limitazione dell'accesso lato server appositamente progettati, ne discuteremo più avanti.
Sappi che le implementazioni CAPTCHA non sono create allo stesso modo; spesso non sono risolvibili per l'uomo, la maggior parte di essi è effettivamente inefficace contro i robot, tutti sono inefficaci contro la manodopera a basso costo del terzo mondo (secondo OWASP , l'attuale tasso di sweatshop è di $ 12 per 500 test) e alcune implementazioni potrebbero essere tecnicamente illegale in alcuni paesi (consultare il Foglio informativo sull'autenticazione OWASP ). Se è necessario utilizzare un CAPTCHA, utilizzare reCAPTCHA di Google , poiché per definizione è difficile da OCR (poiché utilizza scansioni di libri già classificate erroneamente in OCR) e si impegna molto per essere intuitivo.
Personalmente, tendo a trovare fastidiosi CAPTCHAS, e li uso solo come ultima risorsa quando un utente non è riuscito ad accedere più volte e i ritardi di limitazione sono al massimo. Ciò accadrà raramente per essere accettabile e rafforza il sistema nel suo insieme.
Memorizzazione delle password / Verifica degli accessi
Questa potrebbe essere una conoscenza comune dopo tutti gli hack molto pubblicizzati e le perdite di dati degli utenti che abbiamo visto negli ultimi anni, ma va detto: non archiviare le password in chiaro nel database. I database degli utenti vengono sistematicamente hackerati, trapelati o ripuliti tramite l'iniezione SQL e, se si memorizzano password non crittografate, è un gioco istantaneo per la sicurezza dell'accesso.
Quindi, se non riesci a memorizzare la password, come puoi verificare che la combinazione login + password POSTED dal modulo di login sia corretta? La risposta è hashing usando una funzione di derivazione chiave . Ogni volta che viene creato un nuovo utente o viene modificata una password, si prende la password e la si esegue attraverso un KDF, come Argon2, bcrypt, scrypt o PBKDF2, trasformando la password in chiaro ("correcthorsebatterystaple") in una lunga stringa dall'aspetto casuale , che è molto più sicuro da archiviare nel database. Per verificare un accesso, si esegue la stessa funzione hash sulla password immessa, questa volta passando in salt e confrontando la stringa hash risultante con il valore memorizzato nel database. Argon2, bcrypt e scrypt memorizzano già il sale con l'hash. Dai un'occhiata a questo articolo su sec.stackexchange per informazioni più dettagliate.
Il motivo per cui viene utilizzato un sale è che l'hash in sé non è sufficiente: ti consigliamo di aggiungere un cosiddetto "sale" per proteggere l'hash dai tavoli arcobaleno . Un salt impedisce in modo efficace che due password che corrispondono esattamente vengano memorizzate come lo stesso valore di hash, impedendo che l'intero database venga scansionato in una corsa se un attaccante sta eseguendo un tentativo di indovinare la password.
Un hash crittografico non deve essere utilizzato per l'archiviazione delle password perché le password selezionate dall'utente non sono abbastanza forti (cioè non contengono in genere abbastanza entropia) e un attacco che indovina la password potrebbe essere completato in un tempo relativamente breve da un utente malintenzionato con accesso agli hash. Questo è il motivo per cui vengono utilizzati i KDF: questi effettivamente "allungano la chiave" , il che significa che ogni password indovina un attaccante provoca ripetizioni multiple dell'algoritmo hash, ad esempio 10.000 volte, che induce l'attaccante a indovinare la password 10.000 volte più lentamente.
Dati della sessione - "Hai effettuato l'accesso come Spiderman69"
Una volta che il server ha verificato l'accesso e la password nel database dell'utente e ha trovato una corrispondenza, il sistema ha bisogno di un modo per ricordare che il browser è stato autenticato. Questo fatto dovrebbe essere sempre e solo archiviato sul lato server nei dati della sessione.
Se non si ha familiarità con i dati della sessione, ecco come funziona: una singola stringa generata casualmente viene archiviata in un cookie in scadenza e utilizzata per fare riferimento a una raccolta di dati, i dati della sessione, memorizzati sul server. Se si utilizza un framework MVC, questo è già sicuramente gestito.
Se possibile, assicurati che il cookie di sessione abbia i flag di sicurezza e Solo HTTP impostati quando inviati al browser. Il flag HttpOnly fornisce una certa protezione contro il cookie letto attraverso l'attacco XSS. Il contrassegno sicuro garantisce che il cookie venga rispedito solo tramite HTTPS e quindi protegge dagli attacchi di sniffing della rete. Il valore del cookie non dovrebbe essere prevedibile. Quando viene presentato un cookie che fa riferimento a una sessione inesistente, il suo valore deve essere sostituito immediatamente per impedire la fissazione della sessione .
PARTE II: Come rimanere connesso - La famigerata casella di controllo "Ricordami"
I cookie di accesso persistenti (funzionalità "Ricordami") sono una zona pericolosa; da un lato, sono completamente sicuri come gli accessi convenzionali quando gli utenti comprendono come gestirli; e d'altra parte, rappresentano un enorme rischio per la sicurezza nelle mani di utenti negligenti, che possono usarli su computer pubblici e dimenticare di disconnettersi e che potrebbero non sapere quali sono i cookie del browser o come eliminarli.
Personalmente, mi piacciono gli accessi permanenti per i siti Web che visito regolarmente, ma so come gestirli in modo sicuro. Se sei sicuro che i tuoi utenti conoscano lo stesso, puoi usare accessi persistenti con coscienza pulita. Altrimenti, allora puoi iscriverti alla filosofia secondo cui gli utenti che sono disattenti con le loro credenziali di accesso se la sono presa se vengono hackerati. Non è come andare nelle case dei nostri utenti e strappare tutti quegli appunti Post-It che inducono il viso con password che hanno allineato sul bordo dei loro monitor.
Naturalmente, alcuni sistemi non possono permettersi di hackerare alcun account; per tali sistemi, non è possibile giustificare un accesso persistente.
Se decidi di implementare cookie di accesso persistenti, ecco come farlo:
Prima di tutto, prenditi del tempo per leggere l'articolo sull'Iniziativa Paragon . Avrai bisogno di avere un sacco di elementi giusti e l'articolo fa un ottimo lavoro nel spiegarli.
E solo per ribadire una delle insidie più comuni, NON MEMORIZZARE IL COOKIE DI ACCESSO PERSISTENTE (TOKEN) NEL TUO DATABASE, SOLO UN TRATTAMENTO! Il token di accesso è equivalente alla password, quindi se un utente malintenzionato mette le mani sul database, può utilizzare i token per accedere a qualsiasi account, proprio come se fossero combinazioni di login-password in chiaro. Pertanto, utilizzare l'hash (secondo https://security.stackexchange.com/a/63438/5002 un hash debole funzionerà bene a questo scopo) quando si memorizzano token di accesso persistenti.
PARTE III: Uso di domande segrete
Non implementare "domande segrete" . La funzione "domande segrete" è un modello di sicurezza. Leggi l'articolo dal link numero 4 dall'elenco DEVE LEGGERE. Puoi chiedere a Sarah Palin di questo, dopo il suo Yahoo! l'account e-mail è stato violato durante una precedente campagna presidenziale perché la risposta alla sua domanda di sicurezza era ... "Wasilla High School"!
Anche con domande specifiche dell'utente, è molto probabile che la maggior parte degli utenti scelga:
Una domanda segreta "standard" come il nome da nubile della madre o l'animale preferito
Una semplice curiosità che chiunque potrebbe sollevare dal proprio blog, profilo LinkedIn o simili
Qualsiasi domanda a cui è più facile rispondere che indovinare la propria password. Che, per qualsiasi password decente, è ogni domanda che puoi immaginare
In conclusione, le domande di sicurezza sono intrinsecamente insicure in praticamente tutte le loro forme e varianti e non devono essere utilizzate in uno schema di autenticazione per nessun motivo.
Il vero motivo per cui esistono anche domande sulla sicurezza in natura è che risparmiano comodamente il costo di alcune chiamate di supporto da parte di utenti che non possono accedere alla loro e-mail per ottenere un codice di riattivazione. Questo a scapito della sicurezza e della reputazione di Sarah Palin. Ne e 'valsa la pena? Probabilmente no.
PARTE IV: Funzionalità password dimenticata
Ho già menzionato il motivo per cui non dovresti mai usare le domande di sicurezza per gestire le password degli utenti dimenticate / perse; Va da sé che non si dovrebbe mai e-mail agli utenti le loro password effettive. Ci sono almeno altre due insidie fin troppo comuni da evitare in questo campo:
Non reimpostare una password dimenticata su una password complessa generata automaticamente - tali password sono notoriamente difficili da ricordare, il che significa che l'utente deve modificarlo o scriverlo - diciamo, su un Post-It giallo brillante sul bordo del monitor. Invece di impostare una nuova password, lascia che gli utenti ne scelgano subito una nuova, che è comunque ciò che vogliono fare. (Un'eccezione a ciò potrebbe essere se gli utenti utilizzano universalmente un gestore di password per archiviare / gestire password che sarebbero normalmente impossibili da ricordare senza scriverle).
Crea sempre l'hash nel codice / token della password persa nel database. DI NUOVO , questo codice è un altro esempio di password equivalente, quindi DEVE essere sottoposto a hash nel caso in cui un utente malintenzionato abbia messo le mani sul database. Quando viene richiesto un codice password perso, invia il codice in chiaro all'indirizzo e-mail dell'utente, quindi esegui l'hash, salva l'hash nel tuo database e getta l'originale . Proprio come una password o un token di accesso persistente.
Un'ultima nota: assicurati sempre che la tua interfaccia per l'immissione del "codice password perso" sia sicura almeno quanto il modulo di accesso stesso, altrimenti un utente malintenzionato lo utilizzerà semplicemente per ottenere l'accesso. Accertarsi di generare "codici password persi" molto lunghi (ad esempio, 16 caratteri alfanumerici con distinzione tra maiuscole e minuscole) è un buon inizio, ma si consiglia di aggiungere lo stesso schema di limitazione utilizzato per il modulo di accesso stesso.
PARTE V: Verifica della forza della password
Per prima cosa, ti consigliamo di leggere questo piccolo articolo per un controllo di realtà: le 500 password più comuni
Va bene, quindi forse l'elenco non è l' elenco canonico delle password più comuni su qualsiasi sistema in qualsiasi luogo , ma è una buona indicazione di come le persone scarsamente sceglieranno le loro password quando non esiste una politica applicata. Inoltre, l'elenco appare spaventosamente vicino a casa quando lo si confronta con le analisi disponibili al pubblico delle password rubate di recente.
Quindi: senza requisiti minimi di sicurezza delle password, il 2% degli utenti utilizza una delle 20 principali password più comuni. Significato: se un attaccante ottiene solo 20 tentativi, 1 su 50 account sul tuo sito Web sarà crackabile.
Per contrastare ciò è necessario calcolare l'entropia di una password e quindi applicare una soglia. La pubblicazione speciale NIST (National Institute of Standards and Technology) 800-63 ha una serie di ottimi suggerimenti. Ciò, se combinato con un'analisi del layout di tastiera e dizionario (ad esempio, "qwertyuiop" è una password errata), può rifiutare il 99% di tutte le password scarsamente selezionate a un livello di entropia di 18 bit. Il semplice calcolo della sicurezza della password e la visualizzazione di un misuratore della forza visiva per un utente è buono, ma insufficiente. A meno che non venga applicato, molti utenti lo ignoreranno molto probabilmente.
E per una rinfrescante comprensione della facilità d'uso delle password ad alta entropia, xkcd di password password Randall Munroe è altamente raccomandato.
Utilizza l' API Have I Been Pwned di Troy Hunt per verificare le password degli utenti rispetto alle password compromesse nelle violazioni dei dati pubblici.
PARTE VI: Molto altro - Oppure: Prevenire i tentativi di accesso al fuoco rapido
Innanzitutto, dai un'occhiata ai numeri: Velocità di recupero password - Per quanto tempo rimarrà la tua password
Se non hai il tempo di consultare le tabelle in quel link, ecco l'elenco di loro:
Ci vuole praticamente nessun tempo per rompere una password debole, anche se si sta di cracking con un abaco
Non ci vuole praticamente tempo per decifrare una password alfanumerica di 9 caratteri se non fa distinzione tra maiuscole e minuscole
Ci vuole praticamente nessun tempo per rompere un intricato, simboli-e-lettere-e-numeri, la password in alto a e-minuscolo se è lungo meno di 8 caratteri (un PC desktop può cercare l'intero spazio delle chiavi fino a 7 caratteri in una questione di giorni o addirittura ore)
Tuttavia, occorrerebbe una quantità eccessiva di tempo per decifrare anche una password di 6 caratteri, se si fosse limitati a un tentativo al secondo!
Quindi cosa possiamo imparare da questi numeri? Bene, un sacco, ma possiamo concentrarci sulla parte più importante: il fatto che prevenire un gran numero di tentativi di accesso successivi a fuoco rapido (cioè l' attacco di forza bruta ) non è poi così difficile. Ma prevenirlo nel modo giusto non è così facile come sembra.
In generale, hai tre opzioni che sono tutte efficaci contro gli attacchi di forza bruta (e gli attacchi del dizionario, ma poiché stai già impiegando una solida politica di password, non dovrebbero essere un problema) :
Presenta un CAPTCHA dopo N tentativi falliti (fastidiosamente infernali e spesso inefficaci - ma mi sto ripetendo qui)
Blocco degli account e richiesta di verifica tramite e-mail dopo N tentativi falliti (si tratta di un attacco DoS in attesa di verificarsi)
E infine, la limitazione del login : ovvero, impostare un ritardo tra i tentativi dopo N falliti tentativi (sì, gli attacchi DoS sono ancora possibili, ma almeno sono molto meno probabili e molto più complicati da realizzare).
Best practice n. 1: un breve ritardo che aumenta con il numero di tentativi falliti, come:
- 1 tentativo fallito = nessun ritardo
- 2 tentativi falliti = 2 secondi di ritardo
- 3 tentativi falliti = 4 secondi di ritardo
- 4 tentativi falliti = 8 secondi di ritardo
- 5 tentativi falliti = ritardo di 16 secondi
- eccetera.
L'attacco a questo schema sarebbe molto impraticabile, poiché il tempo di blocco risultante è leggermente più grande della somma dei precedenti tempi di blocco.
Per chiarire: il ritardo non è un ritardo prima di restituire la risposta al browser. È più simile a un periodo di timeout o refrattario durante il quale i tentativi di accesso a un account specifico o da un indirizzo IP specifico non saranno accettati o valutati affatto. In altre parole, le credenziali corrette non verranno restituite in caso di accesso riuscito e le credenziali errate non determineranno un aumento del ritardo.
Best practice n. 2: un ritardo di media durata che entra in vigore dopo N tentativi falliti, come:
- 1-4 tentativi falliti = nessun ritardo
- 5 tentativi falliti = ritardo di 15-30 minuti
Attaccare questo schema sarebbe piuttosto poco pratico, ma sicuramente fattibile. Inoltre, potrebbe essere rilevante notare che un ritardo così lungo può essere molto fastidioso per un utente legittimo. Gli utenti dimenticati non apprezzeranno te.
Best practice n. 3: Combinazione dei due approcci: un ritardo fisso e breve che diventa effettivo dopo N tentativi falliti, come:
- 1-4 tentativi falliti = nessun ritardo
- 5+ tentativi falliti = 20 secondi di ritardo
Oppure, un ritardo crescente con un limite superiore fisso, come:
- 1 tentativo fallito = 5 secondi di ritardo
- 2 tentativi falliti = ritardo di 15 secondi
- 3+ tentativi falliti = ritardo di 45 secondi
Questo schema finale è stato preso dai suggerimenti sulle migliori pratiche di OWASP (collegamento 1 dall'elenco MUST-READ) e dovrebbe essere considerato la migliore prassi, anche se è certamente sul lato restrittivo.
Come regola empirica, tuttavia, direi: più forte è la tua politica di password, meno devi infastidire gli utenti con ritardi. Se hai bisogno di password alfanumeriche forti (maiuscole / minuscole + numeri e simboli richiesti) 9+ caratteri, potresti dare agli utenti 2-4 tentativi di password non ritardati prima di attivare la limitazione.
L'attacco a questo schema di limitazione del login finale sarebbe molto impraticabile. E come tocco finale, consenti sempre agli accessi persistenti (cookie) (e / o un modulo di accesso verificato da CAPTCHA) di passare, in modo che gli utenti legittimi non vengano nemmeno ritardati mentre l'attacco è in corso . In questo modo, l'attacco DoS molto poco pratico diventa un attacco estremamente poco pratico.
Inoltre, ha senso fare un throttling più aggressivo sugli account di amministrazione, poiché questi sono i punti di ingresso più interessanti
PARTE VII: Attacchi di forza bruta distribuiti
A parte questo, gli aggressori più avanzati cercheranno di aggirare il throttling di accesso "diffondendo le loro attività":
Distribuire i tentativi su una botnet per impedire la segnalazione dell'indirizzo IP
Invece di scegliere un utente e provare le 50.000 password più comuni (che non possono, a causa della nostra limitazione), sceglieranno LA password più comune e la proveranno invece contro 50.000 utenti. In questo modo, non solo aggirano misure di massimo tentativo come CAPTCHA e limitazione del login, ma aumentano anche le loro possibilità di successo, poiché la password più comune numero 1 è molto più probabile rispetto al numero 49.995
Distanziare le richieste di accesso per ciascun account utente, diciamo, a distanza di 30 secondi, per sgattaiolare sotto il radar
Qui, la migliore pratica sarebbe quella di registrare il numero di accessi non riusciti, a livello di sistema , e utilizzare una media corrente della frequenza di accesso errato del tuo sito come base per un limite superiore che imponi quindi a tutti gli utenti.
Troppo astratto? Lasciami riformulare:
Supponiamo che il tuo sito abbia avuto in media 120 accessi non validi al giorno negli ultimi 3 mesi. Usando quello (media corrente), il tuo sistema potrebbe impostare il limite globale a 3 volte quello - cioè. 360 tentativi falliti per un periodo di 24 ore. Quindi, se il numero totale di tentativi falliti su tutti gli account supera quel numero entro un giorno (o anche meglio, controlla la velocità di accelerazione e si attiva su una soglia calcolata), attiva la limitazione dell'accesso a livello di sistema, il che significa brevi ritardi per TUTTI gli utenti (sempre, ad eccezione degli accessi ai cookie e / o degli accessi CAPTCHA di backup).
Ho anche pubblicato una domanda con maggiori dettagli e una discussione davvero valida su come evitare insidie nel respingere gli attacchi di forza bruta distribuita
PARTE VIII: Provider di autenticazione e autenticazione a due fattori
Le credenziali possono essere compromesse, a causa di exploit, password scritte e perse, laptop con chiavi rubate o utenti che accedono a siti di phishing. Gli accessi possono essere ulteriormente protetti con l'autenticazione a due fattori, che utilizza fattori fuori banda come codici monouso ricevuti da una telefonata, un messaggio SMS, un'app o un dongle. Diversi provider offrono servizi di autenticazione a due fattori.
L'autenticazione può essere completamente delegata a un servizio Single Sign-On, in cui un altro provider gestisce la raccolta delle credenziali. Ciò spinge il problema a una terza parte attendibile. Google e Twitter forniscono entrambi servizi SSO basati su standard, mentre Facebook fornisce una soluzione proprietaria simile.
LINK DA LEGGERE Informazioni sull'autenticazione Web
- Guida OWASP all'autenticazione / Foglio informativo sull'autenticazione OWASP
- Cosa fare e cosa non fare dell'Autenticazione client sul Web (documento di ricerca MIT molto leggibile)
- Wikipedia: cookie HTTP
- Domande sulla conoscenza personale per l'autenticazione di fallback: domande sulla sicurezza nell'era di Facebook (documento di ricerca Berkeley molto leggibile)