Devo utilizzare un generatore di numeri casuali crittograficamente sicuro quando genero gli ID?

7

È comune generare identificatori casuali da esporre tramite un'API invece di utilizzare una semplice chiave primaria con incremento automatico. Le ragioni sono molte:

  • Impedisce una facile enumerazione.
  • Non distribuire oggetti dell'ordine sono stati creati.
  • Non fornisce il numero totale di oggetti o tassi di crescita.

Quando si generano questi ID, ci sono dei vantaggi sostanziali nell'usare un generatore di numeri pseudocasuali crittograficamente sicuro (come in crypto.randomBytes() in Node.js) usando qualcosa di più semplice (come in Math.random() )?

    
posta Anders 13.04.2016 - 14:45
fonte

6 risposte

4

Math.random() viene solitamente seminato dall'ora corrente del giorno. Pertanto esiste la possibilità che si verifichino collisioni per oggetti generati ogni giorno alla stessa ora.

Dal punto di vista della sicurezza, ciò significa che questi valori "casuali" saranno prevedibili da un utente malintenzionato.

Anche se seminato con qualcos'altro, un generatore di numeri pseudo casuali non crittograficamente sicuro può rivelare il suo stato nel caso in cui vengano acquisiti abbastanza valori. Questo è il motivo per cui è meglio da un punto di vista della sicurezza utilizzare solo i valori generati da un generatore di numeri pseudo casuali crittograficamente sicuro (ad esempio crypto.randomBytes() a cui si fa riferimento).

CSPRNG hanno alcune proprietà che li rendono adatti per l'uso in sicurezza:

  • Every CSPRNG should satisfy the next-bit test. That is, given the first k bits of a random sequence, there is no polynomial-time algorithm that can predict the (k+1)th bit with probability of success better than 50%. Andrew Yao proved in 1982 that a generator passing the next-bit test will pass all other polynomial-time statistical tests for randomness.
  • Every CSPRNG should withstand "state compromise extensions". In the event that part or all of its state has been revealed (or guessed correctly), it should be impossible to reconstruct the stream of random numbers prior to the revelation. Additionally, if there is an entropy input while running, it should be infeasible to use knowledge of the input's state to predict future conditions of the CSPRNG state.

L'utilizzo di un tale generatore soddisferà i tuoi requisiti di sicurezza:

  • Impedisce una facile enumerazione.
  • Non sono stati dati gli oggetti dell'ordine creato.
  • Non fornisce il numero totale di oggetti o tassi di crescita.

Tuttavia, non si dovrebbe lasciare il fatto che questi sono ora imprevedibili dal proteggere il primo caso con controlli di accesso adeguati (autenticazione e autorizzazione). Gli URL non dovrebbero essere considerati segreti e ci sono molti modi in cui possono perdere (navigazione a spalla con telecamera nascosta, perdita di intestazioni di referrer HTTP, registri di proxy e browser). Inoltre, una volta che l'URL è noto e si sta facendo affidamento su un segreto imprevedibile per proteggerlo, l'utente che accederà avrà sempre accesso e questo non può essere revocato. Ricorda: possono facilmente aggiungerlo ai segnalibri.

L'utilizzo di valori imprevedibili aiuterebbe sicuramente i tuoi altri requisiti qualora fossero ritenuti necessari per la tua applicazione. Raccomanderei di usare un valore casuale a 128 bit che è più che sufficiente di entropia per prevenire la prevedibilità e le collisioni.

    
risposta data 14.04.2016 - 13:26
fonte
2

tl; dr: dipende, se puoi, da un CSPRNG.

Mentre spesso vengono utilizzati UUID che non sono (destinati ad essere) da un CSPRNG, ciò potrebbe non essere una buona idea nei casi in cui (non CS) -PRNG non viene re-seeded regualarly (come nei processi del server long-living )

Se l'algoritmo che usi per creare tali identificatori è noto - e il suo input può essere stimato con alcuni esempi (come nel caso di C rand() per esempio) - perdi tutte quelle proprietà enumerate nella tua domanda.

Anche se l'utilizzo di un PRNG prevedibile per generare valori da un singolo seme è quindi negativo, se il PRNG errato viene ridistribuito con buona entropia prima di ogni utilizzo (come nel caso normale nella maggior parte degli sz-zari web), dovrebbe andare bene.

Quindi, se puoi, usa un CSPRNG. Se non ci riesci, prova a ridistribuirlo con una buona entropia prima di ogni passaggio di generazione.

Tutto dipende da come viene seminato e utilizzato il processo di generazione.

Se hai un processo di lunga durata, usa un CSPRNG. Se si utilizzano processi di breve durata, utilizzare una buona fonte di entropia e praticamente qualsiasi PRNG.

    
risposta data 13.04.2016 - 15:03
fonte
2

Sì. Un RNG perfettamente protetto è necessario per completare tutte le cose che hai elencato.

Non so come funzioni Math.random, ma penso a un RNG TERRIBILE chiameremo 2bitRNG che è seminato con soli 2 bit, ma produce numeri a 128 bit. Io semino 2bitRNG con i miei 2 bit di entropia e poi produco 10.000 numeri casuali con esso.

Dal momento che l'ho seminato solo con 2 bit, ci sono solo 4 possibili semi. Quindi un utente malintenzionato deve solo cercare uno spazio di 40.000 possibili numeri casuali per trovare il seme corretto e posizionarsi nella sequenza in cui ci si trova attualmente. Questo è un numero piccolo e probabilmente potrebbe essere calcolato in una frazione di secondo con un computer modesto. Una volta che l'attaccante lo sa, conosce la sequenza successiva e quanti RNG hai prodotto.

