Категория OWASP: MASVS-CRYPTO: Криптография
Обзор
Генератор псевдослучайных чисел (PRNG) — это алгоритм, который генерирует предсказуемые числовые последовательности на основе начального значения, называемого начальным числом . Числовая последовательность, сгенерированная с помощью PRNG, имеет примерно те же свойства, что и действительно случайная числовая последовательность, но ее создание выполняется быстрее и требует меньше вычислительных затрат.
Другими словами, ГПСЧ имеют более высокие гарантии, чем слабые ГСЧ (например, java.math.Random
) с точки зрения равномерности распределения энтропии, которые имитируют действительно последовательности случайных чисел. Генерация по-настоящему случайных чисел требует специального оборудования и часто выходит за рамки обычной разработки. В этом документе не рассматривается по-настоящему генерация случайных чисел, а основное внимание уделяется только ГПСЧ, поскольку они являются стандартной используемой методологией.
Слабые уязвимости PRNG возникают, когда разработчики используют обычный PRNG для криптографических целей вместо криптографически безопасного PRNG (CSPRNG). К CSPRNG предъявляются более строгие требования, и когда начальное число неизвестно, они должны давать злоумышленнику лишь незначительное преимущество в различении выходной последовательности от фактической случайной последовательности.
Злоумышленники также могут угадать сгенерированную числовую последовательность, когда предсказуемые начальные числа – например, жестко закодированные разработчиком – используются для инициализации PRNG или CSPRNG, поскольку злоумышленник может угадать начальное число и, таким образом, предсказать выходные данные, сгенерированные PRNG.
Влияние
Если некриптографически защищенный PRNG используется в контексте безопасности, например при аутентификации, злоумышленник может угадать случайно сгенерированные числа и получить доступ к привилегированным данным или функциям.
Смягчения
Общий
- Используйте
java.security.SecureRandom
когда есть проблемы с безопасностью. - Используйте
java.util.Random
для любых других случаев. - Никогда не используйте
Math.random
!
java.security.SecureRandom
Рекомендуется для использования в целях безопасности. Если версия ядра Linux 5.17+ или блокировка потока допустима, подождите, пока накопится достаточно энтропии, прежде чем генерировать случайные числа (т. е. используйте /dev/random
). Для этого вызовите getInstanceStrong()
:
Котлин
val rand = SecureRandom.getInstanceStrong()
Ява
SecureRandom rand = SecureRandom.getInstanceStrong();
В противном случае в версиях ядра Linux до 5.17, когда блокировка потока при генерации случайных чисел недопустима, конструктор SecureRandom
следует вызывать напрямую:
Котлин
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
}
}
Ява
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
получает начальное значение по умолчанию из /dev/urandom
и автоматически используется при создании или получении объекта, поэтому нет необходимости явно задавать PRNG. В общем, любое детерминированное использование SecureRandom
не рекомендуется (особенно, если это приводит к жесткому кодированию начального значения, которое может увидеть любой, кто декомпилирует приложение). Разработчикам, которые хотят генерировать воспроизводимый псевдослучайный вывод, следует использовать более подходящие примитивы, такие как HMAC, HKDF и SHAKE.
java.util.Случайный
Избегайте использования в целях безопасности/аутентификации, допускается использование для чего-либо еще.
Котлин
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)
}
}
Ява
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);
}
}
Ресурсы
- java.security.SecureRandom
- java.util.Случайный
- Math.random
- Предсказуемое семя CWE
- Криптографически слабый PRNG CWE
- Java Безопасный Случайный
- Java Random против SecureRandom
- Как использовать SecureRandom
- Руководство по безопасности Python PRNG
- Памятка по криптографическому хранилищу OWASP
- CVE-2013-6386: Слабая уязвимость PRNG в Drupal.
- CVE-2006-3419: Слабая уязвимость PRNG в Tor.
- CVE-2008-4102: предсказуемое начальное число в Joomla
- Случайный патч ядра Linux