Spoofing di richieste POST / GET in un servizio RESTful

13

Ho iniziato a lavorare su un'app che si collega a un servizio RESTful per l'autenticazione e i dati. POST utente nome utente e password per / endpoint token. Una volta effettuato il login, ottengono un token al portatore che poi aggiungono all'intestazione Authorization nelle chiamate successive a diverse risorse protette.

La mia domanda è ciò che impedisce agli utenti di intercettare il loro post normale dall'app (ottenere il token) e quindi inviare un sacco di richieste POST (usando qualcosa come postman o fiddler) per creare un gran numero di post o articoli falsi o qualsiasi altra cosa altrimenti l'app fa.

Quali sono alcuni modi possibili per proteggere da questo? Il fatto che il traffico verso il servizio finirà per passare a TLS rende questo un non-problema?

    
posta ska-dev 13.11.2017 - 16:40
fonte

10 risposte

30

My question is what prevents users from intercepting their regular post form the app (getting the token) and then possibly sending bunch of POST requests (using something like postman or fiddler) to create a large number of fake posts or articles or whatever else the app does.

Niente

Does the fact that the traffic to the service will eventually go via TLS make this a non-issue?

Questo non fa alcuna differenza.

What are some possible ways from protecting from this?

Il più comune è il rate limit. Cioè se qualcuno posta a un livello molto più alto del previsto rifiuta il post. Ci sono diversi approcci a questo: quando hanno postato l'ultimo, media mobile su N minuti ecc. Se non vuoi falsi positivi che portano gli utenti a perdere il contenuto dei post, allora falli riautenticare per continuare.

Un altro approccio è captcha. Sto cercando di dimostrare all'utente che sono umani.

Un altro sta tentando di rilevare il contenuto generato automaticamente utilizzando filtri antispam o AI.

    
risposta data 13.11.2017 - 16:56
fonte
12

My question is what prevents users from intercepting their regular post form the app

Niente.

Does the fact that the traffic to the service will eventually go via TLS make this a non-issue?

Se lo realizzi per una piattaforma mobile (Android / iOS), ciò lo rende molto più difficile (ma non impossibile).

Se lo fai per il browser, questo non aggiunge molta protezione.

What are some possible ways from protecting from this?

È difficile proteggersi dalle richieste automatiche, ma una cosa che puoi fare è limitare i tassi.

    
risposta data 13.11.2017 - 16:54
fonte
6

My question is what prevents users from intercepting their regular post from the app (getting the token) and then possibly sending bunch of POST requests (using something like postman or fiddler) to create a large number of fake posts or articles or whatever else the app does.

What are some possible ways from protecting from this?

Non lo fai. Cioè, non ti protegge da questo - dal punto di vista dell'autenticazione e dell'autorizzazione, non ci sono attacchi in corso qui, solo traffico perfettamente legittimo.

Il problema è invece "Come impedire agli utenti di inviare spam al mio servizio?" (o simile), e questo è completamente ortogonale alla domanda di token di autenticazione . Allo stesso modo, un utente può spammare le cose manualmente attraverso l'app.

Limitazione della velocità per account utente, limitazione della velocità per indirizzo IP, utilizzo di cookie o identificativi dispositivo per legare più account insieme per valutare limite per dispositivo, termini di blacklist, euristica per spam, ecc. sono tutti metodi comuni per gestire lo spam. Ma qualunque sia la tua cosa reale che stai cercando di prevenire, è quello che dovresti esaminare, non impedendo agli utenti di modificare le cose lato client (che saranno sempre in grado di fare).

    
risposta data 14.11.2017 - 22:33
fonte
4

Il token che fornisci al client deve contenere una scadenza firmata che verrebbe verificata sul lato server (ad esempio, limitata a una tipica sessione utente che ti aspetteresti per la tua app). Ciò non impedirà la re-posting, ma limiterà il periodo entro il quale potrebbe essere fatto dopo l'autenticazione. Alla scadenza, l'utente dovrà eseguire nuovamente l'autenticazione. Questo è comunemente implementato usando Token Web JSON .

