Come salvaguardare un'API REST solo per le applicazioni mobili attendibili

87

Come faccio a essere sicuro che la mia API REST risponda solo alle richieste generate dai client fidati, nel mio caso le mie applicazioni mobili? Voglio evitare richieste indesiderate provenienti da altre fonti. Non voglio che gli utenti riempiano un codice seriale o altro, dovrebbe accadere dietro le quinte, al momento dell'installazione e senza l'intervento dell'utente richiesto.

Per quanto ne so, HTTPS è solo per convalidare il server con cui stai comunicando è chi dice di essere. Ho intenzione di utilizzare HTTPS per crittografare i dati.

C'è un modo per farlo?

Aggiornamento: L'utente può eseguire azioni di sola lettura, che non richiedono l'accesso dell'utente, ma possono anche eseguire azioni di scrittura, che richiedono l'accesso dell'utente (token di autenticazione con accesso). In entrambi i casi voglio che l'API risponda alle richieste provenienti solo da applicazioni mobili attendibili.

L'API verrà utilizzata anche per la registrazione di un nuovo account tramite l'applicazione mobile.

Aggiornamento 2: Sembra che ci siano più risposte a questo, ma sinceramente non so quale contrassegnare come risposta. Alcuni dicono che si può fare, altri dicono che non può.

    
posta Supercell 20.11.2013 - 18:43
fonte

8 risposte

44

Non puoi.

Non puoi mai verificare un'entità, qualsiasi entità , che si tratti di una persona, di un client hardware o di un client software. Puoi solo verificare che ciò che stanno dicendo è corretto, quindi assumere onestà .

Ad esempio, come fa Google a sapere che sto ad accedere al mio account Gmail? Mi chiedono semplicemente un nome utente e una password, verificare che , quindi assumere onestà perché chi altri avrebbe queste informazioni? Ad un certo punto, Google ha deciso che non era abbastanza e ha aggiunto la verifica comportamentale (cercando comportamenti strani), ma che si basa ancora sulla persona per fare il comportamento , quindi sulla convalida del comportamento .

Questa è esattamente la stessa cosa con la convalida del Cliente. Puoi solo convalidare il comportamento del Cliente, ma non il Cliente stesso.

Quindi con SSL, puoi verificare che il Cliente abbia un certificato valido o no, quindi puoi semplicemente installare la tua app, ottenere il certificato, quindi eseguire tutto il nuovo codice.

Quindi la domanda è: perché è così importante? Se questa è una vera preoccupazione, metterei in dubbio la tua scelta di un cliente grasso. Forse dovresti andare con una web app (quindi non devi esporre la tua API).

Vedi anche: Sconfiggi la convalida del certificato SSL per le applicazioni Android

e: Quanto sono sicuri i certificati SSL client in un'app mobile?

    
risposta data 20.11.2013 - 19:53
fonte
28

Sono sicuro che tu ti trovi a tuo agio con gli accessi degli utenti e con le comunicazioni su SSL, quindi mi concentrerò su quella che penso sia la parte più interessante della domanda: come assicurarti che la tua lettura solo azioni - che non richiedono all'utente di essere autenticate - sono accettate solo dalle tue app client?

Prima di ogni altra cosa, c'è il rovescio della medaglia che fNek ha suggerito in una risposta precedente - le tue app client sono nelle mani di utenti potenzialmente ostili. Possono essere esaminati, le loro comunicazioni controllate, il loro codice smontato. Nulla di ciò che suggerirò ti consentirà di garantire che qualcuno non esegue la retroingegnerizzazione del tuo cliente e abusare della tua API REST. Ma dovrebbe mettere una barriera di fronte a qualsiasi tentativo casuale.

Ad ogni modo, un approccio comune è:

  • Il client contiene un segreto
  • Quando si effettua una richiesta, concatena i parametri della richiesta con i segreti e il risultato viene cancellato
  • Questo hash viene inviato con la richiesta e controllato dal server

ad esempio, immagina una richiesta GET per /products/widgets

Diciamo che il segreto del cliente è "OH_HAI_I_IZ_SECRET"

Concatena il verbo HTTP e l'URL e il segreto:

GET/products/widgetsOH_HAI_I_IZ_SECRET

E prendi un hash SHA-1 di questo:

4156023ce06aff06777bef3ecaf6d7fdb6ca4e02

Quindi invialo insieme, quindi la richiesta sarebbe per:

GET /products/widgets?hash=4156023ce06aff06777bef3ecaf6d7fdb6ca4e02

Infine, per impedire a qualcuno di riprodurre almeno le singole richieste, prendere anche una data e ora e aggiungerla ai parametri e all'hash. per esempio. in questo momento, in tempo Unix, è 1384987891. Aggiungilo alla concatenazione:

GET/products/widgetsOH_HAI_I_IZ_SECRET1384987891

Hash that:

2774561d4e9eb37994d6d71e4f396b85af6cacd1

E invia:

GET /products/widgets?time=1384987891&hash=2774561d4e9eb37994d6d71e4f396b85af6cacd1

Il server controllerà l'hash e verificherà che il timestamp sia aggiornato (ad esempio entro 5 minuti per consentire agli orologi di non essere perfettamente sincronizzati)

Avviso! Dal momento che parli di app mobili, c'è il rischio concreto che il telefono di qualcuno abbia l'orologio sbagliato. O fuso orario sbagliato. O qualcosa. Aggiungere il tempo all'hash probabilmente romperà alcuni utenti legittimi, quindi usa questa idea con cautela.

    
risposta data 20.11.2013 - 23:53
fonte
12

Per chiunque sia interessato, su Android puoi verificare che la richiesta ricevuta sia stata inviata dalla tua app.

