Segreti OAuth nelle app mobili


137

Quando si utilizza il protocollo OAuth, è necessaria una stringa segreta ottenuta dal servizio a cui si desidera delegare. Se lo stai facendo in un'app Web, puoi semplicemente archiviare il segreto nella tua base di dati o nel file system, ma qual è il modo migliore per gestirlo in un'app mobile (o in un'app desktop)?

Memorizzare la stringa nell'app non è ovviamente buono, poiché qualcuno potrebbe facilmente trovarla e abusarla.

Un altro approccio potrebbe essere quello di archiviarlo sul server e far sì che l'app lo recuperi ad ogni esecuzione, senza mai memorizzarlo sul telefono. Questo è quasi altrettanto negativo, perché devi includere l'URL nell'app.

L'unica soluzione praticabile che posso trovare è prima ottenere il token di accesso normalmente (preferibilmente utilizzando una vista Web all'interno dell'app), quindi instradare tutte le ulteriori comunicazioni attraverso il nostro server, che aggiungerebbe il segreto ai dati della richiesta e comunicare con il fornitore. Poi di nuovo, sono un sostenitore della sicurezza, quindi mi piacerebbe davvero sentire le opinioni di alcune persone competenti su questo. Non mi sembra che la maggior parte delle app faccia di tutto per garantire la sicurezza (ad esempio, Facebook Connect sembra presumere che tu abbia messo il segreto in una stringa direttamente nella tua app).

Un'altra cosa: non credo che il segreto sia coinvolto nella richiesta iniziale del token di accesso, quindi ciò potrebbe essere fatto senza coinvolgere il nostro server. Ho ragione?


Scusate se non capisco l'ovvio, ma qual è il problema con l'archiviazione dei codici nel database dell'applicazione? Poiché tali token vengono generati e archiviati dopo che l'utente ha autenticato il proprio account, quindi dovrebbe essere sicuro supporre che detto utente desideri che il dispositivo mobile memorizzi l'accesso per avere accesso.
colpì il

Anche dopo che l'utente ti ha autorizzato ad accedere al proprio account (su Twitter, diciamo) devi usare un segreto che hai ottenuto dal servizio a cui stai tentando di accedere. Questo segreto viene utilizzato in tutte le comunicazioni con il proprio server, insieme alla chiave di autenticazione e ad alcune altre chiavi. Quindi sì, è possibile memorizzare la chiave di accesso, ma il segreto non deve essere archiviato, poiché potrebbe essere utilizzato con qualsiasi chiave di autenticazione per abusare del servizio. Ancora una volta, sarei felice di essere corretto da persone che ne sanno di più.
Felixyz,

1
OAuth offre un metodo di autenticazione che protegge i dati di accesso dell'utente originale. Per rendere possibile ciò, viene generata una nuova combinazione di accesso unica che funziona solo insieme alla combinazione di tasti dell'applicazione unica . Il grande vantaggio della memorizzazione dei dati di accesso dell'utente è che questi sono completamente sicuri dopo la prima autorizzazione e in ogni caso di violazione l'utente può semplicemente revocare l'accesso dell'autorizzazione. E ovviamente non salvare il segreto non avrebbe senso in quanto l'utente avrebbe bisogno di riautenticare in seguito (e questo non è ciò che l'utente desidera quando dà l'accesso all'applicazione).
colpì il

@poke La chiave di autenticazione ottenuta quando l'utente approva la tua app con il provider deve essere salvata, ma il token segreto che hai ricevuto dal provider prima di rilasciare l'app non dovrebbe (nel caso di un'app desktop o mobile; se è un'app Web è ovviamente possibile memorizzare la chiave sul server, come indicato nella domanda).
Felixyz,

