Best practice per la protezione di un'API / servizio Web REST [chiuso]


828

Quando si progetta un'API o un servizio REST, esistono delle best practice stabilite per la gestione della sicurezza (autenticazione, autorizzazione, gestione delle identità)?

Quando si crea un'API SOAP si ha WS-Security come guida e molta letteratura esiste sull'argomento. Ho trovato meno informazioni sulla protezione degli endpoint REST.

Mentre capisco che REST intenzionalmente non ha specifiche analoghe a WS- * Spero che siano emerse le migliori pratiche o modelli raccomandati.

Qualsiasi discussione o collegamento a documenti pertinenti sarebbe molto apprezzato. Se è importante, utilizzeremo WCF con messaggi serializzati POX / JSON per le nostre API / servizi REST creati utilizzando la versione 3.5 di .NET Framework.


1
conosci qualche applicazione reale completa che utilizza buoni modelli e pratiche con API REST e webServices in github?
PreguntonCojoneroCabrón,

Risposte:


298

Come già detto, Amazon S3 è un buon modello con cui lavorare. Le loro firme di richiesta hanno alcune caratteristiche (come incorporare un timestamp) che aiutano a prevenire la riproduzione accidentale e dannosa di richieste.

La cosa bella di HTTP Basic è che praticamente tutte le librerie HTTP lo supportano. Ovviamente dovrai richiedere SSL in questo caso perché l'invio di password in chiaro in rete è quasi universalmente una cosa negativa. Di base è preferibile Digest quando si utilizza SSL perché anche se il chiamante sa già che sono necessarie le credenziali, Digest richiede un roundtrip aggiuntivo per scambiare il valore nonce. Con Basic, i chiamanti inviano semplicemente le credenziali la prima volta.

Una volta stabilita l'identità del client, l'autorizzazione è in realtà solo un problema di implementazione. Tuttavia, è possibile delegare l'autorizzazione ad alcuni altri componenti con un modello di autorizzazione esistente. Ancora una volta la cosa bella di Basic qui è che il tuo server finisce con una copia in chiaro della password del client che puoi semplicemente passare ad un altro componente all'interno della tua infrastruttura secondo necessità.


3
SSL è una parte importante della sicurezza, ma non tutte le applicazioni richiedono quel livello di crittografia. Se qualcuno ruba in transito ciò che pubblicherai pubblicamente su Twitter, è uno svantaggio così significativo? Per la maggior parte della crittografia SSL dell'API verrà preferita. I requisiti di infrastruttura di SSL sono leggermente più elevati rispetto al testo in chiaro e nessun server di cache intermedio (leggi qui basato sul bordo) può partecipare alla memorizzazione nella cache di contenuti a cui si accede ripetutamente. Attenzione, la tua scalabilità potrebbe risentirne se hai assolutamente bisogno della crittografia offerta.
Norman H

36
@NormanH: Il tuo argomento è specioso, perché se qualcuno può vedere l'intera transazione che utilizzo per pubblicare su Twitter, potrebbe quindi impersonarmi e pubblicare i propri messaggi sotto il mio nome.
Greg Hewgill

3
Citando da Wikipedia sull'autenticazione Digest, "L'autenticazione dell'accesso Digest è uno dei metodi concordati che un server Web può utilizzare per negoziare le credenziali con il browser Web di un utente. Applica una funzione hash a una password prima di inviarla sulla rete, che è più sicuro dell'autenticazione di accesso di base, che invia testo in chiaro ". quale sarebbe un modo standard per realizzare ciò a cui ho accennato sopra. (Vedi en.wikipedia.org/wiki/Digest_access_authentication per i dettagli)
Norman H

5
"sending plaintext passwords over the net is almost universally a bad thing"- Puoi approfondire il "quasi"? Quando non è una cattiva idea?
toniedzwiedz,

2
@GregHewgill anche in una rete privata, non vorrei che i miei utenti fossero in grado di intercettare le password degli altri. L'unica situazione che mi viene in mente, in cui è OK per inviare una password su una rete è quando l'utente è solo nella rete. Il fatto che cose del genere accadano altrove non è certo un motivo per permetterlo.
toniedzwiedz,