Non so quanto sia pessimo Math.random o quali altri attacchi potrebbero essere vulnerabili, ma la raccomandazione generale è NON usarla per motivi di sicurezza perché non è sicura. Un RNG sicuro appropriato utilizza una grande quantità di entropia (~ 128 bit o superiore) per prevenire il tipo di attacco che ho appena descritto e non produce risultati prevedibili.

    
risposta data 13.04.2016 - 15:05
fonte
1

Raccomando senz'altro l'uso di un generatore di numeri casuali protetto da crittografia laddove possibile, indipendentemente da quali siano i dati. I lati positivi superano i lati negativi.

Inoltre, non si sa mai quale codice potrebbe essere usato per dopo. Quando eseguo revisioni di codice, nella maggior parte dei casi, contrassegnerò sempre l'uso di un generatore di numeri casuali non crittograficamente sicuro.

Potresti anche voler vedere l'uso di per sessione riferimenti ad oggetti indiretti come in alcuni casi questi possono avere senso usare. Non dimenticare di eseguire i controlli di autorizzazione / privilegio prima di utilizzare o restituire dati dal client.

    
risposta data 13.04.2016 - 15:02
fonte
1

Fai un passo indietro e dai un'occhiata al tuo problema da un altro punto di vista. Qual è la cosa peggiore che potrebbe accadere se si usassero numeri sequenziali? Hai menzionato l'enumerazione: qual è la minaccia dell'enumerazione? Qualcuno può causare un problema se vede il tuo numero # 00015 e # 00016 e prevedere che l'ID # 00017 verrà probabilmente generato successivamente? Forse qualcuno potrebbe dirottare un'email o un account Twitter che probabilmente sarà associato a un ID imminente.

E qual è il problema se qualcuno può determinare che l'ID # 00023 è più vecchio di ID # 42234? Gli ID precedenti hanno generalmente più risorse disponibili rispetto ai nuovi ID? Forse so che l'ID 00123 è stato rilasciato il 1 ° maggio e l'ID 00256 è stato rilasciato il 1 ° giugno; se apprendo che alcune celebrità famose hanno annunciato di essersi iscritte a maggio, ho solo 133 numeri per indovinare la loro identità. Indovinare l'ID di qualcuno può causare a qualcuno un problema, o sarà comunque un'informazione pubblica?

A questo punto dovresti capire se i # ID sequenziali devono essere tenuti segreti, o se possono essere pubblici.

Quindi dai un'occhiata ai vettori delle minacce (se si tratta di minacce realistiche) e dai rischi. Molti di questi sembrano essere rischi per i tuoi clienti se i loro ID segreti diventano pubblici e meno pericolosi per i tuoi sistemi. Ma se non stai proteggendo i tuoi clienti, la tua reputazione sarà certamente distrutta e la tua impresa fallirà. Quindi se queste sono minacce valide, devi prenderle sul serio.

Successivamente, aggiungi la comprensione che un Pseudo-Random Number Generator (PRNG) è stato creato esattamente per uno scopo specifico: generare numeri statisticamente ben distribuiti per problemi di modellazione nelle statistiche. Non sono mai stati creati per generare numeri "non raccomandabili". La maggior parte dei PRNG sono solo un problema di matematica dall'essere un generatore di numeri sequenziali. Puoi provare a saltare attraverso molti circuiti di semina per ridurre la capacità di generare numeri indovinabili, ma questo è esattamente il problema che un PRNG crittograficamente sicuro (CSPRNG) è progettato per risolvere. I CSPRNG sono stati specificamente progettati per generare numeri non raccomandabili.

Ora che comprendi meglio alcuni dei rischi, dovresti apprezzare il motivo per cui hai bisogno (o non hai bisogno) di proteggere i tuoi clienti da queste minacce; e con una migliore comprensione delle differenze tra un PRNG e un CSPRNG, puoi arrivare a una decisione solida.

Se devi mantenere questi segreti, allora devi usare un CSPRNG per proteggere i tuoi clienti. Se non è necessario mantenerli segreti, è necessario utilizzare un numero sequenziale e ridurre la complessità del sistema eliminando del tutto il generatore di numeri casuali.

    
risposta data 13.04.2016 - 15:58
fonte
1

I PRNG non crittograficamente protetti sono vulnerabili all'analisi che può determinare i parametri che generano la sequenza. Una volta conosciuta la sequenza, è possibile determinare non solo il valore successivo, ma anche il numero totale di numeri di sequenza in uso. Vedi link per un affascinante esempio di come farlo nel mondo reale.

Oltre a rendere non identificabili gli identificatori sequenziali, in genere si desidera evitare di generare due volte lo stesso identificatore all'interno dello stesso contesto. Se si utilizza un PRNG, il numero di identificatori è limitato dal periodo del PNRG ed è vulnerabile a eventuali punti deboli nella generazione del seme. Se si utilizza il generatore di numeri casuali crittograficamente sicuro, il numero di identificatori è limitato dalla dimensione dell'identificatore e dovrebbe essere meno vulnerabile ai problemi di seeding.

Se i numeri vengono utilizzati in un sistema chiuso in cui vengono generati al massimo qualche migliaio di identificatori, allora un PRNG è probabilmente OK.

Se gli identificatori devono essere generati in modo distribuito e globalmente univoci, quindi l'uso di un generatore di numeri casuali protetto da crittografia garantisce che non vi siano collisioni.

    
risposta data 14.04.2016 - 15:46
fonte

Leggi altre domande sui tag