شعار PRNG ضعيف

فئة OWASP: MASVS-CRYPTO: التشفير

نظرة عامة

مُنشئ الأرقام العشوائية الزائفة (PRNG) هو خوارزمية تنشئ تسلسلات أرقام يمكن توقّعها استنادًا إلى قيمة بداية تُعرف باسم القيمة العشوائية. ويحتوي تسلسل الأرقام الذي ينشئه مُنشئ الأرقام العشوائية الزائفة على الخصائص نفسها تقريبًا التي يحتوي عليها تسلسل الأرقام العشوائية الحقيقية، ولكن إنشاءه أسرع وأقل تكلفة من الناحية الحسابية.

بعبارة أخرى، يقدّم مُنشئو الأرقام العشوائية الزائفة ضمانات أعلى من مُنشئي الأرقام العشوائية الضعيفة (مثل java.math.Random) من حيث التوزيع المتساوي للإنتروبيا، ما يحاكي تسلسلات الأرقام العشوائية الحقيقية. ويتطلّب إنشاء أرقام عشوائية حقيقية معدّات متخصّصة، وغالبًا ما يكون خارج نطاق التطوير العادي. لا يتناول هذا المستند إنشاء أرقام عشوائية حقيقية، ويركّز فقط على مُنشئي الأرقام العشوائية الزائفة لأنّهم المنهجية العادية المستخدَمة.

تحدث الثغرات الأمنية في مُنشئي الأرقام العشوائية الزائفة الضعيفة عندما يستخدم المطوّرون مُنشئ أرقام عشوائية زائفة عاديًا لأغراض التشفير، بدلاً من مُنشئ أرقام عشوائية زائفة آمن بطريقة مشفّرة (CSPRNG). يفرض مُنشئو الأرقام العشوائية الزائفة الآمنة بطريقة مشفّرة متطلبات أكثر صرامة، وعندما تكون القيمة العشوائية غير معروفة، يجب ألا يمنحوا المهاجم سوى ميزة ضئيلة في التمييز بين تسلسل الإخراج وتسلسل عشوائي فعلي.

قد يتمكّن المهاجمون أيضًا من تخمين تسلسل الأرقام الذي تم إنشاؤه عند استخدام قيم عشوائية يمكن توقّعها، مثل تلك التي تم ترميزها بشكل ثابت من قِبل المطوّر، لتهيئة مُنشئ أرقام عشوائية زائفة أو مُنشئ أرقام عشوائية زائفة آمن بطريقة مشفّرة، لأنّ المهاجم يمكنه تخمين القيمة العشوائية وبالتالي توقّع الإخراج الذي ينشئه مُنشئ الأرقام العشوائية الزائفة.

التأثير

إذا تم استخدام مُنشئ أرقام عشوائية زائفة غير آمن بطريقة مشفّرة في سياق أمان مثل المصادقة، قد يتمكّن المهاجم من تخمين الأرقام التي تم إنشاؤها عشوائيًا والوصول إلى بيانات أو ميزات مميّزة.

الإجراءات المخفّفة

بنود عامة

java.security.SecureRandom

يُنصح باستخدامه لأغراض الأمان. إذا كان إصدار Linux kernel هو 5.17 أو إصدار أحدث أو كان حظر سلسلة المحادثات مقبولاً، انتظِر إلى أن تتراكم إنتروبيا كافية قبل إنشاء الأرقام العشوائية (أي استخدِم /dev/random). للقيام بذلك، استخدِم getInstanceStrong():

Kotlin

val rand = SecureRandom.getInstanceStrong()

Java

SecureRandom rand = SecureRandom.getInstanceStrong();

بخلاف ذلك، في إصدارات Linux kernel السابقة للإصدار 5.17، عندما يكون حظر سلسلة التعليمات غير مقبول عند إنشاء أرقام عشوائية، يجب استدعاء طريقة وضع التصميم 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، ويتم استخدامها تلقائيًا عند إنشاء الكائن أو الحصول عليه، لذا ما مِن حاجة إلى تحديد القيمة العشوائية لمُنشئ الأرقام العشوائية الزائفة بشكلٍ صريح. بشكلٍ عام، لا يُنصح بأي استخدام حتمي لـ 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);
    }
}

الموارد