4
Secondo la mia comprensione di oAuth-- Nel caso di un'app desktop è molto semplice annusare / monitorare il traffico HTTP / HTTPS con strumenti come questo ieinspector.com/httpanalyzer/index.html Quindi il tuo token e token segreto possono essere trovati entrambi facilmente. Quindi l'unica protezione è il tuo segreto del consumatore. Ora se il tuo negozio è il segreto all'interno dell'app e qualcuno è in grado di trovarlo, diventa un gioco da ragazzi impersonare qualsiasi altra app come la tua app. Correggimi se sbaglio.
Varun,

Risposte:


38

Sì, questo è un problema con il design OAuth che stiamo affrontando. Abbiamo optato per il proxy di tutte le chiamate tramite il nostro server. OAuth non è stato completamente eliminato per quanto riguarda le app desktop. Non esiste una soluzione perfetta al problema che ho riscontrato senza modificare OAuth.

Se ci pensi e fai la domanda sul perché abbiamo segreti, è principalmente per il provisioning e la disabilitazione delle app. Se il nostro segreto è compromesso, il provider può davvero revocare l'intera app. Dal momento che dobbiamo incorporare il nostro segreto nell'app desktop, siamo un po 'fregati.

La soluzione è avere un segreto diverso per ogni app desktop. OAuth non semplifica questo concetto. Un modo è far andare l'utente a creare un segreto da solo e inserire la chiave da solo nella tua app desktop (alcune app di Facebook hanno fatto qualcosa di simile per molto tempo, facendo sì che l'utente andasse e creasse Facebook per impostare i propri quiz personalizzati e una schifezza). Non è una grande esperienza per l'utente.

Sto lavorando alla proposta di un sistema di delega per OAuth. Il concetto è che usando la nostra chiave segreta che otteniamo dal nostro fornitore, potremmo inviare il nostro segreto delegato ai nostri client desktop (uno per ogni app desktop in pratica) e quindi durante il processo di autenticazione inviamo quella chiave al livello superiore provider che ci richiama e riconvalida con noi. In questo modo possiamo revocare i nostri segreti che forniamo a ciascun client desktop. (Prendendo in prestito molto di come funziona da SSL). L'intero sistema sarebbe perfetto per i servizi Web a valore aggiunto e che trasferiscono le chiamate a un servizio Web di terze parti.

Il processo potrebbe anche essere eseguito senza richiamate di verifica della delega se il provider di livello superiore fornisce un'API per generare e revocare nuovi segreti delegati. Facebook sta facendo qualcosa di simile consentendo alle app di Facebook di consentire agli utenti di creare sub-app.

Ci sono alcuni discorsi sul problema online:

http://blog.atebits.com/2009/02/fixing-oauth/ http://groups.google.com/group/twitter-development-talk/browse_thread/thread/629b03475a3d78a1/de1071bf4b820c14#de1071bf4b820c14

La soluzione di Twitter e Yammer è una soluzione pin di autenticazione: https://dev.twitter.com/oauth/pin-based https://www.yammer.com/api_oauth_security_addendum.html


Questo è molto interessante, anche se conferma ciò che temevo, che OAuth non è così eccezionale per le app desktop / mobili. Naturalmente, un utente malintenzionato dovrebbe prima ottenere il segreto e poi anche annusare le credenziali di qualcuno, quindi ci vorrebbe abbastanza determinazione. La soluzione pin è ok per desktop ma per mani pesanti per dispositivi mobili.
Felixyz,

In che modo il tuo schema proposto potrebbe aiutare i servizi web a valore aggiunto, poiché questo problema non si applica a loro? Inoltre, non vedo come funzionerebbe con il provider che genera nuovi segreti, poiché sarebbe necessario un "master secret" per richiedere anche quei nuovi segreti, quindi avresti almeno bisogno di una chiamata al tuo server (che contiene il segreto principale). Ma questo è ovviamente meglio che instradare tutto il traffico attraverso il proprio server. Chiarimento molto gradito! E ti preghiamo di aggiornare qui mentre la tua proposta avanza!
Felixyz,

