È un buon approccio per proteggere la mia API REST?

3

La mia applicazione è costituita da un'API back-end nodejs, ma sto anche sviluppando un'implementazione di "riferimento" di un client JavaScript, che è un backbone SPA .

Prima di tutto; l'API accetta solo le richieste HTTPS, nel caso in cui una richiesta HTTP raggiunga il server, la ignora completamente e inoltre (a seconda della configurazione del tenant) invalida la password fornita su quella richiesta non sicura.

Il mio server è stateless e sto usando solo l'autenticazione di base HTTP (S) . Fornisco due modi per autenticare una richiesta:

1- Invio delle credenziali sull'intestazione Authentication: base64('Basic ' + user:password)
2- Invio di una richiesta autenticata utilizzando il metodo 1 a GET /users/current che restituisce un token che è una stringa crittografata * contenente: username + '|' + timeOfTokenExpiration . Quindi il client invia solo l'intestazione Authentication: base64('Token ' + username:returnedToken) in seguito.

* La crittografia viene eseguita con l'algoritmo aes-256-ctr di OpenSSL e la chiave è l'hash della password dell'utente

Metodo 1 può essere utilizzato per una comunicazione diretta da server a server, ma non è adatto per un client JavaScript poiché l'utente dovrebbe inserire le sue credenziali su ogni richiesta, ciò che è impossibile .

L'archiviazione delle credenziali dell'utente nella memoria locale del browser risolverebbe questo problema ma manterrebbe l'utente a tempo indefinito, creando un'altra possibile minaccia alla sicurezza. Inoltre, non sono sicuro di quanto sia sicuro archiviare le credenziali in testo non crittografato nella memoria del browser .

Utilizzando il metodo 2 il client JavaScript invierà solo una richiesta autenticata e quindi memorizzerà le credenziali crittografate sull'archiviazione locale, dopo un certo periodo di tempo dovrà riconvalidare le credenziali dell'utente poiché alla fine scadrà e il server non accetterà richieste da quel token.

Sul lato server controllo l'autenticità di una richiesta del metodo 2 recuperando l'hash della password dell'utente e cercando di decodificarlo. Dopo la decifrazione, controllo se decryptedString.split('|')[0] === username .

È un approccio sicuro / buono?

    
posta Renato Gama 07.12.2014 - 23:01
fonte

1 risposta

3

C'è un problema con il metodo 2: se si utilizza l'hash dell'utente come chiave di crittografia per il token - e l'unica cosa verificata nel server è se il token viene decifrato o meno (nessuna altra convalida viene eseguita nel token) - quindi chiunque abbia l'hash dell'utente può autenticarsi come tale utente. Ciò annulla qualsiasi protezione * garantita dall'hashing della password dell'utente, potreste anche memorizzarla come testo normale ...

Suggerirei di non preoccuparsi di crittografare il token (poiché non contiene dati sensibili), solo firmarlo con un segreto noto solo al server e verificare che la firma sia valida quando l'utente prova ad autenticarsi usando il metodo 2. Si noti che con "firma" intendo sia una firma digitale che utilizza una chiave privata nota solo al server, sia un HMAC che utilizza un segreto simile. Ricordando di non memorizzare questo segreto nel DB stesso, ma in un modulo hardware, solo memoria o, se necessario, un file di configurazione.

* Per essere onesti, per lo meno la password stessa sarà comunque protetta - solo il tuo sistema sarà vulnerabile, altri sistemi dove l'utente ha riutilizzato quella password non sarà influenzata negativamente.

    
risposta data 04.03.2015 - 02:32
fonte

Leggi altre domande sui tag