Ho creato una semplice API RESTful per un progetto che segue parzialmente this very good blog post by Riyad Kalla. Ora ho letto dozzine di domande simili su Stack Overflow ma non riesco a trovare una risposta alla mia domanda di sicurezza.Protezione di un endpoint RESTful dell'API senza sessione
In breve, le mie richieste andare in questo modo:
- Il cliente ha una chiave API pubblica (testo in chiaro, accessibili a chiunque sniffing del traffico di rete o il corretto controllo del codice sorgente)
- il client invia una richiesta al server con la chiave API pubblica
- Il server ha una chiave API segreta (riservata a chiunque tranne lo sviluppatore)
- Il server crea un hash HMAC-SHA1 composto dai dati della richiesta del client e dalla chiave API segreta
- Il server invia una richiesta identica alla richiesta del client al server API, ma compresa la risultante HMAC-SHA1
- Il server API cerca la chiave API segreta nel suo database in base alla chiave API pubblica che riceve
- il server API ricrea un hash HMAC-SHA1 utilizzando gli stessi dati del server dello sviluppatore
- Se gli hash corrispondono, la richiesta viene considerato valido e viene elaborato normalmente
sono preoccupato che qualcuno usando il mio servizio potrebbe recuperare la chiave API pubblica (sniffando il traffico di rete diciamo), e quindi semplicemente cURL il sam e richiede che il client faccia originariamente tramite il browser utilizzando AJAX direttamente al server dello sviluppatore. Pertanto, l'utente malintenzionato potrebbe essere autenticato come utente legittimo e accedere all'API con un'altra chiave API segreta.
Proverò a dare un esempio concreto. Normalmente lo farei:
- AJAX a ottenere una richiesta al mio server.
- Il mio server esegue l'hashing della mia richiesta con il mio segreto API e lo invia al server API.
- Il server API convalida la mia richiesta e restituisce il carico utile.
Ma ho paura che:
- Dr. Evil sarà annusare la mia chiave API pubblica.
- Dr. Evil cercherà di ottenere una richiesta al mio server usando la mia chiave API pubblica.
- Il mio server rifiuterà la richiesta del Dr. Evil con la mia API segreta e la invierà al server API.
- Il server API convalida e restituisce il carico utile per completare i piani viziosi del Dr. Evil.
- Dr. Evil ride una risata malvagia.
Qualcosa che mi manca o è solo una parte del gioco RESTful API?
AGGIORNAMENTO: Sto volontariamente omettendo qualsiasi forma di convalida del timestamp per mantenere le cose semplici e concentrarsi solo sul problema di autenticazione.
UPDATE 2: Ho aggiunto una convalida $_SERVER['HTTP_REFERER']
al processo. L'obiettivo qui è che il client deve inviare un referrer insieme alla richiesta e deve corrispondere al referrer elencato nel database sul lato dell'API. Sfortunatamente, i referrer HTTP possono essere falsificati facilmente. È ancora un altro livello di sicurezza, ma non è ancora perfetto.
UPDATE 3: Ho modificato il mio codice lato server per impostare il referrer sull'indirizzo IP remoto. Ciò impone che ogni richiesta inviata al mio server che vuole essere sottoposta a hash usando la chiave API segreta arrivi in definitiva al server API con l'indirizzo IP della richiesta originale. Questo IP può quindi essere convalidato e la richiesta può essere inoltrata. Credo che sia ancora possibile simulare lo $_SERVER['REMOTE_ADDR']
, ma è più complesso di fingere $_SERVER['HTTP_REFERER']
... Ancora non è perfetto, immagino.
UPDATE 4: Secondo questi post: How to fake $_SERVER['REMOTE_ADDR'] variable? e https://serverfault.com/questions/90725/are-ip-addresses-trivial-to-forge, falsificare la $_SERVER['REMOTE_ADDR']
è possibile però difficile. Tuttavia, è impossibile ricevere una risposta dalla richiesta simulata poiché non si ha il controllo della rete simulata. La richiesta può essere validata con successo ma la sua risposta non cadrà in mani dannose.
Grazie. Ho volontariamente escluso la parte timestamp per mantenere le cose semplici in quanto non è un grosso problema da implementare nel mio codice attuale, avrei dovuto accennare a ciò. Non sono sicuro di aver capito correttamente la funzione SSL. È impossibile sniffare il traffico? L'utente malintenzionato può ancora rubarlo dal codice sorgente JavaScript, no? Mi manca sicuramente qualcosa qui ... –
SSL è la crittografia del trasporto. Rende molto più difficile sniffare. Anche con le API questa è una buona idea. – datasage
Ma ho ancora lo stesso problema se l'utente malintenzionato può ottenere la chiave API pubblica dall'origine, giusto? –