Tuttavia, stai parlando di un uso scorretto da parte di un utente legittimo (a meno che un utente malintenzionato non abbia già compromesso il dispositivo dell'utente legittimo e possa intercettare il traffico in chiaro): tale uso errato è molto difficile da prevenire senza rendere l'app quasi inutilizzabile come altri hanno notato (ad esempio, facendo in modo che gli utenti si autenticassero su ogni richiesta). Memorizzando le credenziali sul dispositivo e re-inviandoli silenziosamente è un GRANDE NO-NO.

    
risposta data 13.11.2017 - 19:41
fonte
2

Correggere che un token di sessione da solo non assicura che un hacker non possa intercettare un pacchetto e riutilizzare il token per i propri scopi ... almeno finché il token è valido. La maggior parte dei token di sessione ha un limite di tempo, sebbene dipenda dal metodo di autorizzazione utilizzato per convalidare il token sul server.

Il tempismo è un modo per proteggersi da questo, anche se non è infallibile. Dal momento che stai scrivendo l'app, dovresti avere una ragionevole idea di quanto velocemente l'app può essere gestita e un tasso previsto di chiamate di servizio. Se la tua app, in genere, non può inviare una chiamata di servizio più di una volta al secondo e il servizio riceve 100 richieste in un secondo, è chiaramente un hacker al lavoro.

Tuttavia, questo presuppone che un hacker bombarderà il tuo servizio con le richieste. Un hacker potrebbe capirlo dopo alcuni fallimenti, e abbassare il loro tasso di richieste. Non appena vedono il servizio rifiutare quello che credono essere un token di sessione valido, inizieranno a guardare l'ovvio, come il tempismo.

Un altro modo per evitare questo è richiedere SSL per accedere al servizio. Ciò renderà difficile estrarre i pacchetti e il token di autorizzazione. Avranno bisogno di molto più di uno sniffer di pacchetti. Un hacker particolarmente esperto potrebbe provare a sondare nel binario dell'app, ma questo è un sacco di lavoro, specialmente sulle piattaforme mobili. Dovresti acquistare un certificato SSL per il server, ma questa è un'assicurazione economica.

Un metodo che ho sperimentato è quello di aggiungere un numero di sequenza al token di sessione, con hash, in modo che non assomigli a un numero di sequenza. Il servizio di autorizzazione mantiene un conteggio che viene incrementato ogni volta che un token viene convalidato. Rimuove i byte di sequenza prima di convalidare il token e quindi controlla il numero di sequenza.

Si prevede che il client inizi a zero quando inizialmente riceve il token di sessione e incrementa il conteggio di uno ogni volta che viene effettuata una chiamata. Quindi, quando il server ha ricevuto per l'ultima volta la sequenza 250, e un altro arriva in quella sequenza 135 ... ignora la richiesta, forse blocca l'IP sorgente e invia agli amministratori un avviso che potrebbe essere in corso un tentativo di hacking.

Tuttavia, ciò aggiunge un po 'di complessità all'app client, e potrebbe anche eseguire un controllo dei pacchetti rilasciati o dei pacchetti di ritorno abbandonati. Solo qualcosa con cui ho sperimentato.

E, sì, un hacker potrebbe essere in grado di capirlo, ma solo dopo un sacco di false partenze ... dando agli amministratori un avvertimento che è in corso un tentativo di intrusione.

    
risposta data 14.11.2017 - 06:59
fonte
1

Un sacco di altre persone hanno detto "nulla" in risposta alla prima domanda su "cosa impedisce .." ed è vero; alla fine niente sconfigge davvero qualcuno assolutamente determinato.

Hai anche chiesto strategie che possano contrastarlo; tj1000 ci ha toccato e ho pensato di gettare una simile idea nella mischia, basata sul lavoro che facevo con i terminali delle carte di credito.

Quando ero un junior dev, mi è stato consegnato un incarico che è stato giudicato troppo difficile per essere valso la pena di essere risolto dai professionisti (immagino che sia un po 'come mostrare quanto sono stato pagato); avevamo migliaia di terminali di carte di credito che facevano scalo su un vecchio link pre-isdn, facevano un po 'di autenticazione, registravano una transazione, ottenevano approvazioni o declino dal server e sulla transazione successiva. La parte carina è che non è mai stato seguito un altro messaggio dal terminale se la transazione è stata annullata dopo che l'avremmo approvata (questo era nei giorni delle firme, prima che l'identità dell'utente fosse pre-autorizzata da un chip e un pin), ma non 't bisogno di essere

Queste transazioni sono state protette e confermate da quello che è stato definito un codice di autenticazione del messaggio MAC. Costruito nell'hardware del terminale era una chiave hash, univoca per terminale, dal produttore. Il produttore avrebbe condiviso con noi la chiave di hashing, e quando il terminale è apparso presentando il suo ID unqiue potremmo cercare la chiave hash. Il byte del messaggio formato dal terminale sarebbe stato cancellato dal terminale, con la metà dell'hash precedente o iniziale che veniva aggiunto al messaggio. L'altra metà verrebbe utilizzata per aggiornare la chiave hash utilizzata per il messaggio successivo. Dal lato server, eseguivamo lo stesso hashing per sapere se il messaggio era stato manomesso e arrivavano allo stesso risultato di hash, sapevamo anche di inserire la chiave hash con lo stesso mezzo residuo che avevamo, ma terremo traccia anche della hashkey precedente. La prossima volta che è arrivato un messaggio, una delle due cose era il caso. Se la transazione precedente era riuscita e doveva essere accumulata nei totali giornalieri, il terminale usava la sua nuova chiave cancellata per hash l'ultimo messaggio. Se la transazione precedente è stata ripristinata (utente annullato, firma errata ecc.) Il terminale avrebbe riutilizzato la chiave hash precedente. Cancellando il messaggio con l'ultima chiave inserita e non trovando corrispondenze, ma eseguendo l'hashing con la chiave precedente e trovando una corrispondenza, sapevamo che il destino della transazione precedente era fallito e lo elimineremmo dai totali giornalieri.

Le chiavi hash di tanto in tanto andavano fuori sincrono; quando ciò è accaduto, nessuna delle nostre chiavi memorizzate produrrebbe un hash di corrispondenza per il messaggio. C'è un'altra chiave da provare: la chiave iniziale (gli utenti del supervisore potrebbero reimpostare la chiave all'inizio, e alcuni utenti sembravano farlo su qualsiasi problema, credendo che si trattasse di qualcosa come un riavvio: raramente il caso causava più problemi di risolto ma ..). Se la chiave iniziale ha funzionato, non potremmo dire con certezza cosa è successo alla transazione precedente, ma di solito li abbiamo accumulati (conti delle persone pagate) sulla base della teoria che la gente si lamenterebbe se non fossero stati rimborsati quando dovuti ma non se sono stati rimborsati qualcosa che avevano comprato ..

Se la chiave iniziale non ha funzionato, il terminale è diventato effettivamente inutile, poiché la perdita di sincronizzazione a rotazione significa che non possono funzionare più messaggi. Non avevamo l'autorità di dire al terminale di resettare la sua stessa chiave, ma potremmo inserire un messaggio sul display implorando l'utente di farlo

Per farla breve, non è necessario utilizzare lo stesso token, se si è preoccupati che i token vengano catturati e riprodotti come alternativa memorizzata per le password. Altri hanno indicato opzioni di fare scadere i token dopo un certo tempo; questo metodo è essenzialmente un token in scadenza dopo ogni richiesta (simile a un'altra menzione sull'aggiunta di un numero sequenziale a un token), con un modo interno noto di calcolare un nuovo token su ciascun lato che deve essere eseguito nel passaggio.

Se sei interessato ai dettagli noiosi del modo in cui il mondo della carta di credito lo fa nel Regno Unito, consulta APACS 70 Standard Book 2 e Book 5. Questi non sono disponibili gratuitamente, purtroppo - devi essere un membro per ricevere una copia di nuove pubblicazioni, ma potresti trovare il contenuto di vecchie versioni di esse che girano attorno al Web

    
risposta data 14.11.2017 - 11:53
fonte
1

Quindi ... non c'è niente che puoi fare per proteggere il computer client per mantenere sicuro il token, ma ci sono alcune best practice per la sicurezza JWT:

  1. Implementa i token di aggiornamento e genera token di accesso di breve durata: questo aggiunge complessità a qualsiasi attacco + il modo in cui ho visto il token di aggiornamento implementato è con una tabella SQL ... che puoi gestire (ad esempio l'avvio istantaneo) .

  2. Elimina il token dal client al logout (questo è ovvio).

  3. Puoi crittografare il token, ma la crittografia è reversibile, rende ancora più difficile.

  4. Utilizza una chiave segreta per firmare i tuoi token e ruotala secondo necessità (ad esempio per versione). La modifica della chiave segreta invalida tutti i token precedenti.

Inoltre, leggi: link

Se avete bisogno di una maggiore sicurezza, avete bisogno di più meccanismi per garantire il cliente specifico: whitelist gli IP degli utenti, garantendo gli utenti hanno AV e la formazione anti-phishing, ecc ...

    
risposta data 15.11.2017 - 00:39
fonte
1

TL; DR un utente esperto soddisfatto di una ragionevole percentuale di spam continuerà a passare - se non con altri mezzi, inserendo il loro spam a mano .

Fai in modo che l'app autentichi ogni richiesta in modo indipendente. Non è assolutamente infallibile, ma aumenta il traffico, ma è fattibile.

Un modo: un messaggio non è più un singolo post ma un GET seguito dal POST. Il GET fornisce un nonce (potrebbe essere il timestamp corrente), e il POST deve fornire il nonce insieme ad es. MD5 del nonce, salato con un'app segreta. Ovviamente è necessario memorizzare i punti non emessi per evitare attacchi di riproduzione.

Puoi anche fornire una sessione nonce al login e utilizzarla per l'intera sessione (ovviamente l'utente può intercettarla e copiarla in una seconda app di spam, una volta che ha interrotto l'app segreta fuori dall'app). Tuttavia, questo non è un miglioramento significativo dal cookie di autenticazione.

Oppure puoi aggiungere in silenzio una convalida a tutte le richieste di app, nella forma del timestamp attuale più l'hash di detto timestamp salato con l'app secret. L'unicità può quindi essere garantita impedendo due post nello stesso secondo lato client.

Il server verifica quindi che il timestamp non sia troppo lontano da adesso () e che l'hash sia abbinato. Puoi anche omettere il timestamp se è accettabile per il bruteforce del server (per timestamp = now () - 60 to now () + 60; se hash (secret + timestamp) ...).

Ora, l'utente deve hackerare il segreto della tua app, che è più difficile di un semplice intercettamento del traffico di rete. Se le stringhe / i dati sono facilmente riconoscibili nell'app, puoi aggiungere una piccola sicurezza attraverso l'oscurità inviando il timestamp e l'hash del segreto più il timestamp di sette secondi prima 1 . Ciò richiede all'utente di decodificare completamente l'app.

(1) Una volta ho rotto uno schema di salatura testando tutte le sequenze da 1 a 32 byte in un programma, apposte e suffissate al timestamp in esadecimale, binario e decimale, con un set di separatori incluso il no- separatore e verificare se il risultato fosse la risposta alla sfida. Questo mi ha permesso di non di eseguire il debug del file binario, cosa che non avrei potuto fare, e sono stati necessari venti minuti per l'impostazione e due per l'esecuzione. Se il timestamp fosse stato offuscato aggiungendo una costante conosciuta, non ci sarei riuscito. Se la costante fosse grande, non sarebbe pratico nemmeno conoscerne il trucco.

    
risposta data 15.11.2017 - 09:08
fonte
1

Come altri hanno toccato, non c'è praticamente nulla che tu possa fare una volta che il codice è in esecuzione sul dispositivo di un utente. Se è in esecuzione nel browser, la progettazione inversa del processo token è banale. Se è in esecuzione in un'app, puoi renderlo molto più difficile da decodificare, ma è ancora possibile.

Per le app mobili, l'autore dell'attacco ha due opzioni:

1) Esegui il reverse engineering del protocollo. L'approccio più semplice è quello di sniffare il traffico di rete. Ci sono delle confusioni che puoi mettere in atto per renderlo più difficile (cert pinning, MAC + chiave segreta + rotazione) ma qualsiasi attaccante determinato alla fine le romperà. Tuttavia, se si utilizza il pin cert e / o l'approccio con la chiave segreta, l'autore dell'attacco non sarà in grado di annusare semplicemente i pacchetti per decodificare il protocollo. Dovrà decompilare il file binario per disabilitare il pin cert e / o localizzare la chiave segreta in memoria.

2) Tratta l'applicazione come una blackbox e automatizza l'interazione con essa. Questa operazione potrebbe essere eseguita con una farm di dispositivi fisici (molto più facile se iOS jailbroken / Android con root) o con una farm di emulatori. Dal punto di vista di un utente malintenzionato, questo potrebbe essere un approccio più affidabile in quanto sarebbe resistente agli eventuali aggiornamenti da te richiesti.

Per proteggersi dal numero 1 (decompilazione binaria) ci sono molte opzioni, ma tutte si riducono ad aumentare la difficoltà del reverse engineering, evitandolo del tutto. Il frutto a bassa sospensione è l'offuscamento binario e il rilevamento del debugger. Per l'offuscamento, puoi offuscare le tabelle dei simboli e / o nascondere la logica di crittografia in funzioni banali (o scriverle direttamente in assembly). Per il rilevamento del debugger, esistono diverse tecniche per determinare se un debugger è in esecuzione; se ne prendi una, puoi bloccare l'app o giocare con l'aggressore.

La protezione dal numero 2 (emulatore / dispositivo farm) è un po 'più difficile, ma, di nuovo, è possibile rendere più difficile il lavoro dell'attaccante. Un'opzione è quella di verificare se il dispositivo è jailbroken (questo sarebbe anche difendere contro # 1) e crash l'app se lo è. Un'altra opzione, almeno per Android, è il servizio di attestazione di Google. Questo dovrebbe impedire lo scenario della farm emulator, ma non una farm fisica. Per iOS, Apple ha rilasciato una simile API deviceCheck in iOS11, anche se ha un ambito molto più limitato.

Se vuoi esempi di questo in the wild, controlla Snapchat.app, che ha implementato molte di queste funzionalità.

    
risposta data 15.11.2017 - 14:16
fonte
0

Se un'app è progettata per autenticare (nome utente / password) una volta e poi utilizzare un sistema di token per l'autorizzazione dei servizi REST, quell'app ha effettivamente creato il proprio accesso backdoor.

Sono sicuro che questa soluzione mi farà frustare, ma fondamentalmente devi autenticarti in ogni singolo endpoint RESTful.

Puoi scegliere di infastidire i tuoi utenti e chiedere una password per ogni singola richiesta REST, ma questo potrebbe rendere la tua applicazione incline a diventare un fallimento.

L'altra opzione è quella di memorizzare le credenziali dell'utente nella memoria dell'app al momento del log-in e inviare le credenziali in silenzio agli endpoint REST.

    
risposta data 13.11.2017 - 18:44
fonte

Leggi altre domande sui tag