Aggiunge casuale a un token prima di crittarlo, rendendolo più sicuro?

5

Scenario:

  • La pagina delle richieste degli utenti sul mio sito
  • Il server genera token utilizzando vari valori, lo crittografa (tramite un algoritmo standard del settore, nulla di homegrown) utilizzando una chiave che solo il server conosce e lo restituisce come parte dei dati della pagina
  • Il token è incorporato nel link alla pagina
  • Quando il client fa clic su quel collegamento, il token viene inviato al server, decrittografato e analizzato e i valori utilizzati per determinare cosa fare

Questo perché abbiamo bisogno di alcune informazioni da inviare dal client al server, ma non vogliamo perdere quei bit di informazioni sul client perché rivelerebbero dettagli dei meccanismi interni del server.

Il problema qui è che, ogni volta che un particolare utente visualizza una determinata pagina, per loro verrà generato lo stesso token. Oltre a consentire la ripetizione all'infinito della stessa richiesta per l'endpoint, questo rende più probabile che qualcuno possa rompere la crittografia del token (sì, lo so che non è probabile, ma è possibile).

Per rendere la crittografia ancora più resiliente, la mia intenzione è quella di inserire un valore casuale di alta qualità, ad esempio un GUID, nel token prima che venga crittografato. Il risultato finale sarà introdurre più entropia nel processo di crittografia, il che significa che per un dato insieme di valori identici di cui ci preoccupiamo (vale a dire tutto tranne il valore casuale), il token generato sarà quasi certamente diverso. Questo valore casuale verrà sempre inserito nello stesso posto e sarà sempre della stessa lunghezza, quindi la rimozione e il lancio dopo la decifrazione del token è banale. In effetti, si tratta di un aumento della crittografia con offuscamento.

Sembra a mio occhio inesperto che questa è una soluzione relativamente semplice e sicura al mio problema, ma lo è, o sto semplicemente sprecando il mio tempo e / o rendendo le cose meno sicure e più complicate?

    
posta Ian Kemp 30.08.2018 - 16:23
fonte

4 risposte

15

Non è necessario aggiungere casualità a un token crittografato. Se è correttamente crittografato, l'utente non ha modo di dedurre nulla sui dati crittografati.

The issue here is that, every time a particular user views a particular page, the same token will be generated for them.

Questo sembra strano. La tua crittografia non sembra utilizzare uno standard sicuro. In caso contrario, ogni volta che si crittografa lo stesso token, il testo cifrato cambia. Devi usare un IV e non pensare mai ad AES-ECB, quella modalità è rotta e non dovrebbe essere usata nemmeno per insegnare ai bambini come funziona AES.

Se utilizzi gli standard del settore, conoscerai il Vettore di inizializzazione (IV). In termini approssimativi, l'IV è un valore aggiunto al processo che modifica il testo cifrato, quindi anche se si cifrano due plaintext identici con la stessa chiave, il testo cifrato corrispondente cambierà.

L'IV è il dato casuale che stai pensando di aggiungere. È già lì.

    
risposta data 30.08.2018 - 16:43
fonte
4

Proviamo a suddividere questo:

Problema: riproduzione di un token :

Apart from allowing the same request to be replayed against the endpoint ad infinitum