5
Solo curioso: come determini che la cosa che effettua una chiamata al tuo server proxy sia legittima?
davidtbernal,

1
In risposta a notJim: il rischio principale nel far uscire il segreto del consumatore è che le applicazioni dannose (o sciocche) possano essere sviluppate usando esso, offuscando la tua reputazione e aumentando il rischio di far chiudere l'applicazione legittima per abuso / uso improprio dell'API. Proxying di tutte le chiamate che richiedono il tuo segreto attraverso un'applicazione web che controlli, sei di nuovo in una posizione in cui puoi controllare i modelli di abuso e revocare l'accesso a livello di utente o di token prima che l'API che stai consumando decida di chiudere giù l'intero servizio.
Quasistoic,

Sono d'accordo con quasistoic qui, sarà necessario utilizzare un browser abilitato SSL per gestire la chiamata oauth. Questa è una buona cosa per alcuni motivi, inclusa la facile gestione di eventuali aggiornamenti di sicurezza in futuro, e nulla nell'applicazione effettiva dovrà essere aggiornato nel tempo. Zac sottolinea Twitter proponendo una soluzione PIN, che in realtà ho pensato anche io, perché non puoi fidarti dell'applicazione per ottenere in modo sicuro il codice. Suggerisco di utilizzare un "Nonce" con una crittografia moderna insieme al PIN e segreto per inviare in proxy le richieste tramite il server Web.
Segna l'

18

Con OAUth 2.0, puoi archiviare il segreto sul server. Utilizzare il server per acquisire un token di accesso che si sposta quindi sull'app ed è possibile effettuare chiamate direttamente dall'app alla risorsa.

Con OAuth 1.0 (Twitter), il segreto è necessario per effettuare chiamate API. Il proxy delle chiamate attraverso il server è l'unico modo per garantire che il segreto non sia compromesso.

Entrambi richiedono un meccanismo per cui il componente server sa che è il client che lo chiama. Questo tende a essere fatto durante l'installazione e l'utilizzo di un meccanismo specifico della piattaforma per ottenere un id app di qualche tipo nella chiamata al server.

