PRNG Lemah

Kategori OWASP: MASVS-CRYPTO: Kriptografi

Ringkasan

Generator angka pseudorandom (PRNG) adalah algoritma yang menghasilkan urutan angka yang dapat diprediksi berdasarkan nilai awal yang disebut seed. Urutan angka yang dihasilkan PRNG memiliki perkiraan properti yang sama dengan urutan angka yang benar-benar acak, tetapi lebih cepat dan lebih murah secara komputasi untuk dibuat.

Dengan kata lain, PRNG memiliki jaminan yang lebih tinggi daripada RNG yang lemah (mis. java.math.Random) dalam hal distribusi entropi yang merata, yang mengemulasikan urutan angka yang benar-benar acak. Pembuatan angka yang benar-benar acak memerlukan peralatan khusus dan sering kali berada di luar cakupan pengembangan normal. Artikel ini tidak mencakup pembuatan angka yang benar-benar acak, dan hanya berfokus pada PRNG karena merupakan metodologi standar yang digunakan.

Kerentanan PRNG yang lemah terjadi saat developer menggunakan PRNG biasa untuk tujuan kriptografi, bukan PRNG yang aman secara kriptografis (CSPRNG). CSPRNG memiliki persyaratan yang lebih ketat, dan jika seed tidak diketahui, hal tersebut hanya dapat memberikan keuntungan yang tidak signifikan kepada penyerang dalam membedakan urutan output dengan urutan acak yang sebenarnya.

Penyerang mungkin juga dapat menebak urutan angka yang dihasilkan saat seed yang dapat diprediksi, seperti yang di-hardcode oleh developer, digunakan untuk melakukan inisialisasi PRNG atau CSPRNG, karena penyerang dapat menebak seed dan dengan demikian dapat memprediksi output yang dihasilkan oleh PRNG.

Dampak

Jika PRNG yang tidak aman secara kriptografis digunakan dalam konteks keamanan seperti autentikasi, penyerang mungkin dapat menebak angka yang dibuat secara acak dan mendapatkan akses ke data atau fungsi dengan hak istimewa.

Mitigasi

Umum

java.security.SecureRandom

Direkomendasikan untuk penggunaan keamanan. Jika versi kernel Linux adalah 5.17+ atau memblokir thread dapat diterima, tunggu hingga terakumulasi cukup entropi sebelum Anda menghasilkan angka acak (yaitu menggunakan /dev/random). Untuk melakukannya, panggil getInstanceStrong():

Kotlin

val rand = SecureRandom.getInstanceStrong()

Java

SecureRandom rand = SecureRandom.getInstanceStrong();

Jika tidak, pada versi kernel Linux sebelum 5.17, ketika memblokir thread tidak dapat diterima saat menghasilkan angka acak, konstruktor SecureRandom harus dipanggil secara langsung:

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 mendapatkan seed default dari /dev/urandom, dan otomatis digunakan saat objek dibuat atau diperoleh, sehingga tidak perlu menyediakan PRNG secara eksplisit. Secara umum, setiap penggunaan SecureRandom yang deterministik tidak disarankan (terutama jika ini menyebabkan hardcode nilai seed, yang dapat dilihat oleh siapa saja yang mendekompilasi aplikasi). Developer yang ingin menghasilkan output pseudorandom yang dapat direproduksi harus menggunakan primitif yang lebih sesuai seperti HMAC, HKDF, SHAKE, dll.

java.util.Random

Hindari untuk tujuan keamanan/autentikasi, dapat digunakan untuk hal lain.

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

Referensi