Solitamente i token di autenticazione risolvono questo problema espirando i token: i dati crittografati includono un datestamp (che ha l'effetto collaterale di rendere ogni token univoco) e il server rifiuterà qualsiasi token più vecchio di, diciamo 15 minuti.

Problema: interruzione della crittografia :

this makes it more likely that someone will be able to break the token encryption

Non sono un esperto, ma mi sembra che dovresti usare un IV casuale per ogni crittografia e includere l'IV con il testo cifrato come parte del token. Questo risolverebbe entrambi il problema di crittanalisi a cui stai alludendo, e avrà l'effetto collaterale di rendere le tue pedine uniche. (Se non stai usando IVs casuali, probabilmente avrai problemi molto più grandi nelle tue mani)

Perché non utilizzare una libreria standard per fare questo piuttosto che uscire dal profondo per progettare il proprio schema di crittografia? Vorrei raccomandare JWT .

Infine, come servizio pubblico ho bisogno di correggere questo: i GUID NON SONO LA RIGOROSITÀ DI ALTA QUALITÀ

Vedi Wikipedia / Universally_unique_identifier .

UUID / GUID sono progettati per essere unici , non tentano di essere imprevedibili . Esistono 5 modi standard per derivare un UUID; 4 di questi sono una combinazione di indirizzo MAC + nome host + timestamp. Gli UUID versione 4 sono puramente casuali, ma poiché la generazione di UUID / GUID deve essere veloce e non bloccante, usano generatori di numeri casuali non crittografici.

NON UTILIZZARE UUID / GUID COME FONTE DI RANDOMNESSIONE CRITTOGRAFICA . Usa invece /dev/random in unix, SecureRandom in java, o qualunque sia l'equivalente nel tuo OS / linguaggio di programmazione

    
risposta data 30.08.2018 - 16:48
fonte
1

La soluzione che viene utilizzata sulla mia piattaforma preferita è "encrypt / decrypt with managed IV (Initialization Vector)". Ciò significa che, al momento della crittografia, l'intero testo in chiaro viene crittografato con un IV crittografico sicuro, quindi l'IV viene inserito in formato base64 prima dell'inizio del testo cifrato. Dopo la decodifica, la IV viene tirata fuori dalla parte anteriore e utilizzata come IV per il testo cifrato. Questo è tutto trasparente per lo sviluppatore. Si noti che è perfettamente sicuro esporre l'IV, poiché la decrittazione con la chiave corretta ma l'IV errato determinerà una condizione di errore. Se il tuo linguaggio di programmazione ha una funzione simile, usalo; avendo generato un IV casuale ogni volta che si cripta qualcosa, non è necessario inserire dati extra nel testo normale.

    
risposta data 30.08.2018 - 20:01
fonte
0

Per me, questo sembra un XY Problem .

Il modo migliore per proteggere un segreto è non dire a nessuno il segreto. Il token è generato lato server. Il server conosce già i dati. E poi riproduci il token sul server, che contiene solo i dati che il server ha già . Questo è completamente inutile.

Altre risposte hanno indicato la soluzione rapida e immediata per il tuo problema di crittografia utilizzando la crittografia con IV. Ma la soluzione migliore sarebbe quella di rendere questo superfluo.

Server builds up token using various values, encrypts it (via an industry-standard algorithm, nothing homegrown) using a key only the server knows, and returns it as part of the page data

Invece di crittografare quei valori, salvali in un database. Puoi potenzialmente, se proprio devi, criptare ancora quei valori e poi salvarli. Ma non è assolutamente necessario che questi valori lascino il server, anche in forma crittografata. Quindi generare un token veramente casuale (con un CSPRNG) e utilizzarlo come chiave di ricerca. Invia questo token al client.

Token is embedded into link on page

Usa il token casuale appena generato per quello.

When client clicks that link, token is sent to server, decrypted and parsed and the values used to determine what to do

Invece di decrittografare e analizzare i valori, usi il token per cercarli nel database. Fatto. Se hai archiviato solo i dati crittografati, devi comunque decrittografarli, naturalmente.

Questo funziona anche se hai più server. Se il token viene generato sul server A e inviato al server B, fare in modo che il server B utilizzi una connessione protetta al server A e richieda i dati tramite il token dal server A. Anche in questo scenario i dati non vengono mai inviati al client.

This is done because we need certain bits of information to be sent from the client to the server, but we don't want to leak those bits of information to the client because they would reveal details of the server's inner workings

Lo stato interno non dovrebbe mai fuoriuscire da un'implementazione. Questo è già un odore di codice e un buon suggerimento che la tua architettura è difettosa.

    
risposta data 01.09.2018 - 09:53
fonte

Leggi altre domande sui tag