115

Non esistono standard per REST diversi da HTTP. Ci sono servizi REST stabiliti là fuori. Ti suggerisco di dare un'occhiata a loro e avere un'idea di come funzionano.

Ad esempio, abbiamo preso in prestito molte idee dal servizio REST S3 di Amazon durante lo sviluppo del nostro. Ma abbiamo deciso di non utilizzare il modello di sicurezza più avanzato basato sulle firme delle richieste. L'approccio più semplice è l'autenticazione HTTP di base su SSL. Devi decidere cosa funziona meglio nella tua situazione.

Consiglio vivamente anche il libro RESTful Web Services di O'reilly. Spiega i concetti chiave e fornisce alcune buone pratiche. In genere puoi prendere il modello che forniscono e mapparlo sulla tua applicazione.


6
RESTful Web Services è sicuramente un ottimo libro. A deve leggere in questa area. È stato decisamente stimolante.
EdgarVerona,

6
Com'è possibile che @aehlke abbia ricevuto così tanti voti positivi per quel commento considerando (1) che non esiste una specifica REST e (2) la tesi sul campo sugli stili architettonici e la progettazione di architetture software basate su rete menziona esplicitamente REST e HTTP in 6.3: REST applicato a HTTP.

20
HTTP non è un requisito per REST.
nategood

1
Il libro RESTful Web Services è disponibile gratuitamente dal loro sito Web: crummy.com/writing/RESTful-Web-Services
icc97

Avevo intenzione di leggere il libro e poi mi sono reso conto che è principalmente destinato al formato XML. Dovrei usare questo libro considerando la popolarità di JSON? O non dipende dal formato di interscambio di dati. Hai bisogno di una guida.
Bhargav Jhaveri,

72

Potresti anche dare un'occhiata a OAuth , un protocollo aperto emergente per l'autorizzazione basata su token che si rivolge specificamente alle API http.

È molto simile all'approccio adottato da flickr e ricorda le apis "a riposo" del latte (non necessariamente buoni esempi di api riposanti, ma buoni esempi di approccio basato su token).


3
Ma sembra che oAuth a 2 zampe, che penso sia ciò che è necessario qui, non è coperto (mancanza di informazioni) tanto quanto quello a 3 zampe.
Redben,

4
OAuth riguarda la delega dell'autorizzazione, cioè io il proprietario delle informazioni / dell'account consento al servizio A di interagire con i miei dati sul servizio B (ad esempio, lascio che Twitter scriva sul mio Facebook). Non è un'autorizzazione in senso lato che riguarda il controllo di ciò che gli utenti possono fare sulle risorse (dati, informazioni, servizi ...). È qui che interviene XACML. XACML consente di definire criteri di autorizzazione su chi può fare cosa.
David Brossard,

60

C'è una grande lista di controllo trovata su Github :

Autenticazione

  • Non reinventare la ruota in autenticazione, generazione di token, archiviazione password. Usa gli standard.

  • Funzionalità di utilizzo Max Retrye jail in Login.

  • Usa la crittografia su tutti i dati sensibili.

JWT (token Web JSON)

  • Utilizzare una chiave complicata casuale (Segreto JWT) per rendere molto difficile forzare il token.

  • Non estrarre l'algoritmo dal payload. Forza l'algoritmo nel backend (HS256 o RS256).

  • Scadenza token ( TTL,RTTL ) il più breve possibile.

  • Non archiviare dati sensibili nel JWTpayload, possono essere facilmente decodificati.

OAuth

  • Convalida sempre redirect_uri sul lato server per consentire solo gli URL autorizzati.

  • Cerca sempre di scambiare codice e non token (non consentire response_type=token ).

  • Utilizzare il parametro state con un hash casuale per impedire CSRFilOAuth processo di autenticazione.

  • Definire l'ambito predefinito e convalidare i parametri dell'ambito per ciascuna applicazione.

Accesso

  • Limitare le richieste (limitazione) per evitare attacchi DDoS / forza bruta.

  • Utilizzare HTTPS sul lato server per evitare MITM (Man In The Middle Attack)

  • Utilizzare l' HSTSintestazione con SSL per evitare l'attacco della striscia SSL.