(Sono l'editor delle specifiche di OAuth 2.0)


2
Puoi elaborare il "meccanismo specifico della piattaforma per ottenere un id app di qualche tipo"? In che modo il componente server verifica l'identità del client? Penso che questo possa essere fatto con il provisioning dei client. Ad esempio, distribuire un nuovo certificato SSL univoco su ciascun client. È questo che vuoi dire? Se è più complesso di questo, forse puoi fare riferimento a una scrittura più approfondita?
Cheeso,

2
Ricordo alcuni addetti alla sicurezza che parlavano di come ciò potesse essere fatto. Esiste una chiamata al sistema operativo che restituisce un token firmato che è quindi possibile inviare al server e verificare. Mi dispiace non ho i dettagli. È un errore che potrebbe usare alcuni buoni esempi.
Dick Hardt,

2
@DickHardt ma in questo scenario come ti assicuri che l'applicazione mobile sia davvero la tua app e non fraudolenta?
Rafael Membrives,

11

Una soluzione potrebbe essere quella di codificare il codice segreto OAuth nel codice, ma non come una semplice stringa. Offuscalo in qualche modo - dividilo in segmenti, sposta i caratteri di un offset, ruotalo - fai una o tutte queste cose. Un cracker può analizzare il tuo codice byte e trovare stringhe, ma il codice di offuscamento potrebbe essere difficile da capire.

Non è una soluzione infallibile, ma economica.

A seconda del valore dell'exploit, alcuni geniali cracker possono fare di tutto per trovare il tuo codice segreto. È necessario valutare i fattori: costo della soluzione lato server precedentemente menzionata, incentivo per i cracker a dedicare maggiori sforzi alla ricerca del codice segreto e alla complessità dell'offuscamento che è possibile implementare.


1
Sì, penso sia ragionevole. Ci vorrebbe molta determinazione per estrarre prima il segreto del consumatore e poi strappare le credenziali della gente per fare qualcosa di cattivo. Per le app di alto profilo, non sono sicuro che questo sarebbe abbastanza, ma per un'app media penso che tu abbia ragione che devi bilanciare i tempi di implementazione con una minaccia di sicurezza piuttosto piccola.
Felixyz,

7
Tutto ciò che serve è per un utente di esercitare lo sforzo e quindi pubblicare o condividere il tuo segreto. Una volta svelato il tuo segreto, il rischio che il tuo servizio venga chiuso completamente per abusi alle stelle, ed è completamente fuori dal tuo controllo.
Quasistoic,

8
L'offuscamento non è affatto sicurezza. Questo è peggio di nessuna sicurezza, perché dà allo sviluppatore un falso senso di sicurezza. en.wikipedia.org/wiki/Security_through_obscurity
Paul Legato

8
"L'offuscamento non è affatto sicurezza. Questo è peggio di nessuna sicurezza, perché dà allo sviluppatore un falso senso di sicurezza." Senza senso. Nessuno sta dicendo che l'offuscamento garantisce una buona sicurezza. Ma se ho intenzione di distribuire un segreto OAuth con il mio apk, è sicuramente meglio offuscare che no. L'offuscamento è ciò che Google consiglia anche quando si memorizzano chiavi / segreti in-app. Se non altro, queste misure tengono a bada gli hacker casuali, il che è meglio di niente. Dichiarazioni generali come la tua equivalgono alla sicurezza imperfetta senza sicurezza. Questo semplicemente non è vero. Imperfetto è solo imperfetto.
hungryghost,

1
L'offuscamento NON aiuta, perché non importa quanto spostamento o codifica fai, costruisci ancora la chiave insieme e la usi per creare la tua richiesta API. È abbastanza semplice agganciare dinamicamente le API nei punti giusti per scaricare la richiesta che stai inviando anche prima della crittografia HTTPS. Quindi, per favore, non incorporare chiavi segrete nella tua app a meno che non ci sia davvero alcuna alternativa possibile.
C0deH4cker,

6

Non archiviare il segreto all'interno dell'applicazione.

È necessario disporre di un server a cui l'applicazione può accedere tramite https (ovviamente) e su cui è memorizzato il segreto.

Quando qualcuno desidera accedere tramite l'applicazione mobile / desktop, l'applicazione inoltrerà semplicemente la richiesta al server che quindi aggiungerà il segreto e lo invierà al fornitore di servizi. Il tuo server può quindi dire alla tua applicazione se ha avuto successo o no.

Quindi, se hai bisogno di ottenere informazioni sensibili dal servizio (Facebook, Google, Twitter, ecc.), L'applicazione chiede al tuo server e il tuo server le fornirà all'applicazione solo se è correttamente connessa.

Non esiste davvero alcuna opzione se non quella di memorizzarla su un server. Nulla sul lato client è sicuro.

Nota

Detto questo, questo ti proteggerà solo dai client dannosi ma non dai client malvagi e non dai client malvagi (phising) ...

OAuth è un protocollo molto migliore nel browser che su desktop / mobile.


1
questo non semplifica la vita dell'hacker ?! perché ora, per accedere alle risorse del server, tecnicamente abbiamo solo bisogno dell'ID client, poiché il server aggiungerà comunque il segreto alla richiesta. mi sto perdendo qualcosa?
Hudi Ilfeld,

@HudiIlfeld Sì, ti manca qualcosa: il client deve accedere al server. Finché non ha effettuato l'accesso, il server non restituirà nulla. Un modo per gestirlo è dopo aver inviato le credenziali per la prima volta, il server restituisce un token di accesso al client e quindi il client invia questo token di accesso con ogni futura richiesta. Ci sono molte opzioni qui.
Gudradain,

4

Esiste una nuova estensione per il tipo di concessione del codice di autorizzazione chiamata Proof Key for Code Exchange (PKCE) . Con esso, non è necessario un segreto client.

PKCE (RFC 7636) è una tecnica per proteggere i client pubblici che non utilizzano un segreto client.

Viene utilizzato principalmente da app native e mobili, ma la tecnica può essere applicata anche a qualsiasi client pubblico. Richiede supporto aggiuntivo da parte del server di autorizzazione, quindi è supportato solo su determinati provider.

da https://oauth.net/2/pkce/

Per ulteriori informazioni, è possibile leggere l'intera RFC 7636 o questa breve introduzione .


2

Ecco qualcosa a cui pensare. Google offre due metodi di OAuth ... per le app Web, in cui si registra il dominio e si genera una chiave univoca, e per le app installate in cui si utilizza la chiave "anonimo".

Forse ho riflettuto su qualcosa nella lettura, ma sembra che condividere la chiave univoca della tua webapp con un'app installata sia probabilmente più sicuro dell'uso di "anonimo" nel metodo ufficiale delle app installate.


2

Con OAuth 2.0 puoi semplicemente utilizzare il flusso lato client per ottenere un token di accesso e quindi utilizzare questo token di accesso per autenticare tutte le ulteriori richieste. Quindi non hai assolutamente bisogno di un segreto.

Una bella descrizione di come implementare questo può essere trovata qui: https://aaronparecki.com/articles/2012/07/29/1/oauth2-simplified#mobile-apps


A condizione che il servizio supporti "il flusso lato client". Molti non lo fanno, invece richiedono l'ID client e il segreto client per ottenere questo token di accesso.
Damian Yerrick,

0

Non ho molta esperienza con OAuth, ma ogni richiesta non richiede non solo il token di accesso dell'utente, ma anche una chiave e un segreto per l'utente dell'applicazione? Quindi, anche se qualcuno ruba un dispositivo mobile e cerca di estrarre i dati da esso, avrebbe bisogno di una chiave dell'applicazione e di un segreto per poter effettivamente fare qualsiasi cosa.

Ho sempre pensato che l'intenzione dietro OAuth fosse tale che ogni Tom, Dick e Harry che avevano un mashup non dovessero archiviare le credenziali di Twitter in chiaro. Penso che risolva abbastanza bene quel problema nonostante i suoi limiti. Inoltre, non è stato davvero progettato pensando all'iPhone.


Hai ragione, OAuth è stato progettato principalmente pensando alle app web e sono sicuro che funzioni bene. Sì, è necessario il token e il segreto del consumatore per firmare ogni richiesta e il problema è dove archiviare il segreto. Se qualcuno ruba la chiave di accesso non è un grosso problema perché può essere revocato, ma se qualcuno ottiene la chiave utente ogni copia della tua app è stata compromessa.
Felixyz,

OAuth 1 ha richiesto la firma di ogni richiesta. OAuth 2 richiede solo il token di accesso. Entrambi richiedono la chiave e il segreto quando si acquisisce un token.
Dick Hardt,

0

Sono d'accordo con Felixyz. OAuth, sebbene migliore di Basic Auth, ha ancora molta strada da fare per essere una buona soluzione per le app mobili. Ho giocato con l'utilizzo di OAuth per autenticare un'app per telefono cellulare su un'app di Google App Engine. Il fatto che non sia possibile gestire in modo affidabile il segreto dell'utente sul dispositivo mobile significa che l'impostazione predefinita è utilizzare l'accesso "anonimo".

Il passaggio di autorizzazione del browser dell'implementazione OAuth di Google App Engine ti porta a una pagina in cui contiene testo come: "Il sito <some-site> richiede l'accesso al tuo account Google per i prodotti elencati di seguito"

YourApp (yourapp.appspot.com) - non affiliato a Google

eccetera

Prende <some-site> dal nome dominio / host utilizzato nell'URL di callback che fornisci, che può essere qualsiasi cosa su Android se usi uno schema personalizzato per intercettare il callback. Quindi, se usi l'accesso "anonimo" o il tuo segreto del consumatore è compromesso, allora chiunque potrebbe scrivere a un consumatore che imbroglia l'utente nel dare accesso alla tua app gae.

La pagina di autorizzazione di Google OAuth contiene anche molti avvisi che hanno 3 livelli di gravità a seconda che tu stia utilizzando chiavi "anonime", riservate al consumatore o pubbliche.

Roba abbastanza spaventosa per l'utente medio che non è tecnicamente esperto. Non mi aspetto di avere un'alta percentuale di completamento dell'iscrizione con quel tipo di cose in mezzo.

Questo post sul blog chiarisce come i segreti dei consumatori non funzionano davvero con le app installate. http://hueniverse.com/2009/02/should-twitter-discontinue-their-basic-auth-api/


0

Sto anche cercando di trovare una soluzione per l'autenticazione OAuth mobile e la memorizzazione di segreti all'interno del bundle dell'applicazione in generale.

E un'idea folle mi ha appena colpito: l'idea più semplice è quella di archiviare il segreto all'interno del binario, ma in qualche modo offuscato o, in altre parole, archiviare un segreto crittografato. Quindi, ciò significa che devi memorizzare una chiave per decrittografare il tuo segreto, che sembra averci portato al punto di partenza. Tuttavia, perché non utilizzare semplicemente una chiave che è già nel sistema operativo, ovvero è definita dal sistema operativo e non dall'applicazione.

Quindi, per chiarire la mia idea è che scegli una stringa definita dal sistema operativo, non importa quale. Quindi crittografa il tuo segreto usando questa stringa come chiave e memorizzalo nella tua app. Quindi durante il runtime, decodifica la variabile usando la chiave, che è solo una costante del sistema operativo. Qualsiasi hacker che sbircia nel tuo binario vedrà una stringa crittografata, ma nessuna chiave.

Funzionerà?


3
Buona idea, ma no. Il cracker vedrebbe semplicemente il binario che punta all'indirizzo della costante del sistema operativo.
GrayB,



0

Nessuna di queste soluzioni impedisce a un determinato hacker di sniffare i pacchetti inviati dal proprio dispositivo mobile (o emulatore) per visualizzare il segreto del client nelle intestazioni http.

Una soluzione potrebbe essere quella di disporre di un segreto dinamico costituito da un timestamp crittografato con una chiave di crittografia e un algoritmo privati. Il servizio quindi decodifica il segreto e determina se il timestamp è +/- 5 minuti.

In questo modo, anche se il segreto è compromesso, l'hacker sarà in grado di usarlo per un massimo di 5 minuti.


-2

Come altri hanno già detto, non dovrebbe esserci alcun problema reale con l'archiviazione locale del segreto sul dispositivo.

Inoltre, puoi sempre fare affidamento sul modello di sicurezza basato su UNIX di Android: solo la tua applicazione può accedere a ciò che scrivi nel file system. Scrivi semplicemente le informazioni sull'oggetto SharedPreferences predefinito della tua app.

Per ottenere il segreto, si dovrebbe ottenere l'accesso come root al telefono Android.


3
Come chi ha detto? Se intendi il commento di Poke, vedi la mia risposta che secret! = Chiave di autenticazione. Quest'ultimo può essere tranquillamente archiviato, il primo no. Non conosco Android, ma ottenere l'accesso root a un iPhone non è affatto difficile. Tieni presente che il segreto è lo stesso in tutte le istanze dell'app, quindi un utente malintenzionato dovrebbe ottenere l'accesso a un solo binario. E anche se non riuscissero a ottenere l'accesso root sul dispositivo, potrebbero mettere le mani sul binario in un altro e estrarre il token segreto da esso.
Felixyz,

1
solo per aggiungerlo è molto facile anche il root dei telefoni Android
kgutteridge il
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.