PRNG ضعیف

رده OWASP: MASVS-CRYPTO: رمزنگاری

نمای کلی

مولد اعداد شبه‌تصادفی (PRNG) الگوریتمی است که توالی‌های عددی قابل پیش‌بینی را بر اساس یک مقدار اولیه به نام « بذر» (seed) تولید می‌کند. یک توالی عددی تولید شده توسط PRNG تقریباً همان ویژگی‌های یک توالی عددی واقعاً تصادفی را دارد، اما سریع‌تر و از نظر محاسباتی کم‌هزینه‌تر است.

به عبارت دیگر، PRNGها از نظر یکنواختی توزیع آنتروپی، که توالی‌های اعداد واقعاً تصادفی را شبیه‌سازی می‌کنند، نسبت به RNGهای ضعیف (مثلاً java.math.Random ) اطمینان بیشتری دارند. تولید اعداد واقعاً تصادفی نیاز به تجهیزات تخصصی دارد و اغلب خارج از محدوده توسعه عادی است. این سند تولید اعداد واقعاً تصادفی را پوشش نمی‌دهد و فقط بر PRNGها تمرکز دارد زیرا آنها روش استاندارد مورد استفاده هستند.

آسیب‌پذیری‌های PRNG ضعیف زمانی رخ می‌دهند که توسعه‌دهندگان از یک PRNG معمولی برای اهداف رمزنگاری، به جای یک PRNG امن رمزنگاری‌شده (CSPRNG) استفاده می‌کنند. CSPRNGها الزامات سختگیرانه‌تری دارند و وقتی سید ناشناخته باشد، باید به مهاجم تنها یک مزیت ناچیز در تمایز یک توالی خروجی از یک توالی تصادفی واقعی بدهند.

مهاجمان همچنین ممکن است بتوانند توالی اعداد تولید شده را حدس بزنند، زمانی که از سیدهای قابل پیش‌بینی - مانند سیدهایی که توسط توسعه‌دهنده کدگذاری شده‌اند - برای مقداردهی اولیه PRNG یا CSPRNG استفاده می‌شود، زیرا مهاجم می‌تواند سید را حدس بزند و بنابراین خروجی تولید شده توسط PRNG را پیش‌بینی کند.

تأثیر

اگر یک PRNG غیر رمزنگاری‌شده امن در یک زمینه امنیتی مانند احراز هویت استفاده شود، یک مهاجم ممکن است بتواند اعداد تصادفی تولید شده را حدس بزند و به داده‌ها یا ویژگی‌های ممتاز دسترسی پیدا کند.

کاهش‌ها

عمومی

جاوا.امنیتی.SecureRandom

برای کاربردهای امنیتی توصیه می‌شود . اگر نسخه هسته لینوکس ۵.۱۷+ است یا مسدود کردن نخ قابل قبول است، قبل از تولید اعداد تصادفی (یعنی استفاده از /dev/random ) صبر کنید تا آنتروپی کافی جمع شود. برای انجام این کار، getInstanceStrong() را فراخوانی کنید:

کاتلین

val rand = SecureRandom.getInstanceStrong()

جاوا

SecureRandom rand = SecureRandom.getInstanceStrong();

در غیر این صورت، در نسخه‌های هسته لینوکس قبل از ۵.۱۷، وقتی مسدود کردن نخ هنگام تولید اعداد تصادفی غیرقابل قبول است، سازنده 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 gets the default seed from /dev/urandom , and is automatically used when the object is constructed or obtained, so there is no need to explicitly seed the PRNG. In general, any deterministic usage of SecureRandom is discouraged (especially if this leads to hard coding a seed value, which anyone decompiling the app can see). Developers who want to generate reproducible pseudorandom output should use more appropriate primitives such as HMAC, HKDF, and SHAKE.

java.util.Random

برای اهداف امنیتی/احراز هویت از آن اجتناب کنید ، استفاده از آن برای هر چیز دیگری قابل قبول است.

کاتلین

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);
    }
}

منابع