In breve, quando carichi la tua app su google, la firmi con una chiave univoca che solo tu conosci (e google).

Il processo di verifica diventa (ish) come questo:

  1. la tua app va su google e richiede il token di autenticazione
  2. la tua app invia il token in modo sicuro al tuo back-end
    1. il tuo back-end va su google e controlla il token di autenticazione ricevuto dalla tua app.
    2. il tuo back-end quindi controlla se la chiave univoca della tua app ha firmato corrispondenze, altrimenti vuol dire che non era la tua app ...

il blog completo che lo spiega e come implementarlo può essere trovato qui: link

    
risposta data 12.04.2016 - 11:20
fonte
5

Ok, quindi vale la pena menzionare prima di iniziare che per la maggior parte delle applicazioni questo è estremamente eccessivo. Per la maggior parte dei casi d'uso, avere semplicemente un certificato e / o un token valido è più che sufficiente. Se si tratta di fare qualcosa di difficile come decompilare la tua app, anche la maggior parte degli hacker non si preoccuperà se non fornisci dati molto preziosi. Ma hey, dov'è il divertimento in quella risposta?

Quindi ciò che puoi fare è impostare la crittografia asimmetrica in qualche modo come firma digitale usata per firmare programmi. Ogni app può quindi avere un singolo certificato emesso da una singola CA e verificato quando l'utente si connette. (al momento della prima registrazione o della prima installazione) Quando il certificato viene autenticato, è possibile proteggere ulteriormente l'applicazione registrando tale certificato come valido per un determinato identificatore di dispositivo (come ID Android )

    
risposta data 21.11.2013 - 00:36
fonte
4

Come @Morons menzionato nella sua risposta, è molto difficile verificare l'entità all'altra estremità della connessione.

Il modo più semplice per fornire un certo livello di autenticità è di fare in modo che il server controlli un segreto che solo la vera entità potrebbe conoscere. Per un utente, potrebbe essere un nome utente e una password. Per un software in cui non ci sono utenti potresti incorporare un segreto.

Il problema con questi approcci è che devi avere fiducia nel client. Se qualcuno esegue il reverse engineering della tua app o ruba la tua password, può fingere di essere te stesso.

Puoi prendere delle misure per rendere più difficile l'estrazione delle informazioni segrete offuscandole nell'eseguibile. Strumenti come ProGuard, che è un offuscatore per Java, possono essere d'aiuto in questo, non so molto sull'offuscamento in altre lingue, ma ci sono probabilmente strumenti simili. L'utilizzo di una connessione TLS aiuta a prevenire lo spionaggio del traffico, ma non impedisce un attacco MITM. Appuntare può aiutarti ad affrontare questo problema.

Lavoro per una società chiamata CriticalBlue (Full disclosure!) che ha un prodotto chiamato Approov che cerca di affrontare questo problema di fiducia . Funziona attualmente per Android / iOS e fornisce un meccanismo per i nostri server per verificare l'integrità dell'app client. Lo fa facendo in modo che il cliente calcoli una risposta a una sfida casuale. Il client deve calcolare la risposta utilizzando gli attributi del pacchetto app installato che sono difficili da falsificare e include alcuni sofisticati meccanismi anti-manomissione.

Restituisce un token che puoi quindi inviare come prova di autenticità alla tua API.

L'importante differenza con questo approccio è che sebbene sarebbe possibile disabilitare il controllo di autenticità sul client, se lo facessi non avresti il token di autenticazione devi verificare la tua app con il server. La libreria è anche strettamente legata alle caratteristiche dell'eseguibile in cui si trova, quindi sarebbe molto difficile incorporarla in un'applicazione falsa e farlo funzionare.

Esiste un'analisi costi / benefici che ogni sviluppatore API deve fare per decidere quanto è probabile che qualcuno tenterà di hackerare la propria API e quanto costoso possa essere. Un semplice controllo segreto dell'applicazione impedisce attacchi banali, ma per proteggersi da un aggressore più determinato è probabilmente molto più complicato e potenzialmente costoso.

    
risposta data 25.07.2016 - 18:10
fonte
0

SSL protegge il canale di comunicazione.

Il login riuscito emetterà un token di autenticazione su una connessione criptata.

Il token di autenticazione verrà passato all'API REST in tutte le richieste successive.

    
risposta data 20.11.2013 - 19:09
fonte
0

Non sarebbe troppo sicuro, ma potresti aggiungere una sorta di codice segreto o persino una firma digitale. Lato negativo: Deve essere incluso nell'app, il che rende facile ottenerlo se sai cosa fai.

    
risposta data 20.11.2013 - 19:59
fonte
0

As far as I know, HTTPS is only to validate the server you are communicating with is who it says it is.

In effetti, puoi usare SSL per autenticare sia il client che il server. Oppure, in modo diverso, "sì, puoi usare i certificati client".

Dovrai ...

  • guarda la libreria SSL che stai utilizzando per determinare come specificare i certificati client nel dispositivo mobile,
  • scrivi il codice o configura il tuo server HTTPS in modo che accetti solo le connessioni da client registrati e fidati.
  • crea un meccanismo per aggiungere certificati client affidabili al tuo server
  • viene fornito un meccanismo per rimuovere i certificati client non più attendibili dal server

Puoi fare in modo che l'applicazione mobile memorizzi il certificato ovunque tu voglia. Dal momento che desideri un'autenticazione specifica per l'applicazione, dovresti considerare di archiviare il certificato in una posizione del disco protetta (su Android, potresti creare una tabella "config" nel tuo database SQLite e una riga per il tuo certificato e un'altra per la tua chiave privata) .

    
risposta data 20.11.2013 - 21:15
fonte

Leggi altre domande sui tag