Problemi di sicurezza dell'API REST Tokenless

5

Sto progettando un'API in PHP / MySQL che, per la sua progettazione, non memorizzerà la password di un utente nel database e quindi non genera token di autorizzazione per il client da conservare. La ragione di ciò è di impedire qualsiasi possibilità di ottenere informazioni sensibili non crittografate in caso di compromissione del database.

I dati sensibili dell'utente vengono crittografati utilizzando la propria password, in modo che la decrittografia dei dati non possa essere eseguita con qualsiasi cosa memorizzata nel database (potenzialmente compromesso). Al momento ho implementato alcune funzioni di sicurezza:

  1. Come precedentemente descritto, i dati sensibili vengono crittografati utilizzando AES utilizzando la password hash SHA-512 dell'utente (la password viene fornita con ogni richiesta come dati del modulo), oltre a un po 'di sale extra.
  2. È richiesto HTTPS e sono consentite solo le richieste POST.
  3. Gli account utente sono identificati dagli indirizzi e-mail (tagliati e con custodia inferiore nella memoria) e richiedono la verifica prima dell'uso.
  4. Le password degli utenti devono avere una lunghezza minima di 8 caratteri.
  5. Alla fine, sarà necessario un token API per l'utilizzo di app di terze parti tramite l'intestazione Authorization. Le app di terze parti sono limitate dal fatto che non possono creare, verificare o eliminare account.

La mia domanda è, è abbastanza? Non sono un esperto di sicurezza e l'ultima cosa che voglio fare è progettare qualcosa con una supervisione importante. La mia preoccupazione principale è che la password dell'utente sia fornita con ogni richiesta, anche se sarebbe solo tramite SSL.

Modifica

Per chiarire, gli utenti saranno in grado di cambiare le loro password purché abbiano ancora quella attuale. Viene effettuata una richiesta contenente l'indirizzo e-mail dell'utente, la password corrente e la nuova password. La richiesta è autenticata come normalmente, utilizzando l'indirizzo e-mail e la password corrente. La convalida viene eseguita sulla nuova password (applicando anche il minimo di 8 caratteri) prima di continuare.

In primo luogo, così come è fatto quando l'utente desidera recuperare le proprie informazioni sensibili, le informazioni vengono decifrate usando la loro password corrente. Nel suo stato decrittografato, le informazioni vengono quindi crittografate utilizzando la nuova password e i dati sensibili vengono sovrascritti nel database.

A questo punto, non vi è alcun record memorizzato della password precedente e non può più essere utilizzato. Una modifica della password non può essere eseguita da un amministratore o, in ogni caso, senza la password che è stata utilizzata per crittografare in precedenza le informazioni. Se la password viene persa, non è possibile eseguire nulla.

    
posta William Thomas 17.10.2013 - 00:47
fonte

2 risposte

1

La tua idea non è irragionevole. Crittografare i dati di un utente utilizzando una chiave che può essere generata solo quando l'utente è presente è una tattica ragionevole, ed è infatti utilizzata in un numero di ambienti ad alta sicurezza. Questo può fornire una sicurezza significativa se fatto bene. Ma vorrei introdurre i seguenti avvertimenti e modifiche:

  • L'autenticazione stateless dovrebbe essere evitata. È categoricamente peggiore dell'autenticazione sessione limitata. Si Sempre. Esistono più reaon, ma uno di questi è che se le password vengono inviate con ogni richiesta, le password vengono memorizzate nella cache da qualche parte . Idealmente, l'utente dovrebbe effettuare il login, che "sblocca" il datastore e fornisce all'utente una chiave di sessione a tempo limitato che può essere utilizzata per accedere al datastore "sbloccato" solo per un periodo di tempo limitato. Ciò consente di scadere le sessioni di autenticazione e aiuta a prevenire una serie di potenziali attacchi. Nota che ciò richiede una leggera modifica del progetto che descriverò in seguito.

  • Se i dati del client possono essere crittografati sul lato client, allora fallo. Se tutto ciò che vedete dei dati dell'utente è un frammento di bit crittografato, allora il server non potrebbe mai mettere a rischio quei dati.

  • Dovresti prendere in considerazione l'utilizzo di una catena di crittografia in due passaggi. Invece di crittografare i dati dell'utente utilizzando la chiave derivata da password, dovresti invece criptare i dati importanti usando una chiave totalmente casuale, e quindi crittografare quella chiave totalmente casuale usando la chiave derivata da password dell'utente. Ciò consente di (a) modificare facilmente le password degli utenti, (b) introdurre schemi di autenticazione più complessi (ad esempio a due fattori) e (c) rimuove il requisito di inviare la password ad ogni richiesta. Ricalcola semplicemente la chiave del datastore usando una chiave temporanea che deriva da un token di sessione casuale che fornisci all'utente al login. Devi anche collegare l'ora corrente, l'IP dell'utente e qualsiasi altra informazione specifica della sessione che desideri utilizzare per impedire il furto delle sessioni.

  • Utilizzare una formula di derivazione della chiave ragionevole. Un singolo passaggio di una funzione di hashing non è sufficiente per impedire a un utente malintenzionato di forzare la chiave di crittografia se ottiene i dati crittografati. Invece, usa una funzione come PBKDF2 o scrypt con un numero ragionevole di round. Ciò aumenta drasticamente la quantità di lavoro che un utente malintenzionato dovrebbe fare per indovinare la password di un utente.

risposta data 21.10.2013 - 10:26
fonte
2

Prima di reinventare la ruota e creare il proprio gestore di sessioni, leggi il foglio di lavoro per la gestione della sessione OWASP , che aiuterà eviti errori comuni.

Il problema è che il token di autenticazione proposto sha512(password) utilizzato per mantenere lo stato autenticato, è in realtà un token di sessione molto comprensibile per una serie di ragioni:

  1. Il problema peggiore è che questo ID di sessione proposto è molto piccolo spazio chiave. È molto più facile per un attaccante indovinare sha512(password) di indovinare 16 byte di /dev/urandom .
  2. Crittografia! = Autenticazione. Più chiavi possono agire sul testo cifrato     per ottenere qualche risultato, solo la chiave corretta produrrà effettivamente il     vero testo normale. Devi ancora verificare di aver ricevuto     la chiave esatta e AES-CBC non lo faranno. La correttezza di questa chiave potrebbe essere verificata con a     funzione di hash, un CMAC o HMAC. Funzionerebbe AES in una modalità di autenticazione autenticata.
  3. CWE-613 afferma che gli ID di sessione o "token" devono scadere. Di usando l'hash della password, in effetti è stata creata una nuova password che è sha512(password) non ha scadenza e può essere utilizzato per l'autenticazione senza conoscere la password in testo semplice. Una volta che questo valore è compromesso, può farlo un utente malintenzionato accedi all'account.
  4. SHA512 è una cattiva funzione di derivazione chiave (KDF) e un cattivo modo per archiviare password in generale ( CWE-916 ). bcrypt, pbkdf2, scrypt sono tutte buone opzioni.
  5. Se sei RESTful, quindi usa il VERBO corretto ! utilizzando POST per tutto è confuso. L'applicazione di POST non rende il sistema più sicuro, queste richieste sono vulnerabili quanto GET ad attacchi come CSRF o altri attacchi.
risposta data 17.10.2013 - 18:25
fonte

Leggi altre domande sui tag