Zayıf PRNG

OWASP kategorisi: MASVS-CRYPTO: Kriptografi

Genel Bakış

Sözde rastgele sayı üreteci (PRNG), başlangıç değeri adı verilen bir başlangıç değerine dayalı olarak tahmin edilebilir sayı dizileri oluşturan bir algoritmadır. PRNG tarafından oluşturulan sayı dizisi, yaklaşık olarak tamamen rastgele bir sayı dizisiyle aynı özelliklere sahiptir ancak daha hızlıdır ve oluşturulması daha az hesaplama maliyetlidir.

Diğer bir deyişle, PRNG'ler, entropi dağılımının eşitliği açısından zayıf RNG'lerden (ör. java.math.Random) daha fazla güvenceye sahiptir ve gerçekten rastgele sayı dizilerini taklit eder. Gerçekten rastgele sayı üretimi için özel ekipman gerekir ve genellikle normal geliştirme kapsamı dışındadır. Bu belge, gerçekten rastgele sayı oluşturmayı kapsamaz ve yalnızca kullanılan standart metodoloji oldukları için PRNG'lere odaklanır.

Zayıf PRNG güvenlik açıkları, geliştiriciler kriptografik amaçlar için kriptografik olarak güvenli bir PRNG (CSPRNG) yerine normal bir PRNG kullandığında ortaya çıkar. CSPRNG'ler daha katı koşullara sahiptir ve başlangıç değeri bilinmediğinde, saldırgana bir çıktı dizisini gerçek bir rastgele diziden ayırt etme konusunda yalnızca önemsiz bir avantaj sağlamalıdır.

Geliştirici tarafından sabit kodlanmış olanlar gibi tahmin edilebilir başlangıç değerleri, PRNG veya CSPRNG başlatmak için kullanıldığında saldırganlar, oluşturulan sayı dizisini de tahmin edebilir. Bunun nedeni, saldırganın başlangıç değerini tahmin edip PRNG tarafından oluşturulan çıkışı tahmin edebilmesidir.

Etki

Kimlik doğrulama gibi bir güvenlik bağlamında kriptografik olarak güvenli olmayan bir PRNG kullanılırsa saldırgan, rastgele oluşturulan sayıları tahmin edebilir ve ayrıcalıklı verilere veya özelliklere erişebilir.

Çözümler

Genel

java.security.SecureRandom

Güvenlik amaçlı kullanım için önerilir. Android'de, SecureRandom.getInstanceStrong(), AndroidOpenSSL'dan SHA1PRNG almakla eş değerdir. Bu, engelleme /dev/random uygulamasıyla eşlenmez. Bu özelliği kullanmak için getInstanceStrong() numarasını arayın:

Kotlin

val rand = SecureRandom.getInstanceStrong()

Java

SecureRandom rand = SecureRandom.getInstanceStrong();

Aksi takdirde, Linux çekirdeğinin 5.17'den önceki sürümlerinde rastgele sayılar oluşturulurken iş parçacığının engellenmesi kabul edilemez olduğunda SecureRandom oluşturucusu doğrudan çağrılmalıdır:

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'den varsayılan başlangıç değerini alır ve nesne oluşturulduğunda veya alındığında otomatik olarak kullanılır. Bu nedenle, PRNG'yi açıkça başlatmaya gerek yoktur. Genel olarak, SecureRandom değerinin deterministik kullanımı (özellikle bu durum, uygulamayı derlemeden çıkaran herkesin görebileceği bir başlangıç değerinin sabit kodlanmasına yol açıyorsa) önerilmez. Yeniden üretilebilir sözde rastgele çıkış oluşturmak isteyen geliştiriciler HMAC, HKDF ve SHAKE gibi daha uygun temel öğeleri kullanmalıdır.

java.util.Random

Güvenlik / kimlik doğrulama amacıyla kullanılmamalıdır. Diğer amaçlar için kullanılabilir.

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

Kaynaklar