Come proteggere l'autenticazione JWT REST dall'accettare le chiamate dal browser?

2

Ho creato un semplice sistema client-server REST usando token JWT.

Sulla mia app mobile, puoi scambiare il tuo token di accesso Facebook / Google per un JWT con il server e quindi effettuare chiamate con esso, ad es. Recupera i tuoi amici / dati nell'app.

Ora, voglio limitare questo in modo che il server accetti solo le risposte pubblicate tramite l'app Android, non il classico browser web.

Questo scenario può accadere, quando per esempio l'utente pubblica la sua richiesta POST attraverso un'app come postino per Chrome.

Come gestisci questo genere di cose?

    
posta Spectre 24.01.2017 - 12:34
fonte

3 risposte

3

Sembra che quello che stai cercando di fare è identificare il software utilizzato per accedere alla tua API. Il modo in cui guardo questo, è indipendente dall'autenticazione dell'utente. L'autenticazione utente ti dice che chi sta utilizzando la tua API, sei interessato a che viene utilizzato per accedere alla tua API.

Il problema fondamentale che affronti è che non puoi fidarti al 100% del codice che è in esecuzione sul client. Non hai alcun controllo su di esso e un utente malintenzionato può modificarlo o eseguirne il reverse engineering o come hai suggerito di utilizzare qualcosa come Postman per inviare richieste sintetiche.

Hai un certo numero di opzioni su come procedere:

Rimuovi il problema

Può darsi che tu possa ri-progettare l'app e il server in modo che non ti interessi più a cosa viene utilizzato per accedere alla tua API. È difficile fidarsi del codice che non controlli, quindi se possibile è opportuno spostare la maggior parte delle funzionalità sul server.

Stringa utente-agente

Un metodo di base per tentare di identificare l'origine di una richiesta consiste nell'esaminare la stringa user-agent inclusa nelle intestazioni delle richieste che arrivano alla tua API. Puoi filtrare le richieste provenienti da cose che non sono app Android. Il problema è che è solo un'intestazione ed è davvero facile da falsificare. Quindi non fa molto in pratica.

Chiave API (e segreto)

Un'altra cosa che potresti fare sarebbe usare una chiave API. Questo è un identificatore che usi per far sapere al tuo server che il client che lo accede è autentico. Per evitare che venga rubato osservando semplicemente la connessione con un proxy, è necessario utilizzare TLS che crittografa la connessione tra il client e il server in modo che terze parti non possano facilmente origliare. Puoi comunque essere vulnerabile a un attacco man-in-the-middle (guarda bloccare se questo è un preoccupazione).

Puoi migliorare questo schema combinando o sostituendo la tua chiave con un segreto che memorizzi nell'app e non trasmetti mai. Invece si firma il traffico che si invia all'API utilizzando un HMAC. Se qualcuno altera il messaggio che invii, la firma non corrisponderà e puoi respingere la richiesta. Poiché la tua app è l'unica cosa con il segreto, un'altra app non sarà in grado di accedere alla tua API.

Questo è vero fino a quando il tuo segreto rimane nascosto, ma se hai rilasciato la tua app in the wild, qualcuno malintenzionato può ancora potenzialmente accedere all'app e provare a guardarci dentro per recuperare il segreto. Quanto è difficile dipende da quanto difficile lo nascondi. Puoi nascondere il tuo segreto o incorporarlo nel codice nativo, ma un individuo sufficientemente motivato sarà probabilmente in grado di trovarlo dato abbastanza tempo.

In conclusione

Nessuna delle opzioni per identificare l'origine di una chiamata API è perfetta, le persone ti diranno giustamente che possono essere tutte infrante. La decisione che devi prendere è quanto è importante qualsiasi cosa tu abbia dietro la tua API e quanto vuoi proteggerla. Solo tu puoi rispondere a quello.

Lavoro in un posto che fa questo genere di cose e uno dei miei colleghi ha appena iniziato a scrivere una serie di articoli che forniscono maggiori dettagli su sicurezza dell'API mobile . Se vuoi maggiori dettagli potrebbe essere di interesse.

    
risposta data 25.01.2017 - 23:23
fonte
1

Ci sono alcuni modi in cui puoi ottenerlo. Spero che il tuo obiettivo sia accettare richieste solo da clienti conosciuti?

Chiave precondivisa

Un PSK nella sua forma più semplice è una chiave scambiata tra due parti fuori banda con il mittente che usa la chiave condivisa come è nei messaggi come credenziale. Per questo motivo, HTTPS è generalmente un must per i PSK. Senza aiuto dalla sicurezza del trasporto, è più facile per un utente malintenzionato ottenere il PSK e utilizzarlo in una richiesta malevola, proprio come una richiesta legittima.

