PRNG חלש

קטגוריה ב-OWASP: MASVS-CRYPTO: קריפטוגרפיה

סקירה כללית

מחולל מספרים מדומה (PRNG) הוא אלגוריתם שיוצר רצפי מספרים צפויים שמבוססים על ערך התחלה שנקרא seed. א' לרצף מספרים שנוצר על ידי PRNG יש בערך אותם מאפיינים כמו רצף מספרים אקראי באמת, אבל הוא מהיר יותר ופחות יקר מבחינה חישובית. ליצירה.

במילים אחרות, ל-PRNG יש רמת הבטחות גבוהה יותר מאשר ב-RNG חלשים (למשל, java.math.Random) מבחינת שוויון התפלגות האנטרופיה, רצפי מספרים אקראיים באמת. כדי ליצור מספרים אקראיים באמת, נדרש ציוד מיוחד ולרוב זה לא נכלל בהיקף הפיתוח הרגיל. הזה אינו מתייחס ליצירת מספרים אקראיים באמת, ומתמקד רק קובצי PRNG, כי הם המתודולוגיה הסטנדרטית בשימוש.

נקודות חולשה של PRNG חלש מתרחשות כשמפתחים משתמשים ב-PRNG רגיל למטרות קריפטוגרפיות, במקום ב-PRNG מאובטח מבחינה קריפטוגרפית (CSPRNG). ל-CSPRNG יש דרישות מחמירות יותר, וכאשר המקור לא ידוע, הוא חייב לתת לתוקף יתרון זניח בלבד בהבחנה בין רצף פלט לבין רצף אקראי בפועל.

תוקפים יוכלו גם לנחש את רצף המספרים שנוצר רכיבים ראשוניים צפויים – כמו אלה שקודדו באופן קשיח על ידי המפתח – משמשים לאתחל PRNG או CSPRNG, כי התוקף יכול לנחש את המקור ולחזות אותו הפלט שנוצר על ידי ה-PRNG.

השפעה

אם משתמשים ב-PRNG שלא מאובטח מבחינה קריפטוגרפית בהקשר אבטחה כמו אימות, יכול להיות שתוקפים יוכלו לנחש את המספרים שנוצרו באופן אקראי ולקבל גישה לתכונות או לנתונים מוגבלים.

פעולות מיטיגציה

כללי

Java.security.SecureRandom

מומלץ לשימושי אבטחה. אם גרסת הליבה של Linux היא 5.17 ואילך או אפשר לחסום את ה-thread, צריך לחכות עד שיצטברו מספיק אנטרופיה יוצרים את המספרים האקראיים (כלומר משתמשים ב-/dev/random). כדי לעשות את זה, צריך להתקשר getInstanceStrong():

Kotlin

val rand = SecureRandom.getInstanceStrong()

Java

SecureRandom rand = SecureRandom.getInstanceStrong();

אחרת, בגרסאות הליבה של Linux שקדמו ל-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, ומשתמש בהם באופן אוטומטי כשיוצרים או מקבלים את האובייקט, כך שאין צורך להגדיר זרעים ל-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);
    }
}

משאבים