Ingresso

  • Utilizzare il metodo HTTP corretto in base all'operazione: GET(leggi), POST(crea), PUT/PATCH(sostituisci / aggiorna) e DELETE(per eliminare un record) e rispondere 405 Method Not Allowedse il metodo richiesto non è appropriato per la risorsa richiesta.

  • Convalida il tipo di contenuto Acceptnell'intestazione della richiesta (Negoziazione del contenuto) per consentire solo il formato supportato (ad es application/xml. application/json, Ecc.) E rispondere con 406 Not Acceptablerisposta se non corrispondente.

  • Convalida content-typedei dati ha registrato mentre accettate (ad esempio application/x-www-form-urlencoded, multipart/form-data, application/json, ecc).

  • Convalida dell'input dell'utente per evitare vulnerabilità comuni (ad esempio XSS, SQL-Injection, Remote Code Execution, ecc.).

  • Non utilizzare dati sensibili (credenziali, password, token di sicurezza o chiavi API) nell'URL, ma utilizzare standard Authorization un'intestazione .

  • Utilizzare un servizio gateway API per abilitare la memorizzazione nella cache, i Rate Limitcriteri (ad esempio quota, arresto spike, limite di velocità simultanea) e distribuire le risorse API in modo dinamico.

in lavorazione

  • Controllare se tutti gli endpoint sono protetti dall'autenticazione per evitare il processo di autenticazione interrotto.

  • L'ID risorsa personale dell'utente deve essere evitato. Usa / me / ordini invece di / utente / 654321 / ordini.

  • Non aumentare automaticamente gli ID. Usa invece UUID.

  • Se stai analizzando i file XML, assicurati che l'analisi dell'entità non sia abilitata per evitare XXE (attacco di entità esterna XML).

  • Se stai analizzando i file XML, assicurati che l'espansione dell'entità non sia abilitata per evitare miliardi di risate / bomba XML tramite l'attacco esponenziale dell'espansione dell'entità.

  • Utilizzare un CDN per i caricamenti di file.

  • Se hai a che fare con enormi quantità di dati, utilizza Lavoratori e Code per elaborare il più possibile in background e restituire rapidamente la risposta per evitare il blocco HTTP.

  • Non dimenticare di disattivare la modalità DEBUG .

Produzione

  • Invia X-Content-Type-Options: nosniffintestazione.

  • Invia X-Frame-Options: denyintestazione.

  • Invia Content-Security-Policy: default-src 'none'intestazione.

  • Rimuovere impronte digitali intestazioni - X-Powered-By, Server, X-AspNet-Versionetc.

  • Forza content-typeper la tua risposta, se ritorni, application/jsonil tipo di contenuto della risposta è application/json.

  • Non restituire dati sensibili come credenziali, password, token di sicurezza.

  • Restituire il codice di stato corretto in base all'operazione completata. (ad esempio 200 OK, 400 Bad Request, 401 Unauthorized, 405 Method Not Allowed, ecc).


1
Bella lista, anche se un po 'supponente - e inizia con un imho senza senso: "Non usare l'autent di base Usa l'autenticazione standard (ad esempio JWT, OAuth)". Non puoi ottenere più standard-y di Basic Auth, e ha il suo posto, specialmente per le API in cui i client non sono browser (per i browser JWT di solito è più adatto). OAuth, d'altra parte, sta utilizzando tutta un'altra serie di compromessi per l'autenticazione e non è realmente paragonabile a Basic Auth e JWT.
johndodo,

Hai ragione, BasicAuth con HTTPS è comune, ma è molto dibattuto: security.stackexchange.com/questions/988/… . Rimuoverò comunque questo punto.
Andrejs,

43

Sono sorpreso che SSL con i certificati client non sia ancora stato menzionato. Certo, questo approccio è davvero utile solo se puoi contare sulla comunità di utenti identificata dai certificati. Ma un certo numero di governi / aziende li rilasciano ai propri utenti. L'utente non deve preoccuparsi di creare ancora un'altra combinazione nome utente / password e l'identità viene stabilita su ogni connessione in modo che la comunicazione con il server possa essere completamente apolide, non sono necessarie sessioni utente. (Non implicare che una o tutte le altre soluzioni menzionate richiedano sessioni)


