Passa al contenuto principale

8. Security Considerations (Considerazioni sulla sicurezza)

8.1. Protecting the Authorization Code (Protezione del codice di autorizzazione)

Le opzioni di URI di reindirizzamento documentate nella Sezione 7 condividono il vantaggio che solo un'app nativa sullo stesso dispositivo o il sito web dell'app stessa può ricevere il codice di autorizzazione (Authorization Code), il che limita la superficie di attacco. Tuttavia, l'intercettazione del codice da parte di un'app nativa diversa in esecuzione sullo stesso dispositivo può essere possibile.

Una limitazione dell'utilizzo di schemi URI per uso privato (Private-Use URI Schemes) per gli URI di reindirizzamento è che più app possono tipicamente registrare lo stesso schema, il che rende indeterminato quale app riceverà il codice di autorizzazione. La Sezione 1 di PKCE [RFC7636] descrive in dettaglio come questa limitazione possa essere utilizzata per eseguire un attacco di intercettazione del codice.

Gli URI di reindirizzamento basati su IP di loopback possono essere suscettibili all'intercettazione da parte di altre app che accedono alla stessa interfaccia di loopback su alcuni sistemi operativi.

I reindirizzamenti con schema "https" rivendicati dall'app sono meno suscettibili all'intercettazione dell'URI a causa della presenza dell'autorità URI, ma l'app è ancora un client pubblico (Public Client); inoltre, l'URI viene inviato utilizzando il gestore di distribuzione URI del sistema operativo con proprietà di sicurezza sconosciute.

Il protocollo PKCE [RFC7636] è stato creato specificamente per mitigare questo attacco. Si tratta di un'estensione di prova di possesso (Proof-of-Possession Extension) per OAuth 2.0 che protegge il codice di autorizzazione dall'essere utilizzato se viene intercettato. Per fornire protezione, questa estensione fa generare al client un verificatore secreto (Secret Verifier); passa un hash di questo verificatore nella richiesta di autorizzazione iniziale e deve (MUST) presentare il verificatore non hashato quando riscatta il codice di autorizzazione. Un'app che ha intercettato il codice di autorizzazione non sarebbe in possesso di questo segreto, rendendo il codice inutile.

La Sezione 6 richiede (MUST) che sia i client che i server utilizzino PKCE per i client di app native pubbliche. I server di autorizzazione (Authorization Servers) dovrebbero (SHOULD) rifiutare le richieste di autorizzazione da app native che non utilizzano PKCE restituendo un messaggio di errore, come definito nella Sezione 4.4.1 di PKCE [RFC7636].

8.2. OAuth Implicit Grant Authorization Flow (Flusso di autorizzazione con concessione implicita OAuth)

Il flusso di autorizzazione con concessione implicita OAuth 2.0 (definito nella Sezione 4.2 di OAuth 2.0 [RFC6749]) funziona generalmente con la pratica di eseguire la richiesta di autorizzazione nel browser e ricevere la risposta di autorizzazione tramite comunicazione inter-app basata su URI. Tuttavia, poiché il flusso implicito non può essere protetto da PKCE [RFC7636] (che è richiesto nella Sezione 8.1), l'uso del flusso implicito con app native NON è RACCOMANDATO (NOT RECOMMENDED).

I token di accesso (Access Tokens) concessi tramite il flusso implicito non possono nemmeno essere aggiornati senza l'interazione dell'utente, rendendo il flusso di concessione del codice di autorizzazione (Authorization Code Grant Flow) -- che può emettere token di aggiornamento (Refresh Tokens) -- l'opzione più pratica per le autorizzazioni di app native che richiedono l'aggiornamento dei token di accesso.

8.3. Loopback Redirect Considerations (Considerazioni sui reindirizzamenti di loopback)

Gli URI di reindirizzamento dell'interfaccia di loopback utilizzano lo schema "http" (cioè, senza Transport Layer Security (TLS)). Questo è accettabile per gli URI di reindirizzamento dell'interfaccia di loopback poiché la richiesta HTTP non lascia mai il dispositivo.

