Inserimento di una password in una chiamata API REST

30

Supponiamo di avere un'API REST che viene anche utilizzata per impostare / reimpostare le password. Supponiamo anche che funzioni su connessioni HTTPS. C'è qualche buona ragione per non mettere quella password nel percorso della chiamata, diciamo anche che la codificherò in BASE64?

Un esempio potrebbe essere quello di reimpostare una password come questa:

http://www.example.com/user/joe/resetpassword/OLDPASSWD/NEWPASSWD

Capisco che BASE64 non è crittografia, ma in questo caso voglio solo proteggere la password per eseguire il surfing.

    
posta Bart Friederichs 29.11.2015 - 20:12
fonte

6 risposte

76

Un buon server registra tutte le richieste inviate ad esso, inclusi gli URL (spesso, senza parte variabile dopo '?'), IP sorgente, tempo di esecuzione ... Vuoi davvero questo log (potenzialmente letto da un ampio gruppo di amministratori ) per contenere informazioni criticamente sicure come password? Base64 non è un tappo contro di loro.

    
risposta data 29.11.2015 - 20:34
fonte
67

Ciò che stai proponendo non è né sicuro né RESTful.

@Netch ha già menzionato il problema con i log, ma c'è anche un altro problema nel mostrare le password inviate via HTTP, rendendo banale l'acquisizione delle password con qualsiasi tipo di sniffer wire o man-in-the-middle attacco.

Quando esegui una richiesta GET usando REST, i diversi elementi nell'URL rappresentano più elementi a grana fine. L'URL viene letto come se si stesse restituendo una parte NEWPASSWD di un OLDPASSWD che fa parte di una password di ripristino. Questo non ha alcun senso semantico. I GET non dovrebbero essere usati per salvare i dati.

Dovresti fare qualcosa del genere:

POST https://www.example.com/user/joe/resetpassword/
{oldpasswd:[data], newpasswd:[data]}

POST perché stai scrivendo dati e https perché non vuoi che venga sniffato.

(Questa è davvero la sicurezza a bassa barra. Il minimo assoluto che dovresti fare.)

    
risposta data 29.11.2015 - 20:42
fonte
61

Lo schema proposto presenta problemi in diverse aree.

Sicurezza

I percorsi URL sono registrati frequentemente; mettere le passwords unhashed nel percorso è una cattiva pratica.

HTTP

Le informazioni di autenticazione / autorizzazione dovrebbero apparire nell'intestazione Autorizzazione. O potenzialmente, per i contenuti basati su browser, l'intestazione Cookie.

REST

Verbi come resetpassword nel tuo URL sono generalmente un chiaro segno di un paradigma di trasferimento di stato non rappresentativo. Un URL dovrebbe rappresentare una risorsa. Cosa significa OTTENERE resetpassword ? O DELETE?

API

Questo schema richiede sempre la conoscenza della password precedente. Probabilmente vorrai consentire più casi; per esempio. la password è persa.

Potresti utilizzare Autenticazione di base o Digest , che è uno schema ben compreso.

PUT /user/joe/password HTTP/1.0
Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
Content-Type: text/plain
Host: www.example.com

NEWPASSWD

Non inserisce informazioni ultra-sensibili nel percorso e segue le convenzioni HTTP e REST

Se dovessi consentire qualche altra modalità di autorizzazione (ad esempio qualche token inviato attraverso un canale verificato per reimpostare la password), puoi semplicemente utilizzare un'intestazione di autorizzazione diversa senza dover cambiare altro.

    
risposta data 29.11.2015 - 23:43
fonte
3

Oltre alla sicurezza, il problema è che non si tratta di un approccio molto RESTful.

OLDPASSWD e NEWPASSWD non rappresentano nulla nella tua gerarchia di risorse e, peggio ancora, l'operazione non è idempotente.

Quindi puoi utilizzare POST come verbo e non dovresti includere le due password nel percorso della tua risorsa.

    
risposta data 29.11.2015 - 20:40
fonte
3

Il problema è evitare password in testo semplice nelle tue richieste. Ci sono due opzioni per soddisfare i restful requisiti del servizio web.

1. Hashing lato client

  • Immagino che tu stia memorizzando le tue password come e. g. hash (password + sale)
  • Puoi hash la nuova password con un salt sul lato client
  • Ciò significa: creare un nuovo salt sul lato client, creare un hash e. g. hash (newPassword + newSalt)
  • Invia il nuovo hash creato più il sale al tuo webservice restful
  • Invia la vecchia password anche come hash (oldPassword + oldSalt)

2. La crittografia

  • Crea una risorsa "una volta sola" (otk) per un utente come / otk / john
  • Questa risorsa restituisce una chiave unidirezionale casuale sicura, ad es. g. kbDlJbmNmQ0Y0SmRHZC9GaWtRMW0ycVJpYzhMcVNZTWlMUXN6ZWxLdTZESFRs e un ID univoco e. g. 95648915125
  • Il tuo webservice restful deve memorizzare questo caso casuale per la prossima comunicazione sicura con l'ID 95648915125
  • Cripta la tua nuova e vecchia password con l'otk e. g. AES (per ragioni di sicurezza dovresti usare due otk separati per la vecchia e la nuova password)
  • Invia le password crittografate alla tua risorsa password di modifica con l'ID 95648915125
  • Una combinazione di otk e ID può funzionare una sola volta, quindi devi eliminare quella combinazione dopo aver modificato la password
  • Possibile opzione migliore: invia la password corrente / vecchia con l'autenticazione di base

Nota: è richiesto HTTPS per entrambe le opzioni!

    
risposta data 01.12.2015 - 14:39
fonte
2

Quali sono le funzionalità di un'operazione di ripristino della password?

  1. Cambia qualcosa.
  2. C'è un valore su cui è impostato.
  3. Solo alcune persone possono farlo (l'utente, un amministratore o entrambi, forse con regole diverse su come possono farlo).

Il punto 1 qui significa che non puoi usare GET, devi POST qualcosa che rappresenta l'operazione di modifica della password a un URI che rappresenta una risorsa che gestisce le modifiche della password, o PUT qualcosa che rappresenta la nuova password a un URI che rappresenta la password o che rappresenta qualcosa (es. l'utente) di cui quella password è una funzionalità.

Generalmente verremmo POST, non ultimo perché può essere imbarazzante PUTting qualcosa che non possiamo in seguito ottenere e, naturalmente, non possiamo ottenere la password.

Il punto 2 sarà quindi i dati che rappresentano la nuova password, in ciò che viene POSTATO.

Il punto 3 significa che dovremo autorizzare la richiesta, il che significa che se l'utente è l'utente corrente avremo bisogno che la password corrente ci sia provata (anche se non necessariamente ricevere la password corrente, se ad es. un hash la sfida basata su base è stata utilizzata per dimostrarne la conoscenza senza inviarla).

L'URI dovrebbe quindi essere qualcosa come <http://example.net/changeCurrentUserPassword> o <http://example.net/users/joe/changePassword> .

Potremmo decidere di ricevere la password corrente nei dati POST e nel meccanismo generale di autorizzazione in uso.

    
risposta data 30.11.2015 - 11:45
fonte

Leggi altre domande sui tag