Kategoria OWASP: MASVS-CRYPTO: Kryptografia
Omówienie
Generator pseudorandomów (PRNG) to algorytm, który generuje przewidywalne sekwencje liczb na podstawie wartości początkowej nazywanej seedem. Sekwencja liczb wygenerowana przez PRNG ma w przybliżeniu te same właściwości co prawdziwa losowa sekwencja liczb, ale jej utworzenie jest szybsze i mniej kosztowne pod względem obliczeniowym.
Inaczej mówiąc, PRNG mają wyższe gwarancje niż słabe generatory liczb losowych (np.
java.math.Random
) pod względem równomierności rozkładu entropii, który emuluje
naprawdę losowe ciągi liczbowe. Prawdziwe losowe generowanie liczb wymaga specjalistycznego sprzętu i często wykracza poza zakres normalnego rozwoju. Ten
nie obejmuje generowania liczb losowych i skupia się tylko na
PRNG, ponieważ są to standardowa metodologia używana.
Słabe luki w zabezpieczeniach PRNG występują, gdy deweloperzy używają zwykłego PRNG do do celów kryptograficznych, a nie do kryptograficznie bezpiecznych PRNG (CSPRNG). CSPRNG mają bardziej rygorystyczne wymagania, a w przypadku nieznanej wartości wyjściowej muszą podać nieistotnej przewagi w rozróżnieniu danych wyjściowych, z rzeczywistej sekwencji losowej.
Atakujący mogą też być w stanie odgadnąć wygenerowaną sekwencję liczb, gdy do zainicjowania generatora liczb pseudolosowych (PRNG) lub generatora liczb pseudolosowych z zabezpieczeniem CSPRNG używane są przewidywalne nasiona, np. zakodowane na stałe przez dewelopera, ponieważ atakujący może odgadnąć nasienie i w ten sposób przewidzieć dane wyjściowe wygenerowane przez generator liczb pseudolosowych.
Wpływ
Jeśli niezabezpieczony kryptograficznie klucz PRNG jest używany w kontekście zabezpieczeń, na przykład uwierzytelnianie, haker może odgadnąć losowo wygenerowane liczby, oraz uzyskać dostęp do uprzywilejowanych danych i funkcji.
Środki zaradcze
Ogólne
- Używaj
java.security.SecureRandom
, gdy ma to wpływ na bezpieczeństwo - Użyj
java.util.Random
w innych przypadkach. - Nigdy nie używaj
Math.random
.
java.security.SecureRandom
Zalecany do celów związanych z bezpieczeństwem. Jeśli jądro Linux jest w wersji 5.17 lub nowszej lub
zablokowanie wątku, poczekaj na nagromadzenie wystarczającej entropii przed
generujesz liczby losowe (np. /dev/random
). Aby to zrobić, zadzwoń:
getInstanceStrong()
:
Kotlin
val rand = SecureRandom.getInstanceStrong()
Java
SecureRandom rand = SecureRandom.getInstanceStrong();
W innych wersjach jądra Linuxa, które są starsze niż 5.17, gdy blokowanie wątku jest niedopuszczalne podczas generowania liczb losowych, konstruktor SecureRandom
powinien być wywoływany bezpośrednio:
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
pobiera domyślne dane wyjściowe z /dev/urandom
i jest automatycznie stosowane
używanej podczas tworzenia lub uzyskiwania obiektu, więc nie trzeba
jawnie wywołuje PRNG. Ogólnie każde deterministyczne użycie funkcji SecureRandom
(zwłaszcza wtedy, gdy doprowadzi to do zakodowania na stałe wartości wyjściowej,
każdy użytkownik dekompilujący aplikację). Deweloperzy, którzy chcą generować
odtwarzalne dane wyjściowe powinny używać bardziej odpowiednich elementów podstawowych, takich jak
HMAC, HKDF i SHAKE.
java.util.Random
Unikaj stosowania w celu bezpieczeństwa lub uwierzytelniania, ale do innych celów jest ono dopuszczalne.
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);
}
}
Materiały
- java.security.SecureRandom
- java.util.Random
- Math.random
- Przewidywalny identyfikator CWE nasion
- CWE dotyczący słabego generatora liczb pseudolosowych z punktu widzenia kryptografii
- Java Secure Random
- Java Random vs. SecureRandom
- Jak korzystać z usługi SecureRandom
- Wskazówki dotyczące bezpieczeństwa Pythona PRNG
- Ściągawka OWASP dotycząca przechowywania danych zaszyfrowanych
- CVE-2013-6386: luka w Drupal dotycząca słabego generatora liczb pseudolosowych
- CVE-2006-3419: podatność w generatorze liczb pseudolosowych w Tor
- CVE-2008-4102: przewidywalny nasiew w Joomla
- Przypadkowa poprawka jądra systemu Linux