I client dovrebbero (should) aprire la porta di rete solo all'avvio della richiesta di autorizzazione e chiuderla una volta restituita la risposta.

I client dovrebbero (should) ascoltare solo sull'interfaccia di rete di loopback, al fine di evitare interferenze da parte di altri attori di rete.

Sebbene gli URI di reindirizzamento che utilizzano localhost (cioè, http://localhost:{port}/{path}) funzionino in modo simile ai reindirizzamenti IP di loopback descritti nella Sezione 7.3, l'uso di localhost NON è RACCOMANDATO (NOT RECOMMENDED). Specificare un URI di reindirizzamento con il letterale IP di loopback anziché localhost evita di ascoltare inavvertitamente su interfacce di rete diverse dall'interfaccia di loopback. È anche meno suscettibile ai firewall lato client e alla risoluzione del nome host mal configurata sul dispositivo dell'utente.

8.4. Registration of Native App Clients (Registrazione dei client di app native)

Tranne quando si utilizza un meccanismo come la registrazione dinamica del client (Dynamic Client Registration) [RFC7591] per fornire segreti per istanza, le app native sono classificate come client pubblici, come definito dalla Sezione 2.1 di OAuth 2.0 [RFC6749]; devono (MUST) essere registrate presso il server di autorizzazione come tali. I server di autorizzazione devono (MUST) registrare il tipo di client nei dettagli di registrazione del client al fine di identificare ed elaborare le richieste di conseguenza.

I server di autorizzazione devono (MUST) richiedere ai client di registrare il loro URI di reindirizzamento completo (incluso il componente del percorso) e rifiutare le richieste di autorizzazione che specificano un URI di reindirizzamento che non corrisponde esattamente a quello registrato; l'eccezione sono i reindirizzamenti di loopback, dove è richiesta una corrispondenza esatta tranne per il componente della porta URI.

Per i reindirizzamenti basati su schemi URI per uso privato, i server di autorizzazione dovrebbero (SHOULD) applicare il requisito della Sezione 7.1 che i client utilizzino schemi basati su nomi di dominio inversi. Come minimo, qualsiasi schema URI per uso privato che non contenga un carattere punto (".") dovrebbe (SHOULD) essere rifiutato.

Oltre alle proprietà resistenti alle collisioni, richiedere uno schema URI basato su un nome di dominio sotto il controllo dell'app può aiutare a dimostrare la proprietà nel caso di una disputa in cui due app rivendicano lo stesso schema URI per uso privato (dove un'app agisce maliziosamente). Ad esempio, se due app rivendicassero "com.example.app", il proprietario di "example.com" potrebbe richiedere all'operatore dell'app store di rimuovere l'app contraffatta. Una tale petizione è più difficile da dimostrare se è stato utilizzato uno schema URI generico.

I server di autorizzazione possono (MAY) richiedere l'inclusione di altre informazioni specifiche della piattaforma, come il nome del pacchetto o del bundle dell'app, o altre informazioni che possono essere utili per verificare l'identità dell'app chiamante su sistemi operativi che supportano tali funzioni.

8.5. Client Authentication (Autenticazione del client)

I segreti che sono inclusi staticamente come parte di un'app distribuita a più utenti non dovrebbero essere trattati come segreti confidenziali, poiché un utente può ispezionare la propria copia e apprendere il segreto condiviso. Per questo motivo, e per quelli indicati nella Sezione 5.3.1 di [RFC6819], NON è RACCOMANDATO (NOT RECOMMENDED) che i server di autorizzazione richiedano l'autenticazione del client dei client di app native pubbliche utilizzando un segreto condiviso, poiché questo serve poco valore oltre all'identificazione del client che è già fornita dal parametro di richiesta "client_id".

I server di autorizzazione che richiedono ancora un segreto condiviso incluso staticamente per i client di app native devono (MUST) trattare il client come un client pubblico (come definito dalla Sezione 2.1 di OAuth 2.0 [RFC6749]), e non accettare il segreto come prova dell'identità del client. Senza misure aggiuntive, tali client sono soggetti a impersonificazione del client (vedere Sezione 8.6).

