Categoria OWASP: MASVS-CRYPTO: crittografia
Panoramica
Un generatore di numeri pseudocasuali (PRNG) è un algoritmo che genera sequenze numeriche prevedibili basate su un valore iniziale chiamato seed. R Una sequenza numerica generata da PRNG ha approssimativamente le stesse proprietà di una sequenza numerica una sequenza di numeri casuale, ma è più veloce e meno costosa dal punto di vista del calcolo per creare.
In altre parole, le PRNG offrono garanzie superiori rispetto alle RNG deboli (ad es.java.math.Random
) in termini di uniformità della distribuzione dell'entropia, che emulano sequenze di numeri veramente casuali. La generazione di numeri casuali richiede
apparecchiature specializzate e spesso non rientrano nell'ambito del normale sviluppo. Questo
documento non tratta la generazione di numeri veramente casuali e si concentra solo su
PRNG, in quanto rappresentano la metodologia standard in uso.
Le vulnerabilità PRNG deboli si verificano quando gli sviluppatori usano un PRNG normale per al posto di un PRNG con protezione crittografica (CSPRNG). I CSPRNG hanno requisiti più rigidi e, quando il seed è sconosciuto, devono fornire un aggressore è solo un vantaggio insignificante nel differenziare un output da una sequenza casuale effettiva.
Gli attaccanti potrebbero anche essere in grado di indovinare la sequenza di numeri generata quando vengono utilizzati semi prevedibili, ad esempio quelli hardcoded dallo sviluppatore, per inizializzare un generatore di numeri pseudo-casuali (PRNG) o un generatore di numeri pseudo-casuali basato su crittografia (CSPRNG), in quanto l'attaccante può indovinare il seme e quindi prevedere l'output generato dal PRNG.
Impatto
Se in un contesto di sicurezza come l'autenticazione viene utilizzato un generatore di numeri pseudocasuali non sicuro dal punto di vista della crittografia, un malintenzionato potrebbe essere in grado di indovinare i numeri generati in modo casuale e ottenere l'accesso a funzionalità o dati privilegiati.
Mitigazioni
Generali
- Utilizza
java.security.SecureRandom
quando ci sono implicazioni per la sicurezza - Utilizza
java.util.Random
per tutti gli altri casi - Non utilizzare mai
Math.random
.
java.security.SecureRandom
Consigliato per usi di sicurezza. Se la versione del kernel Linux è 5.17 o successiva o
il blocco del thread è accettabile, attendi che si accumuli sufficiente entropia prima
di generare i numeri casuali (ovvero utilizza /dev/random
). Per farlo, chiama
getInstanceStrong()
:
Kotlin
val rand = SecureRandom.getInstanceStrong()
Java
SecureRandom rand = SecureRandom.getInstanceStrong();
Altrimenti, nelle versioni del kernel Linux precedenti alla 5.17, quando il blocco del thread
non accettabile quando si generano numeri casuali, allora il costruttore SecureRandom
deve essere chiamato direttamente:
Kotlin
import java.security.SecureRandom
object generateRandom {
@JvmStatic
fun main(args: Array<String>) {
// Create instance of SecureRandom class
val rand = SecureRandom()
// Generate random integers in range 0 to 999
val rand_int = rand.nextInt(1000)
// Use rand_int for security & authentication
}
}
Java
import java.security.SecureRandom;
public class generateRandom {
public static void main(String args[])
{
// Create instance of SecureRandom class
SecureRandom rand = new SecureRandom();
// Generate random integers in range 0 to 999
int rand_int = rand.nextInt(1000);
// Use rand_int for security & authentication
}
}
SecureRandom
ottiene il seed predefinito da /dev/urandom
e viene automaticamente
utilizzata quando l'oggetto viene creato o ottenuto, quindi non è necessario
eseguire esplicitamente il seed del PRNG. In generale, qualsiasi utilizzo deterministico di SecureRandom
è sconsigliato (soprattutto se porta alla codifica forzata di un valore seed, che chiunque decompili l'app può vedere). Gli sviluppatori che vogliono generare un output pseudocasuale riproducibile devono utilizzare primitive più appropriate come HMAC, HKDF e SHAKE.
java.util.Random
Evita per motivi di sicurezza / autenticazione, accettabile per qualsiasi cosa diverso.
Kotlin
import java.util.Random
object generateRandom {
@JvmStatic
fun main(args: Array<String>) {
// Create instance of SecureRandom class
val rand = Random()
// Generate random integers in range 0 to 999
val rand_int = rand.nextInt(1000)
}
}
Java
import java.util.Random;
public class generateRandom {
public static void main(String args[])
{
// Create instance of Random class
Random rand = new Random();
// Generate random integers in range 0 to 999
int rand_int = rand.nextInt(1000);
}
}
Risorse
- java.security.SecureRandom
- java.util.Random
- Math.random
- Vulnerabilità CVE con seed prevedibile
- CWE PRNG dal punto di vista crittografico debole
- Java sicuro casuale
- Java Random e SecureRandom
- Come utilizzare SecureRandom
- guida per la sicurezza PRNG di Python
- Scheda di riferimento di OWASP per lo spazio di archiviazione crittografico
- CVE-2013-6386: vulnerabilità PRNG debole in Drupal
- CVE-2006-3419: vulnerabilità PRNG debole in Tor
- CVE-2008-4102: origine prevedibile in Joomla
- Patch casuale del kernel Linux