In realtà lo usiamo per alcune integrazioni e tunnel vpn crittografati per supportare sistemi più vecchi che non controlliamo che non possono comunicare su HTTPS.
Casey,

I certificati client possono creare problemi quando è necessario il bilanciamento del carico ... può essere fatto, ma è meno semplice.
Jeremy Logan,

2
@fiXedd - L'opposto è stata la mia esperienza con i certificati client perché sono davvero apolidi. Le connessioni autenticate con certificato client possono essere bilanciate con un bilanciamento del carico muto, indipendentemente dall'appiccicosità della connessione perché richiedono uno stato condiviso assolutamente zero tra client e server.
Stinkymatt,

4
Oh, puoi farlo .... puoi semplicemente fare in modo che il bilanciamento del carico inoltri il traffico TCP, ma ad esempio, non puoi avere il bilanciamento del carico come punto di terminazione per SSL.
Jeremy Logan,

È ancora sicuro se i certificati client e la relativa autorità principale sono autofirmati? L'autorità root verrà importata nelle autorità di certificazione radice attendibili del client.
Joyce,

38

Tutti in queste risposte hanno trascurato il vero controllo / autorizzazione dell'accesso.

Se, ad esempio, le tue API REST / i servizi web riguardano il POST / RICEZIONE di cartelle cliniche, potresti voler definire una politica di controllo degli accessi su chi può accedere ai dati e in quali circostanze. Per esempio:

  • i medici possono ottenere la cartella clinica di un paziente con cui hanno rapporti di cura
  • nessuno può POSTARE i dati medici al di fuori delle ore di pratica (es. da 9 a 5)
  • gli utenti finali possono ottenere cartelle cliniche di loro proprietà o cartelle cliniche di pazienti per i quali sono tutori
  • gli infermieri possono AGGIORNARE la cartella clinica di un paziente appartenente alla stessa unità dell'infermiere.

Per definire e implementare tali autorizzazioni dettagliate, è necessario utilizzare un linguaggio di controllo degli accessi basato sugli attributi chiamato XACML, il linguaggio di markup di controllo degli accessi eXtensible.

Gli altri standard qui sono per i seguenti:

  • OAuth: id. federazione e delega dell'autorizzazione, ad es. lasciare che un servizio agisca per mio conto su un altro servizio (Facebook può pubblicare sul mio Twitter)
  • SAML: federazione identità / web SSO. SAML riguarda moltissimo chi è l'utente.
  • Standard WS-Security / WS- *: questi si concentrano sulla comunicazione tra i servizi SOAP. Sono specifici del formato di messaggistica (SOAP) a livello di applicazione e trattano aspetti della messaggistica, ad esempio affidabilità, sicurezza, riservatezza, integrità, atomicità, eventi ... Nessuno riguarda il controllo degli accessi e tutti sono specifici di SOAP.

XACML è indipendente dalla tecnologia. Può essere applicato ad app java, .NET, Python, Ruby ... servizi web, API REST e altro.

Le seguenti sono risorse interessanti:


2
Non capisco perché non puoi semplicemente implementare un sistema token che otterrà l'utente e le sue autorizzazioni che saranno essenzialmente la stessa cosa?
Stan,

Puoi adottare un approccio basato su token. Funziona anche bene, ma hai ancora bisogno della logica che definisce quali autorizzazioni ottengono gli utenti, in altre parole, quali autorizzazioni inserire nel token. Questo è ciò che XACML può aiutarti a raggiungere. Inoltre evita il gonfiamento del token.
David Brossard,

2
Come commento laterale, in che modo "9 a 5" contribuisce alla sicurezza? Come se gli attaccanti fossero attivi solo di notte? Per non parlare delle gravi conseguenze sull'uso, come se i medici lavorassero solo "da 9 a 5".
Roland,

Questo è un requisito comune negli scenari sanitari. Dai un'occhiata a HL7 per esempio. Ci sono anche scenari di rottura nel caso in cui un medico abbia bisogno di accedere al di fuori degli orari. Per quanto riguarda gli hacker, una volta che sono in tutte le scommesse sono disattivate
David Brossard, l'