Time Stamp per impedire attacchi di riproduzione

Supponiamo di progettare il nostro meccanismo di sicurezza per trasmettere le credenziali non in testo semplice ma crittografate usando il PSK. La credenziale crittografata viene inviata nel messaggio, in genere nell'intestazione della richiesta HTTP. Un utente malintenzionato non può decodificare l'intestazione e estrarre le credenziali, ma può riprodurre la richiesta precedente così com'è. Peggio ancora, un utente malintenzionato può incorniciare un nuovo richiedi e utilizza solo il valore dell'intestazione contenente le credenziali valide della precedente richiesta riuscita.

Un timestamp può essere aggiunto al messaggio e crittografato insieme al resto del contenuto del messaggio. Il servizio può recuperare il timestamp dopo la decrittografia del messaggio e fallire la richiesta se il timestamp è troppo vecchio per la soglia questo è già stato concordato. Questo riduce la finestra di opportunità per riprodurre una richiesta.

Il lato negativo è che sia il server che il client devono sincronizzarsi con il tempo.

Un'alternativa a un timestamp è un contatore come il contatore nonce che abbiamo visto con l'autenticazione digest. Con un contatore, non abbiamo bisogno di essere preoccupati per l'inclinazione tra gli orologi. Tuttavia, i clienti devono implementare a contatore per garantire che il conteggio inviato in una richiesta sia maggiore del conteggio nella richiesta precedente almeno di uno e il numero il server deve conservare una registrazione dell'ultimo contatore ricevuto. Naturalmente, il messaggio deve essere firmato in modo che un utente malintenzionato non incrementa il contatore e riproduce il resto della richiesta.

Impedisci l'uso improprio dell'identificatore

Nella sua forma più semplice, un PSK è sia l'identificativo dell'utente che le credenziali. Per questo motivo, le PSK devono essere uniche. Dato a chiave, un'applicazione deve essere in grado di identificare l'utente corrispondente senza alcuna ambiguità. La premessa di base che noi stanno lavorando è l'evitare di HTTPS. Per questo motivo, la PSK non può essere trasmessa così com'è. Abbiamo bisogno di avere due chiavi: una che agisce come identità dell'utente e l'altra che funge da credenziale.

Tuttavia, queste chiavi non sono collegate matematicamente. Inoltre, viene utilizzata la stessa chiave utilizzata per firmare sul lato del mittente convalidare la firma sulla fine del destinatario; quindi, questa è solo una chiave condivisa simmetrica. Ma simile alla chiave pubblica crittografia, solo la chiave privata deve essere protetta.

Impedisci attacchi MIM (per comunicazioni non HTTPS)

Senza HTTPS, un attacco man-in-the-middle (MITM) è una delle minacce più significative. Il meccanismo principale per garantire l'integrità dei dati dei messaggi è un codice di autenticazione dei messaggi basato su hash (HMAC). HMAC è solo un pezzo di dati creati tramite un algoritmo di hashing crittografico e una chiave segreta condivisa. In questa sezione, ti mostro come per creare un HMAC usando l'algoritmo SHA256. Tuttavia, se il messaggio deve essere crittografato per riservatezza, è possibile aggiungere facilmente tale funzionalità utilizzando la stessa chiave privata che utilizziamo per HMAC o puoi introdurre una nuova chiave specifica per la crittografia.

La richiesta dovrebbe contenere i seguenti parametri

  • La chiave pubblica, che è la chiave associata all'utente.
  • Il contatore
  • Il timestamp

Oltre ai parametri, la richiesta include una firma che garantisce che nessuno dei parametri sia manomesso È possibile creare la firma basata non solo sui tre parametri ma anche sull'intero corpo della richiesta se l'obiettivo è assicurarsi che nulla nella richiesta venga modificato.

Per assicurarci che nessuno manchi i parametri, possiamo includere un HMAC-SHA256 di tutti e tre i valori più il richiede il metodo URI e HTTP. Il Listato 9-1 mostra una richiesta HTTP protetta dal meccanismo PSK. La figura 9-2 mostra il design PSK.

    
risposta data 26.01.2017 - 13:15
fonte
0

Se hai bisogno di identificare in modo affidabile l'applicazione client (non l'utente, né il dispositivo), allora stai entrando in alcune delle tecniche utilizzate da DRM (Digital Rights Management). Nessuno di loro è robusto ed è generalmente attraverso l'oscurità. Quindi sono d'accordo, se riesci a rearchitect a non preoccuparti di quale applicazione ti sta chiamando, sarai in una posizione migliore.

    
risposta data 26.01.2017 - 00:03
fonte

Leggi altre domande sui tag