약한 PRNG
컬렉션을 사용해 정리하기
내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요.
OWASP 카테고리: MASVS-CRYPTO: 암호화
개요
의사 난수 생성기(PRNG)는 시드라고 하는 시작 값을 기반으로 예측 가능한 숫자 시퀀스를 생성하는 알고리즘입니다. PRNG에서 생성하는 숫자 시퀀스는 진짜 랜덤 숫자 시퀀스와 속성은 거의 동일하지만, 시퀀스를 생성하는 속도가 더 빠르고 계산 비용이 더 적게 듭니다.
즉, 실제로 랜덤 숫자 시퀀스를 에뮬레이션하는 PRNG는 엔트로피 분포의 균일성 측면에서 약한 RNG(예: java.math.Random
)보다 보장 확률이 높습니다. 진짜 랜덤 숫자를 생성하는 데에는 전문 장비가 필요하고 이 작업은 종종 일반적인 개발 범위를 벗어납니다. 이 도움말에서는 진짜 랜덤 숫자를 생성하는 것은 다루지 않으며, 표준 방법론인 PRNG에만 중점을 둡니다.
약한 PRNG의 취약점은 개발자가 암호화 방식으로 보호되는 PRNG(CSPRNG) 대신 암호화 용도의 일반 PRNG를 사용하는 경우에 발생합니다. CSPRNG의 요구사항이 더 엄격하며, 시드를 알 수 없는 경우, 실제 랜덤 시퀀스로부터 출력 시퀀스를 차별화하는 데 있어 공격자에게 무의미한 이득만 있어야 합니다.
PRNG 또는 CSPRNG를 초기화하는 데 예측 가능한 시드(개발자에 의해 하드코딩된 시드)가 사용되면 공격자가 생성된 숫자 시퀀스를 추측할 수 있을 수도 있습니다. 공격자가 시드를 추측할 수 있고 그러면 PRNG에서 생성한 출력을 예측할 수 있기 때문입니다.
영향
암호화하지 않는 방식의 보안 PRNG가 인증과 같은 보안 컨텍스트에서 사용되면 공격자는 임의로 생성된 숫자를 추측할 수도 있고 권한이 필요한 데이터 또는 기능에 액세스할 수도 있습니다.
완화 조치
일반
java.security.SecureRandom
보안 용도로 권장됩니다. Linux 커널 버전이 5.17 이상 또는 스레드 차단이 허용 가능한 경우 랜덤 숫자를 생성하기 전에 충분한 엔트로피가 누적될 때까지 기다립니다 (예: /dev/random
사용). 이렇게 하려면 다음과 같이 getInstanceStrong()
을 호출하면 됩니다.
Kotlin
val rand = SecureRandom.getInstanceStrong()
자바
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
}
}
자바
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);
}
}
리소스
이 페이지에 나와 있는 콘텐츠와 코드 샘플에는 콘텐츠 라이선스에서 설명하는 라이선스가 적용됩니다. 자바 및 OpenJDK는 Oracle 및 Oracle 계열사의 상표 또는 등록 상표입니다.
최종 업데이트: 2023-12-08(UTC)
[[["이해하기 쉬움","easyToUnderstand","thumb-up"],["문제가 해결됨","solvedMyProblem","thumb-up"],["기타","otherUp","thumb-up"]],[["필요한 정보가 없음","missingTheInformationINeed","thumb-down"],["너무 복잡함/단계 수가 너무 많음","tooComplicatedTooManySteps","thumb-down"],["오래됨","outOfDate","thumb-down"],["번역 문제","translationIssue","thumb-down"],["샘플/코드 문제","samplesCodeIssue","thumb-down"],["기타","otherDown","thumb-down"]],["최종 업데이트: 2023-12-08(UTC)"],[],[],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/)"]]