弱 PRNG
使用集合让一切井井有条
根据您的偏好保存内容并对其进行分类。
OWASP 类别:MASVS-CRYPTO:加密
概览
伪随机数生成器 (PRNG) 是一种根据称为种子的起始值生成可预测的数字序列的算法。由 PRNG 生成的数字序列在属性上与真正的随机数序列大致相同,但前者创建速度更快,计算开销也更低。
也就是说,对于模拟真正的随机数序列的熵分配,在均匀性方面,PRNG 比弱 RNG(例如 java.math.Random
)更有保证。真正随机数的生成需要专门的设备,通常不在正常开发的范围之内。本文并不涵盖真正随机数的生成,仅重点介绍 PRNG,因为 PRNG 是当下使用的标准方法。
如果开发者使用常规 PRNG 进行加密,而不采用确保加密安全的 PRNG (CSPRNG),就会出现弱 PRNG 漏洞。CSPRNG 有更严格的要求,当种子未知时,它们只能让攻击者在区分输出序列与实际随机序列方面占据微乎其微的优势。
当系统使用可预测的种子(例如开发者硬编码的种子)来初始化 PRNG 或 CSPRNG 时,攻击者或许还可以猜测生成的种子序列,因为攻击者可以猜测出这些种子,从而预测 PRNG 生成的输出。
影响
如果在身份验证等安全上下文中使用无法确保加密安全的 PRNG,攻击者或许能猜出随机生成的数字,获得需要特权才能访问的数据或功能的访问权限。
缓解措施
常规
java.security.SecureRandom
用于安全用途时,建议使用。如果 Linux 内核版本为 5.17 或以上,或者可以阻止线程,可等待累积足够多的熵后再生成随机数(即使用 /dev/random
)。为此,请调用 getInstanceStrong()
:
Kotlin
val rand = SecureRandom.getInstanceStrong()
Java
SecureRandom rand = SecureRandom.getInstanceStrong();
但是在 5.17 之前的 Linux 内核版本中,如果在生成随机数时不可阻止线程,那么应直接调用 SecureRandom
构造函数:
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
会从 /dev/urandom
获取默认种子,并且系统在构建或获取对象时会自动使用它,因此无需明确获取 PRNG 的种子。一般来说,不建议对 SecureRandom 进行任何确定性的使用(如果这样做会导致对种子值进行硬编码,而任何人在解压缩该应用时都能看到该种子值,便更为如此)。如果开发者想要生成可重现的伪随机输出,应使用更合适的基元,例如 HMAC、HKDF、SHAKE 等。
java.util.Random
避免用于安全/身份验证目的,适用于任何其他用途。
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);
}
}
资源
本页面上的内容和代码示例受内容许可部分所述许可的限制。Java 和 OpenJDK 是 Oracle 和/或其关联公司的注册商标。
最后更新时间 (UTC):2023-12-13。
[null,null,["最后更新时间 (UTC):2023-12-13。"],[],[],null,["# Weak PRNG\n\n\u003cbr /\u003e\n\n**OWASP category:** [MASVS-CRYPTO: Cryptography](https://mas.owasp.org/MASVS/06-MASVS-CRYPTO)\n\nOverview\n--------\n\nA pseudorandom number generator (PRNG) is an algorithm that generates\npredictable number sequences based on a starting value called a *seed* . A\nPRNG-generated number sequence has **approximately** the same properties as a\ntruly random number sequence, but is faster and less computationally expensive\nto create.\n\nIn other words, PRNGs have higher assurances than weak RNGs (e.g.\n`java.math.Random`) in terms of evenness of entropy distribution, which emulate\ntruly random number sequences. Truly random number generation requires\nspecialized equipment and is often outside the scope of normal development. This\ndocument does not cover truly random number generation, and focuses only on\nPRNGs as they are the standard methodology in use.\n\nWeak PRNG vulnerabilities occur when developers use a regular PRNG for\ncryptographic purposes, instead of a cryptographically-secure PRNG (CSPRNG).\nCSPRNGs have stricter requirements, and when the seed is unknown, they must give\nan attacker only an insignificant advantage in differentiating an output\nsequence from an actual random sequence.\n\nAttackers may also be able to guess the generated number sequence when\npredictable seeds -- such as those hard coded by the developer -- are used to\ninitialize a PRNG or CSPRNG, as the attacker can guess the seed and thus predict\nthe output generated by the PRNG.\n\nImpact\n------\n\nIf a non-cryptographically secure PRNG is used in a security context like\nauthentication, an attacker may be able to guess the randomly-generated numbers\nand gain access to privileged data or features.\n\nMitigations\n-----------\n\n### General\n\n- Use [`java.security.SecureRandom`](/reference/java/security/SecureRandom) when there are *security implications*\n- Use [`java.util.Random`](/reference/java/util/Random) for any other cases\n- **Never** use [`Math.random`](/reference/java/lang/Math#random())!\n\n### java.security.SecureRandom\n\n**Recommended** for security uses. If the Linux kernel version is 5.17+ *or*\nblocking the thread is acceptable, wait for enough entropy to accumulate before\nyou generate the random numbers (i.e. use `/dev/random`). To do so, call\n`getInstanceStrong()`: \n\n### Kotlin\n\n val rand = SecureRandom.getInstanceStrong()\n\n### Java\n\n SecureRandom rand = SecureRandom.getInstanceStrong();\n\nOtherwise, on Linux kernel versions prior to 5.17 when blocking the thread is\nunacceptable when generating random numbers, then the `SecureRandom` constructor\nshould be called directly: \n\n### Kotlin\n\n import java.security.SecureRandom\n\n object generateRandom {\n @JvmStatic\n fun main(args: Array\u003cString\u003e) {\n // Create instance of SecureRandom class\n val rand = SecureRandom()\n\n // Generate random integers in range 0 to 999\n val rand_int = rand.nextInt(1000)\n\n // Use rand_int for security & authentication\n }\n }\n\n### Java\n\n import java.security.SecureRandom;\n\n public class generateRandom {\n\n public static void main(String args[])\n {\n // Create instance of SecureRandom class\n SecureRandom rand = new SecureRandom();\n\n // Generate random integers in range 0 to 999\n int rand_int = rand.nextInt(1000);\n\n // Use rand_int for security & authentication\n }\n }\n\n`SecureRandom` gets the default seed from `/dev/urandom`, and is automatically\nused when the object is constructed or obtained, so there is no need to\nexplicitly seed the PRNG. In general, any deterministic usage of `SecureRandom`\nis discouraged (especially if this leads to hard coding a seed value, which\nanyone decompiling the app can see). Developers who want to generate\nreproducible pseudorandom output should use more appropriate primitives such as\nHMAC, HKDF, and SHAKE.\n\n### java.util.Random\n\n**Avoid** for security / authentication purposes, acceptable to use for anything\nelse. \n\n### Kotlin\n\n import java.util.Random\n\n object generateRandom {\n @JvmStatic\n fun main(args: Array\u003cString\u003e) {\n // Create instance of SecureRandom class\n val rand = Random()\n\n // Generate random integers in range 0 to 999\n val rand_int = rand.nextInt(1000)\n }\n }\n\n### Java\n\n import java.util.Random;\n\n public class generateRandom {\n\n public static void main(String args[])\n {\n // Create instance of Random class\n Random rand = new Random();\n\n // Generate random integers in range 0 to 999\n int rand_int = rand.nextInt(1000);\n }\n }\n\nResources\n---------\n\n- [java.security.SecureRandom](/reference/java/security/SecureRandom)\n- [java.util.Random](/reference/java/util/Random)\n- [Math.random](/reference/java/lang/Math#random())\n- [Predictable Seed CWE](https://cwe.mitre.org/data/definitions/337.html)\n- [Cryptographically Weak PRNG CWE](https://cwe.mitre.org/data/definitions/338.html)\n- [Java Secure Random](https://www.baeldung.com/java-secure-random)\n- [Java Random versus SecureRandom](https://www.geeksforgeeks.org/random-vs-secure-random-numbers-java/)\n- [How to use SecureRandom](https://tersesystems.com/blog/2015/12/17/the-right-way-to-use-securerandom/)\n- [Python PRNG security guidance](https://rules.sonarsource.com/python/RSPEC-2245)\n- [OWASP Cryptographic Storage Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Cryptographic_Storage_Cheat_Sheet.html#secure-random-number-generation)\n- [CVE-2013-6386: Weak PRNG vuln in Drupal](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2013-6386)\n- [CVE-2006-3419: Weak PRNG vuln in Tor](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2006-3419)\n- [CVE-2008-4102: Predictable Seed in Joomla](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2008-4102)\n- [Linux Kernel random patch](https://lwn.net/Articles/884875/)"]]