8.6. Client Impersonation (Impersonificazione del client)

Come indicato nella Sezione 10.2 di OAuth 2.0 [RFC6749], il server di autorizzazione NON dovrebbe (SHOULD NOT) elaborare automaticamente le richieste di autorizzazione senza il consenso o l'interazione dell'utente, tranne quando l'identità del client può essere assicurata. Questo include il caso in cui l'utente ha precedentemente approvato una richiesta di autorizzazione per un determinato ID client -- a meno che l'identità del client non possa essere provata, la richiesta dovrebbe (SHOULD) essere elaborata come se nessuna richiesta precedente fosse stata approvata.

Misure come i reindirizzamenti con schema "https" rivendicati possono (MAY) essere accettate dai server di autorizzazione come prova di identità. Alcuni sistemi operativi possono offrire funzionalità di identità alternative specifiche della piattaforma che possono (MAY) essere accettate, a seconda dei casi.

8.7. Fake External User-Agents (User-agent esterni falsi)

L'app nativa che avvia la richiesta di autorizzazione ha un alto grado di controllo sull'interfaccia utente e può potenzialmente presentare un user-agent esterno falso (External User-Agent), ovvero un user-agent incorporato (Embedded User-Agent) fatto apparire come un user-agent esterno.

Quando tutti gli attori buoni utilizzano user-agent esterni, il vantaggio è che è possibile per gli esperti di sicurezza rilevare gli attori cattivi, poiché chiunque falsifichi un user-agent esterno è dimostrabilmente cattivo. D'altra parte, se gli attori buoni e cattivi utilizzano allo stesso modo user-agent incorporati, gli attori cattivi non hanno bisogno di falsificare nulla, rendendoli più difficili da rilevare. Una volta rilevata un'app dannosa, potrebbe essere possibile utilizzare questa conoscenza per inserire nella lista nera la firma dell'app nel software di scansione malware, intraprendere azioni di rimozione (nel caso di app distribuite tramite app store) e altri passaggi per ridurre l'impatto e la diffusione dell'app dannosa.

I server di autorizzazione possono anche proteggersi direttamente contro i user-agent esterni falsi richiedendo un fattore di autenticazione disponibile solo per i veri user-agent esterni.

Gli utenti particolarmente preoccupati per la loro sicurezza quando utilizzano schede del browser integrate nell'app possono anche compiere il passaggio aggiuntivo di aprire la richiesta nel browser completo dalla scheda del browser integrata nell'app e completare l'autorizzazione lì, poiché la maggior parte delle implementazioni del pattern di scheda del browser integrata nell'app offre tale funzionalità.

8.8. Malicious External User-Agents (User-agent esterni dannosi)

Se un'app dannosa è in grado di configurarsi come gestore predefinito per gli URI con schema "https" nel sistema operativo, sarà in grado di intercettare le richieste di autorizzazione che utilizzano il browser predefinito e abusare di questa posizione di fiducia per scopi dannosi come il phishing dell'utente.

Questo attacco non è limitato a OAuth; un'app dannosa configurata in questo modo presenterebbe un rischio generale e continuo per l'utente oltre l'uso di OAuth da parte delle app native. Molti sistemi operativi mitigano questo problema richiedendo un'azione esplicita dell'utente per modificare il gestore predefinito per gli URI con schema "http" e "https".

8.9. Cross-App Request Forgery Protections (Protezioni contro la falsificazione di richieste tra app)

La Sezione 5.3.5 di [RFC6819] raccomanda di utilizzare il parametro "state" per collegare le richieste e le risposte del client al fine di prevenire attacchi CSRF (Cross-Site Request Forgery).

