Il client è l'autore dell'attacco. Cammina nel tuo ufficio cantando quella frase 144 volte; assicurati di punteggiare la tua dizione con un piccolo tamburo. In questo modo, te ne ricorderai.
Nel tuo server, stai inviando codice Java per l'esecuzione sul client. Il cliente onesto eseguirà il tuo codice. Nessuno costringe l'aggressore a fare altrettanto; e si utilizza l'autenticazione del client proprio perché si teme che il client possa essere qualcun altro, che tenta di impersonare l'utente normale. Dal punto di vista del server, vengono visualizzati solo i byte che si inviano al client e i byte che ritornano. Non puoi assicurarti che questi byte siano stati calcolati con il tuo codice. L'attaccante, essendo un mascalzone malvagio, è perfettamente in grado di immaginare non di eseguire il tuo codice e invece di inviare la risposta che il tuo server si aspetta.
Considerate ora un semplice schema di autenticazione della password in cui semplicemente salvate le password degli utenti nel vostro database. Per autenticare, chiedere all'utente di inviare la password e quindi confrontarla con ciò che è stato memorizzato. Questo è molto semplice. Anche questo è molto brutto: si chiama password in chiaro . Il problema è che qualsiasi semplice occhiata di sola lettura al database (che si tratti di un attacco di SQL injection, un nastro di backup rubato, un vecchio hard disk recuperato da un dumpster ...) darà all'aggressore tutte le password. Per dichiarare chiaramente le cose, l'errore qui è di archiviare nel database esattamente i valori che, una volta inviati dal client, concedono l'accesso.
E il tuo schema proposto? Esattamente la stessa cosa Si archivia nel database il valore hash "così com'è". E quando il client invia quel valore esatto, l'accesso è garantito. Ovviamente, il client onesto invierà il valore mediante l'hashing di una password. Ma ammettiamolo: molti attaccanti non sono persone oneste.
Ora c'è un valore nel fare parte dell'hashing sul lato client. Effettivamente, un buon hashing della password è una corsa agli armamenti, in cui l'hashing è fatto di proposito a caro prezzo. Scaricare una parte del lavoro sui clienti può essere una buona cosa. Non funziona altrettanto bene quando i clienti sono deboli, ad es. smartphone con Java, o, peggio ancora, Javascript (che è una cosa completamente diversa, nonostante la somiglianza del nome).
In tal caso, è necessario eseguire bcrypt sul client e archiviare sul server non l'output bcrypt, ma l'hash dell'output bcrypt con una funzione di hash ragionevole (una veloce come SHA-256 andrebbe bene). L'elaborazione di una password P sarebbe quindi una bcrypt sul client, quindi un SHA-256 del risultato, calcolato sul server. Ciò spingerà la maggior parte della spesa della CPU sul client e sarà sicuro come un raw bcrypt per ciò che è destinato a fare (vedi sotto).
Comprendo che si desidera "crittografare" le password (l'hashing non è crittografia!) perché si desidera utilizzare un semplice HTTP. Non ti piace HTTPS per la stessa ragione di chiunque altro, che è il temuto certificato SSL. Pagare 20 dollari l'anno per un certificato SSL sarebbe simile alla rimozione della pelle con un pelapatate cosparso di succo di limone.
Sfortunatamente, non è possibile sfuggire al peeler. Come altri hanno osservato, anche se si dispone di un meccanismo di autenticazione solido, il raw HTTP non è ancora protetto e un attaccante attivo può semplicemente aspettare che un utente effettui l'autenticazione e dirottare la connessione da quel punto. Un esempio molto comune di "attaccante attivo" sono le persone che eseguono semplicemente un falso punto di accesso WiFi, ovvero un vero e proprio punto di accesso WiFi, ma mantengono anche l'opzione di dirottare le connessioni in qualsiasi momento. Questo è un tipo di modello di attacco che non può essere neutralizzato senza un protocollo crittografico completo che si estende su tutti i dati, non solo un metodo di autenticazione iniziale. Il tipo più semplice di tale protocollo è SSL / TLS. Qualsiasi protocollo che offra le stesse garanzie di cui hai assolutamente bisogno sarà anche complesso come SSL / TLS e molto più difficile da implementare perché, contrariamente a SSL / TLS, non è già implementato nel software client.
SSL è lì, basta usarlo. Per quanto riguarda il limone, succhialo.
(Se il costo finanziario è una barriera, ci sono alternative gratuite, come Let's Encrypt e pki.io . Resta da vedere se si adatta alla tua bolletta, ma vale la pena prenderlo in considerazione se sei davvero a corto di denaro.)