1
Alcuni dei miei colleghi lo stanno indagando davvero. Grazie @SimplyG.
David Brossard,

25

Ho usato OAuth alcune volte e ho anche usato altri metodi (BASIC / DIGEST). Consiglio vivamente OAuth. Il seguente link è il miglior tutorial che ho visto sull'uso di OAuth:

http://hueniverse.com/oauth/guide/


Anche se questa è una risposta molto antica relativa a OAuth 1.0, vale la pena notare che l'autore del link che hai citato aveva questo da dire su OAuth 2.0 : "Sono giunto alla conclusione che OAuth 2.0 è un cattivo protocollo ... Se confrontato con OAuth 1.0, la specifica 2.0 è più complessa, meno interoperabile, meno utile, più incompleta e, soprattutto, meno sicura. " . Per essere chiari, il commento che sto citando è stato fatto diversi anni dopo aver pubblicato la tua risposta.
skomisa,

17

Uno dei migliori post che abbia mai incontrato in merito alla sicurezza in relazione a REST è finito su 1 RainDrop . Le API di MySpace usano OAuth anche per la sicurezza e hai pieno accesso ai loro canali personalizzati nel codice RestChess, con cui ho fatto molte esplorazioni. Questo è stato demo su Mix e puoi trovare i post qui .


Grazie per il link (1 RainDrop) - Discussione molto interessante sulla sicurezza in relazione a SOAP v REST
Nathan

15

Grazie per l'eccellente consiglio. Abbiamo finito per usare un'intestazione HTTP personalizzata per passare un token di identità dal client al servizio, in preparazione per l'integrazione della nostra API RESTful con l'imminente framework Zermatt Identity di Microsoft. Ho descritto il problema qui e la nostra soluzione qui . Ho anche preso tweakt il consiglio di e acquistato RESTful Web Services - un ottimo libro se stai costruendo un'API RESTful di qualsiasi tipo.


1
Questo approccio mi sembra sospetto. Cosa impedisce a un utente malintenzionato di utilizzare il token di identità per mascherare il client? HTTPS non protegge l'URL o le intestazioni l'ultima volta che ho controllato ...
Gili,

2
Hmmm ... non sono sicuro di aver ragione. Credo che, tranne per le poche intestazioni richieste per capire quale tipo di crittografia è richiesta, tutte le altre intestazioni sono crittografate.
Nathan,

51
Questo è sbagliato. HTTPS protegge TUTTO. Funziona così: stretta di mano TCP ... stretta di mano TLS ... <ENCRYPTED> GET / foo 200 OK ... smontaggio </ENCRYPTED>.
Mark Renouf,

1
Nota che puoi anche passare un token come cookie (anziché come intestazione personalizzata). Ciò si comporta bene nei browser in quanto utilizza un'intestazione HTTP con comportamenti standard nella maggior parte dei toolkit e delle applicazioni. Dal lato del servizio, il cookie non deve essere correlato a una sessione, è possibile utilizzarlo per comunicare qualsiasi token desiderato.
Bruce Alderson,

11
La Wayback Machine è una cosa bellissima: descrizione e soluzione del
cjc343,


7

Consiglierei OAuth 2/3. Puoi trovare maggiori informazioni su http://oauth.net/2/


8
Cura di elaborare perché consiglieresti la versione 2 quando rimane in gran parte incompleta? IMHO, la versione 1.0a rimane una soluzione solida per la maggior parte delle app.
Butifarra,

6

Ho cercato molto sulla sicurezza della tranquillità e abbiamo anche finito con l'uso di token tramite cookie dal client al server per autenticare le richieste. Ho usato la sicurezza primaverile per l'autorizzazione delle richieste in servizio perché dovevo autenticare e autorizzare ogni richiesta in base a criteri di sicurezza specifici già presenti nel database.


6

Il fatto che il mondo SOAP sia piuttosto ben coperto dagli standard di sicurezza non significa che sia sicuro per impostazione predefinita. In primo luogo, gli standard sono molto complessi. La complessità non è molto amica della sicurezza e delle vulnerabilità dell'implementazione come gli attacchi di wrapping della firma XML sono endemiche qui.