Per mitigare gli attacchi in stile CSRF sui canali di comunicazione inter-app basati su URI (cosiddetta "falsificazione di richieste tra app"), è similmente RACCOMANDATO (RECOMMENDED) che le app native includano un numero casuale sicuro ad alta entropia nel parametro "state" della richiesta di autorizzazione e rifiutino qualsiasi risposta di autorizzazione in arrivo senza un valore di stato che corrisponda a una richiesta di autorizzazione in uscita in sospeso.

8.10. Authorization Server Mix-Up Mitigation (Mitigazione della confusione del server di autorizzazione)

Per proteggersi da un server di autorizzazione compromesso o dannoso che attacca un altro server di autorizzazione utilizzato dalla stessa app, è RICHIESTO (REQUIRED) che venga utilizzato un URI di reindirizzamento univoco per ciascun server di autorizzazione utilizzato dall'app (ad esempio, variando il componente del percorso), e che le risposte di autorizzazione vengano rifiutate se l'URI di reindirizzamento su cui sono state ricevute non corrisponde all'URI di reindirizzamento in una richiesta di autorizzazione in uscita.

L'app nativa deve (MUST) memorizzare l'URI di reindirizzamento utilizzato nella richiesta di autorizzazione con i dati della sessione di autorizzazione (cioè, insieme a "state" e altri dati correlati) e deve (MUST) verificare che l'URI su cui è stata ricevuta la risposta di autorizzazione corrisponda esattamente.

Il requisito della Sezione 8.4, in particolare che i server di autorizzazione rifiutino le richieste con URI che non corrispondono a quanto registrato, è anche necessario per prevenire tali attacchi.

8.11. Non-Browser External User-Agents (User-agent esterni non-browser)

Questa best practice raccomanda un tipo particolare di user-agent esterno: il browser dell'utente. Altri pattern di user-agent esterni possono anche essere validi per OAuth sicuro e utilizzabile. Questo documento non fa commenti su tali pattern.

8.12. Embedded User-Agents (User-agent incorporati)

La Sezione 9 di OAuth 2.0 [RFC6749] documenta due approcci per le app native per interagire con l'endpoint di autorizzazione. Questa best current practice richiede (MUST NOT) che le app native non utilizzino user-agent incorporati per eseguire richieste di autorizzazione e consente che gli endpoint di autorizzazione possano (MAY) intraprendere misure per rilevare e bloccare le richieste di autorizzazione in user-agent incorporati. Le considerazioni sulla sicurezza per questi requisiti sono dettagliate qui.

Gli user-agent incorporati sono un metodo alternativo per autorizzare le app native. Questi user-agent incorporati sono, per definizione, non sicuri per l'uso da parte di terze parti rispetto al server di autorizzazione, poiché l'app che ospita l'user-agent incorporato può accedere alle credenziali di autenticazione complete dell'utente, non solo alla concessione di autorizzazione OAuth che era destinata all'app.

Nelle tipiche implementazioni basate su web-view di user-agent incorporati, l'applicazione host può registrare ogni pressione di tasto inserita nel modulo di accesso per catturare nomi utente e password, inviare automaticamente moduli per aggirare il consenso dell'utente e copiare i cookie di sessione e utilizzarli per eseguire azioni autenticate come utente.

Anche quando utilizzati da app affidabili appartenenti alla stessa parte del server di autorizzazione, gli user-agent incorporati violano il principio del minimo privilegio avendo accesso a credenziali più potenti di quelle di cui hanno bisogno, aumentando potenzialmente la superficie di attacco.

Incoraggiare gli utenti a inserire credenziali in un user-agent incorporato senza la consueta barra degli indirizzi e le funzionalità di convalida del certificato visibili che hanno i browser rende impossibile per l'utente sapere se stanno accedendo al sito legittimo; anche quando lo sono, li addestra che va bene inserire credenziali senza convalidare prima il sito.

A parte le preoccupazioni sulla sicurezza, gli user-agent incorporati non condividono lo stato di autenticazione con altre app o il browser, richiedendo all'utente di accedere per ogni richiesta di autorizzazione, il che è spesso considerato un'esperienza utente inferiore.