से अगले मूल्य का अनुमान लगाने की क्षमता यह rand
निर्धारित करने में सक्षम है कि क्या srand
साथ बुलाया गया था। विशेष रूप से, पूर्वनिर्धारित संख्या के साथ बीजारोपण srand
पूर्वानुमेय आउटपुट में परिणाम करता है ! PHP इंटरेक्टिव प्रॉम्प्ट से:
[charles@charles-workstation ~]$ php -a
Interactive shell
php > srand(1024);
php > echo rand(1, 100);
97
php > echo rand(1, 100);
97
php > echo rand(1, 100);
39
php > echo rand(1, 100);
77
php > echo rand(1, 100);
93
php > srand(1024);
php > echo rand(1, 100);
97
php > echo rand(1, 100);
97
php > echo rand(1, 100);
39
php > echo rand(1, 100);
77
php > echo rand(1, 100);
93
php >
यह सिर्फ कुछ अस्थायी नहीं है। अधिकांश प्लेटफार्मों पर अधिकांश PHP संस्करण * ** अनुक्रम उत्पन्न करेगा 97, 97, 39, 77, 93 जब srand
1024 के साथ।
स्पष्ट होने के लिए, यह PHP के साथ कोई समस्या नहीं है, यह rand
स्वयं के कार्यान्वयन के साथ एक समस्या है। यही समस्या अन्य भाषाओं में भी दिखाई देती है, जो पर्ल (सहित) के समान (या समान) कार्यान्वयन का उपयोग करती हैं।
चाल यह है कि PHP के किसी भी संस्करण को srand
"अज्ञात" मान के साथ पूर्व-वरीयता दी जाएगी । ओह, लेकिन यह वास्तव में अज्ञात नहीं है । से ext/standard/php_rand.h
:
#define GENERATE_SEED() (((long) (time(0) * getpid())) ^ ((long) (1000000.0 * php_combined_lcg(TSRMLS_C))))
तो, यह कुछ गणित है time()
, पीआईडी, और परिणाम php_combined_lcg
, जो में परिभाषित किया गया है ext/standard/lcg.c
। मैं यहाँ c & p नहीं जा रहा हूँ, साथ ही, मेरी आँखें चमक उठीं और मैंने शिकार रोकने का फैसला किया।
Googling के एक बिट से पता चलता है कि PHP के अन्य क्षेत्रों में सर्वश्रेष्ठ यादृच्छिकता पीढ़ी गुण नहीं हैं , और php_combined_lcg
यहां बाहर खड़े होने के लिए कॉल करता है, विशेष रूप से विश्लेषण का यह बिट:
न केवल यह फ़ंक्शन ( gettimeofday
) हमें एक सटीक सर्वर टाइमस्टैम्प को एक रजत पट्टिका पर वापस सौंपता है, यह LCG आउटपुट में भी जोड़ता है यदि हम "अधिक एन्ट्रॉपी" (PHP के uniqid
) से अनुरोध करते हैं ।
हाँ ऐसा हैuniqid
। ऐसा लगता है कि मूल्य वह php_combined_lcg
है जो हम देखते हैं जब हम परिणामी हेक्स अंकों uniqid
को एक वास्तविक मूल्य पर सेट दूसरे तर्क के साथ कॉल करने के बाद देखते हैं ।
अब, हम कहाँ थे?
अरे हाँ। srand
।
इसलिए, यदि आप जिस कोड को कॉल नहीं करते हैं srand
, उससे यादृच्छिक मूल्यों की भविष्यवाणी करने की कोशिश कर रहे हैं , तो आपको php_combined_lcg
एक कॉल के माध्यम से, जो आप (अप्रत्यक्ष रूप से) प्राप्त कर सकते हैं, को प्रदान करने की आवश्यकता है uniqid
। हाथ में उस मूल्य के साथ, यह बाकी मूल्य - पीआईडी और कुछ गणित पर बल देने के लिए संभव है time()
। जुड़ा हुआ सुरक्षा मुद्दा ब्रेकिंग सेशन के बारे में है, लेकिन वही तकनीक यहां काम करेगी। फिर से, लेख से:
यहाँ ऊपर उल्लिखित हमले के चरणों का सारांश दिया गया है:
- सर्वर रिबूट करने के लिए प्रतीक्षा करें
- एक uniqid मूल्य प्राप्त करें
- जानवर इस से RNG बीज बल
- लक्ष्य के लिए प्रतीक्षा करने के लिए ऑनलाइन स्थिति प्रदूषित करें
- मौजूदा सर्वर समय और RNG मान का ट्रैक रखने के लिए अनइकिड पोल के साथ इंटरलेवे स्टेटस पोल
- मतदान में समय और RNG मान अंतराल का उपयोग कर सर्वर के खिलाफ जानवर बल सत्र आईडी
आवश्यकतानुसार उस अंतिम चरण को बदलें।
(यह सुरक्षा समस्या पहले के PHP संस्करण (5.3.2) में बताई गई थी, जो वर्तमान में हमारे पास (5.3.6) है, इसलिए यह संभव है कि uniqid
और / या php_combined_lcg
का व्यवहार बदल गया है, इसलिए यह विशिष्ट तकनीक किसी भी अधिक उपयोगी नहीं हो सकती है। YMMV।)
दूसरी ओर, यदि आप कोड उत्पाद की कोशिश कर रहे कॉल srand
मैन्युअल , तो जब तक वे के चलते उत्पन्न की तुलना में बेहतर उपयोग कर रहे हैं कई बार php_combined_lcg
, तो आप शायद जा रहे हैं एक बहुत है करने के लिए आसान समय मूल्य अनुमान लगा और अपने स्थानीय बोने सही संख्या के साथ जनरेटर। मैन्युअल रूप से कॉल करने वाले अधिकांश लोगों को यह srand
भी एहसास नहीं होगा कि यह एक विचार से कितना भयानक है, और इस प्रकार बेहतर मूल्यों का उपयोग करने की संभावना नहीं है।
यह ध्यान देने योग्य है कि mt_rand
एक ही समस्या से पीड़ित भी है। mt_srand
ज्ञात मूल्य के साथ सीडिंग भी अनुमानित परिणाम देगा। अपनी एन्ट्रापी को बंद openssl_random_pseudo_bytes
करना शायद एक सुरक्षित शर्त है।
tl; dr: सर्वोत्तम परिणामों के लिए, PHP रैंडम नंबर जनरेटर को सीड न करें, और अच्छाई के लिए, uniqid
उपयोगकर्ताओं को उजागर न करें । इन दोनों को करने से आपके रैंडम नंबर अधिक अनुमानित हो सकते हैं।
PHP 7 के लिए अपडेट करें:
PHP 7.0 परिचय random_bytes
और random_int
मुख्य कार्यों के रूप में। वे अंतर्निहित सिस्टम के CSPRNG कार्यान्वयन का उपयोग करते हैं, जिससे उन्हें उन समस्याओं से मुक्त किया जाता है जो एक क्रमबद्ध यादृच्छिक संख्या जनरेटर है। वे प्रभावी रूप से समान हैं openssl_random_pseudo_bytes
, केवल एक एक्सटेंशन की आवश्यकता के बिना स्थापित किया जाना है। एक पॉलीफ़िल PHP5 के लिए उपलब्ध है ।
*: सुहोसिन सुरक्षा पैच का व्यवहार बदलता है rand
और mt_rand
ऐसा होता है कि वे हमेशा हर कॉल के साथ फिर से बीजारोपण करते हैं। सुहोसिन एक तीसरी पार्टी द्वारा प्रदान किया जाता है। कुछ लिनक्स वितरण इसे डिफ़ॉल्ट रूप से अपने आधिकारिक PHP पैकेजों में शामिल करते हैं, जबकि अन्य इसे एक विकल्प बनाते हैं, और अन्य इसे पूरी तरह से अनदेखा करते हैं।
**: प्लेटफ़ॉर्म और अंतर्निहित लाइब्रेरी कॉल का उपयोग करने पर निर्भर करता है, यहां दस्तावेज़ों की तुलना में अलग-अलग अनुक्रम उत्पन्न किए जाएंगे, लेकिन परिणाम तब तक दोहराए जाने चाहिए जब तक कि सुहोसिन पैच का उपयोग न किया जाए।