Sto progettando l'API per un gruppo di siti. I siti sono molto simili (un po 'come StackOverflow, SuperUser e ServerFault), e ha senso per loro avere un back-end condiviso. Quindi abbiamo deciso di provare ad avere una bella API REST come back-end e una serie di frontend molto simili ma diversi che consumano detta API. I frontend dovrebbero preferibilmente essere tutti statici, ma non è un requisito difficile se risulta impossibile essere borderline.Come si protegge un'API RESTful consumata da un browser dagli attacchi CSRF?
Sto lavorando alla progettazione di questa API ora e sono preoccupato per le implicazioni sulla sicurezza, in particolare CSRF. Dalle mie conoscenze di base sugli attacchi CSRF, sono costituiti da due componenti importanti:
Essere in grado di denominare la risorsa e il corpo della richiesta.
Trying l'utente/browser nell'utilizzo di auth ambientale (come le sessioni) per effettuare una richiesta a tale risorsa che sembra autenticata.
Molti degli approcci classici per correggere gli attacchi CSRF si basano sulla sessione. Dal momento che la mia API REST non esegue realmente le sessioni, entrambe prevengono molti vettori e praticamente tutti i modi per risolverli. Ad esempio, il doppio invio non ha senso perché non c'è nulla da raddoppiare.
Il mio approccio iniziale riguardava l'attacco alla parte 2 di un attacco CSRF. Se autenticherò tutte le richieste (ad esempio usando l'autenticazione di base HTTP), e il browser non conserva quelle credenziali memorizzate (ad esempio, alcuni JS hanno fatto la richiesta), solo il JS con le credenziali può fare la richiesta, e abbiamo finito . L'ovvio svantaggio è che l'app deve conoscere le credenziali dell'utente. L'altro svantaggio leggermente meno ovvio è che se voglio memorizzare le credenziali in modo sicuro sull'estremità dell'API, la verifica di una password dovrebbe richiedere una quantità di tempo fissa e non trascurabile. Se la verifica di una password richiede 100ms in modo sicuro, allora ogni altra richiesta richiederà almeno 100 ms + eps, e ci vorranno alcuni accorgimenti maliziosi per evitare che si sentano lenti. Potrei essere in grado di memorizzarlo nella cache (dal momento che le credenziali saranno sempre le stesse), e se sono molto attento potrei riuscire a farlo senza introdurre una vulnerabilità temporale, ma suona come un vespaio.
OAuth 2.0 sembra un po 'esagerato, ma suppongo che potrebbe essere la soluzione migliore, dopotutto finisco per non implementarla male. Suppongo che per ora potrei fare l'Auth di base HTTP e passare a OAuth quando avremo sviluppatori di app di terze parti.
C'è un po 'di disadattamento di impedenza con OAuth. OAuth vuole davvero aiutare le app ad accedere ad altre app, in pratica. Voglio che gli utenti si registrino su uno dei frontend, prima che un account di questo tipo esista.
Ho anche considerato il punto di attacco 1 rendendo gli URL randomizzati, ovvero aggiungendo token a una stringa di query. Questo funzionerebbe sicuramente ed è molto vicino a come funziona il tradizionale token randomizzato in una forma, e dato HATEOAS dovrebbe essere abbastanza RESTful, anche se questo solleva due domande: 1) da dove inizi? Esiste un punto di inizio API obbligatorio in cui effettuare l'accesso utilizzando l'autenticazione di base HTTP? 2) Quanto conterebbe gli sviluppatori di app se loro non possono prevedere un URL in anticipo, HATEOAS essere dannato?
Ho visto How to prevent CSRF in a RESTful application?, ma non sono d'accordo con la premessa che gli URI randomizzati sono necessariamente irrilevanti. Inoltre, questa domanda non ha alcuna risposta soddisfacente e non menziona OAuth. Inoltre, la soluzione di invio doppio di sessione non è valida, come ho menzionato sopra (dominio diverso per il frontend statico rispetto all'endpoint API).
Mi rendo conto che ciò che sto fondamentalmente cercando di fare qui è cercare di consentire le richieste cross-site da un dominio e non consentirne l'altro, e non è facile. Sicuramente ci deve essere una soluzione ragionevole?
Il problema, come dici tu, è che vuoi sia prevenire che consentire le richieste cross-site. Chiedi a Schrödinger. –
Ciò non significa che non ci siano modi per risolvere il problema. Ne ho persino fornito uno che sarebbe, anche se un po 'lentamente. – lvh