Saya telah membaca di banyak sumber bahwa output rand PHP () dapat diprediksi sebagai PRNG-nya, dan saya menerima itu sebagai fakta hanya karena saya melihatnya di banyak tempat.
Saya tertarik pada pembuktian konsep: bagaimana cara memprediksi hasil rand ()? Dari membaca artikel ini saya mengerti bahwa angka acak adalah angka yang dikembalikan dari daftar mulai dari pointer (seed) - tetapi saya tidak dapat membayangkan bagaimana hal ini dapat diprediksi.
Bisakah seseorang mencari tahu # acak apa yang dihasilkan melalui rand () pada saat tertentu dalam beberapa ribu tebakan? atau bahkan 10.000 tebakan? Bagaimana?
Ini muncul karena saya melihat perpustakaan auth yang menggunakan rand () untuk menghasilkan token untuk pengguna yang kehilangan kata sandi, dan saya berasumsi ini adalah celah keamanan potensial. Sejak itu saya mengganti metode dengan hashing campuran openssl_random_pseudo_bytes()
, kata sandi hasign orignal, dan microtime. Setelah melakukan ini, saya menyadari bahwa jika saya berada di luar mencari, saya tidak tahu bagaimana menebak token, bahkan mengetahui itu adalah md5 dari rand ().
Jawaban:
Kemampuan untuk menebak nilai selanjutnya
rand
terkait dengan kemampuan untuk menentukan apasrand
yang dipanggil. Secara khusus, penyemaiansrand
dengan jumlah yang ditentukan menghasilkan hasil yang dapat diprediksi ! Dari prompt interaktif PHP:Ini bukan hanya kebetulan. Sebagian besar versi PHP * di sebagian besar platform ** akan menghasilkan urutan 97, 97, 39, 77, 93 saat
srand
menggunakan 1024.Untuk lebih jelasnya, ini bukan masalah dengan PHP, ini adalah masalah dengan implementasi
rand
itu sendiri. Masalah yang sama muncul dalam bahasa lain yang menggunakan implementasi yang sama (atau serupa), termasuk Perl.Kuncinya adalah bahwa setiap versi PHP waras akan memiliki pra-seeded
srand
dengan nilai "tidak diketahui". Oh, tapi itu tidak terlalu diketahui. Dariext/standard/php_rand.h
:Jadi, ini adalah beberapa matematika dengan
time()
, PID, dan hasilphp_combined_lcg
, yang didefinisikan dalamext/standard/lcg.c
. Saya tidak akan tinggal di sini, karena mata saya berkaca-kaca dan saya memutuskan untuk berhenti berburu.Sedikit Googling menunjukkan bahwa area lain dari PHP tidak memiliki properti generasi keacakan terbaik , dan panggilan untuk
php_combined_lcg
menonjol di sini, terutama sedikit analisis ini:Ya itu
uniqid
. Tampaknya nilaiphp_combined_lcg
adalah apa yang kita lihat ketika kita melihat digit hex yang dihasilkan setelah memanggiluniqid
dengan argumen kedua diatur ke nilai sebenarnya.Sekarang, dimana kita?
Oh ya.
srand
.Jadi, jika kode yang Anda coba prediksi dari nilai acak tidak menelepon
srand
, Anda harus menentukan nilai yang disediakan olehphp_combined_lcg
, yang bisa Anda dapatkan (secara tidak langsung?) Melalui panggilan keuniqid
. Dengan nilai itu di tangan, layak untuk memaksa sisa nilai -time()
, PID dan beberapa matematika. Masalah keamanan terkait adalah tentang sesi istirahat, tetapi teknik yang sama akan bekerja di sini. Sekali lagi, dari artikel:Cukup ganti langkah terakhir seperti yang diminta.
(Masalah keamanan ini dilaporkan dalam versi PHP yang lebih lama (5.3.2) dari yang kita miliki saat ini (5.3.6), jadi ada kemungkinan bahwa perilaku
uniqid
dan / atauphp_combined_lcg
telah berubah, sehingga teknik khusus ini mungkin tidak bisa diterapkan lagi. YMMV.)Di sisi lain, jika kode Anda mencoba untuk produk panggilan
srand
secara manual , maka kecuali mereka menggunakan sesuatu yang banyak kali lebih baik dari hasilphp_combined_lcg
, Anda mungkin akan memiliki banyak lebih mudah waktu menebak nilai dan penyemaian lokal Anda generator dengan nomor yang benar. Kebanyakan orang yang secara manual meneleponsrand
juga tidak akan menyadari betapa mengerikannya ide ini, dan karenanya tidak mungkin menggunakan nilai yang lebih baik.Perlu dicatat bahwa
mt_rand
ini juga diderita oleh masalah yang sama. Pembibitanmt_srand
dengan nilai yang diketahui juga akan menghasilkan hasil yang dapat diprediksi. Mendasarkan entropi Andaopenssl_random_pseudo_bytes
mungkin adalah taruhan yang lebih aman.tl; dr: Untuk hasil terbaik, jangan menabur pembuat angka acak PHP, dan demi kebaikan, jangan memaparkan
uniqid
kepada pengguna. Melakukan salah satu atau keduanya ini dapat menyebabkan angka acak Anda lebih mudah ditebak.Pembaruan untuk PHP 7:
PHP 7.0 memperkenalkan
random_bytes
danrandom_int
sebagai fungsi inti. Mereka menggunakan implementasi sistem yang mendasari CSPRNG, membuat mereka bebas dari masalah yang dimiliki oleh generator nomor acak unggulan. Mereka mirip secara efektifopenssl_random_pseudo_bytes
, hanya tanpa memerlukan ekstensi untuk diinstal. Polyfill tersedia untuk PHP5 .*: Patch keamanan Suhosin mengubah perilaku
rand
danmt_rand
sedemikian rupa sehingga mereka selalu mengunggah setiap panggilan. Suhosin disediakan oleh pihak ketiga. Beberapa distribusi Linux memasukkannya ke dalam paket PHP resmi mereka secara default, sementara yang lain menjadikannya pilihan, dan yang lain mengabaikannya sama sekali.**: Bergantung pada platform dan panggilan pustaka yang mendasarinya sedang digunakan, urutan yang berbeda akan dihasilkan dari yang didokumentasikan di sini, tetapi hasilnya masih harus diulang kecuali patch Suhosin digunakan.
sumber
Untuk menggambarkan secara visual bagaimana non-acak
rand()
fungsi ini, berikut adalah gambar di mana semua piksel terbuat dari nilai-nilai merah, hijau dan biru "acak":Biasanya tidak ada pola dalam gambar.
Saya sudah mencoba menelepon
srand()
dengan nilai yang berbeda, itu tidak mengubah seberapa dapat diprediksi fungsi ini.Perhatikan bahwa keduanya tidak aman secara kriptografis dan menghasilkan hasil yang dapat diprediksi.
sumber
Ini adalah generator kongruensi linier . Itu berarti Anda memiliki fungsi yang efektif:
NEW_NUMBER = (A * OLD_NUMBER + B) MOD C
. Jika Anda memetakan NEW_NUMBER vs OLD_NUMBER Anda akan mulai melihat garis diagonal. Beberapa catatan pada dokumentasi RAND PHP memberikan contoh bagaimana melakukannya.Pada mesin windows, nilai maksimum RAND adalah 2 ^ 15. Ini memberi penyerang hanya 32.768 kemungkinan untuk diperiksa.
Meskipun artikel ini bukan yang Anda cari, artikel ini menunjukkan bagaimana beberapa peneliti mengambil implementasi generator nomor acak yang ada dan menggunakannya untuk menghasilkan uang di Texas Holdem. Ada 52! deck yang mungkin dikocok, tetapi implementasinya menggunakan generator angka acak 32-bit (yang merupakan jumlah maksimum dari mt_getrandmax pada mesin windows), dan diunggulkan dengan waktu dalam milidetik sejak tengah malam. Ini mengurangi jumlah deck yang mungkin dikocok dari sekitar 2 ^ 226 menjadi sekitar 2 ^ 27 sehingga memungkinkan untuk mencari secara real time dan tahu apa yang telah ditangani.
Saya akan merekomendasikan menggunakan sesuatu dalam keluarga SHA-2 karena FB menganggap md5 rusak. Beberapa orang menggunakan google untuk mendekripsi hash md5 karena mereka sangat umum. Hanya hash sesuatu kemudian melemparkan hash ke pencarian google - pada dasarnya google telah menjadi meja pelangi raksasa .
sumber
Benar-benar lebih akurat untuk mengatakan bahwa mengingat angka yang dihasilkan secara acak, yang berikutnya relatif dapat diprediksi. Hanya ada begitu banyak angka. Tetapi itu tidak berarti bahwa Anda dapat menebaknya, lebih dari itu Anda dapat menulis sebuah program yang dapat melakukannya, cukup cepat.
sumber