Per quanto riguarda l'ambiente .NET, non aiuterò molto, ma "Costruire servizi Web con Java" (un mattone con ~ 10 autori) mi ha aiutato molto a capire l'architettura di sicurezza WS- * e, soprattutto, le sue stranezze.


4

REST stesso non offre standard di sicurezza, ma cose come OAuth e SAML stanno rapidamente diventando gli standard in questo spazio. Tuttavia, l'autenticazione e l'autorizzazione sono solo una piccola parte di ciò che è necessario considerare. Molte delle vulnerabilità note relative alle applicazioni Web si applicano molto alle API REST. Devi considerare la convalida dell'input, il cracking della sessione, i messaggi di errore inappropriati, le vulnerabilità interne dei dipendenti e così via. È un argomento importante.


4

Voglio aggiungere (in linea con stinkeymatt), la soluzione più semplice sarebbe quella di aggiungere certificati SSL al tuo sito. In altre parole, assicurati che l'URL sia HTTPS: //. Questo coprirà la tua sicurezza di trasporto (bang for the buck). Con l'URL di RESTful, l'idea è di mantenerlo semplice (a differenza di WS * security / SAML), è possibile utilizzare oAuth2 / openID connect o anche Basic Auth (in casi semplici). Ma avrai ancora bisogno di SSL / HTTPS. Controlla la sicurezza dell'API Web ASP.NET 2 qui: http://www.asp.net/web-api/overview/security (articoli e video)


3

Come ha finito @Nathan con il quale si tratta di una semplice intestazione HTTP, e alcuni avevano detto OAuth2 e certificati SSL lato client. L'essenza di questo è questo ... l'API REST non dovrebbe gestire la sicurezza in quanto dovrebbe essere al di fuori dell'ambito dell'API.

Invece un livello di sicurezza dovrebbe essere messo al di sopra di esso, che si tratti di un'intestazione HTTP dietro un proxy web (un approccio comune come SiteMinder, Zermatt o persino Apache HTTPd), o complicato come OAuth 2.

La cosa fondamentale è che le richieste dovrebbero funzionare senza alcuna interazione con l'utente finale. Tutto ciò che serve è garantire che la connessione all'API REST sia autenticata. In Java EE abbiamo l'idea di un userPrincipalche può essere ottenuto su un HttpServletRequest. È inoltre gestito nel descrittore di distribuzione che un modello di URL può essere protetto, pertanto il codice API REST non deve più essere verificato.

Nel mondo WCF, vorrei usare ServiceSecurityContext.Current per ottenere l'attuale contesto di sicurezza. È necessario configurare l'applicazione per richiedere l'autenticazione.

C'è un'eccezione all'affermazione che ho avuto sopra e che è l'uso di un nonce per evitare replay (che può essere un attacco o qualcuno che sta inviando gli stessi dati due volte). Quella parte può essere gestita solo nel livello applicazione.


3

Per la sicurezza delle applicazioni Web, dovresti dare un'occhiata a OWASP ( https://www.owasp.org/index.php/Main_Page ) che fornisce i foglietti illustrativi per vari attacchi alla sicurezza. È possibile incorporare quante più misure possibili per proteggere l'applicazione. Per quanto riguarda la sicurezza delle API (autorizzazione, autenticazione, gestione delle identità), esistono diversi modi come già menzionato (Basic, Digest e OAuth). Ci sono buchi di loop in OAuth1.0, quindi puoi usare OAuth1.0a (OAuth2.0 non è ampiamente adottato a causa di problemi con le specifiche)


2

È passato un po 'di tempo ma la domanda è ancora rilevante, anche se la risposta potrebbe essere cambiata un po'.

Un gateway API sarebbe una soluzione flessibile e altamente configurabile. Ho testato e usato un po ' KONG e mi è piaciuto molto quello che ho visto. KONG fornisce una propria API REST di amministrazione che è possibile utilizzare per gestire gli utenti.

Express-gateway.io è più recente ed è anche un gateway API.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.