PHP के रैंड के उत्पादन की भविष्यवाणी करना ()


21

मैंने कई स्रोतों में पढ़ा है कि PHP के रैंड () का आउटपुट इसके PRNG के रूप में अनुमानित है, और मैं ज्यादातर इसे केवल इसलिए स्वीकार करता हूं क्योंकि मैंने इसे इतने सारे स्थानों पर देखा है।

मुझे एक प्रूफ-ऑफ-कॉन्सेप्ट में दिलचस्पी है: मैं रैंड () के आउटपुट की भविष्यवाणी करने के बारे में कैसे जाऊंगा? इस लेख को पढ़ने से मैं समझता हूं कि यादृच्छिक संख्या एक सूचक (बीज) पर शुरू होने वाली सूची से वापस लौटी संख्या है - लेकिन मैं कल्पना नहीं कर सकता कि यह कैसे पूर्वानुमान है।

क्या कोई व्यक्ति अनुमान लगा सकता है कि कुछ हज़ार अनुमानों के भीतर एक निश्चित समय में रैंड () के माध्यम से क्या यादृच्छिक # उत्पन्न किया गया था? या 10,000 अनुमान भी लगा सकते हैं? कैसे?

यह सामने आ रहा है क्योंकि मैंने एक ऐसी लाइब्रेरी देखी है जो पासवर्ड खो चुके उपयोगकर्ताओं के लिए टोकन बनाने के लिए रैंड () का उपयोग करती है, और मैंने माना कि यह एक संभावित सुरक्षा छेद था। जब से मैंने हैशिंग के साथ विधि को प्रतिस्थापित किया है openssl_random_pseudo_bytes(), ओरिगनल हैशेड पासवर्ड और माइक्रोटाइम। ऐसा करने के बाद मुझे एहसास हुआ कि अगर मैं बाहर की ओर देख रहा था, तो मुझे पता नहीं होगा कि टोकन का अनुमान कैसे लगाया जाए, यह जानते हुए भी कि यह रैंड का एक md5 था ()।


"लेकिन मैं कल्पना नहीं कर सकता कि यह कैसे पूर्वानुमान है"? आपको पहले " en.wikipedia.org/wiki/Linear_congruential_generator " पर पढ़ना होगा ताकि आप कल्पना कर सकें कि यह कैसे अनुमानित है। तब आप विस्मय को समाप्त करने के लिए अपने प्रश्न को संशोधित कर सकते हैं और रिवर्स इंजीनियरिंग PHP के अधिक व्यावहारिक मुद्दों पर जा सकते हैं। रैंड फ़ंक्शन स्रोत यह देखने के लिए कि यह कैसे काम करता है।
एस.लॉट

"मुझे लगता है कि यह एक संभावित सुरक्षा छेद था"? केवल अगर ईविल हैकर को कुछ उपयोगकर्ता का यादृच्छिक पासवर्ड मिल सकता है, तो मूल (प्री-हैश) मूल्य को पुनर्प्राप्त करने के लिए एमडी 5 हैश को पूर्ववत करने के लिए एक इंद्रधनुष तालिका का उपयोग करें और फिर गारंटी दें कि उन्होंने बहुत ही अगला पासवर्ड अनुरोध किया था। सैद्धांतिक रूप से संभव है, मुझे लगता है। लेकिन केवल अगर उनके पास एक यादृच्छिक संख्या के लिए एक कार्यशील इंद्रधनुष तालिका थी।
S.Lott

@ S.Lott - यह पासवर्ड की बात नहीं है। सिस्टम आपको पासवर्ड रीसेट करने देता है और आपको एक टोकन देता है जो एक URL में उपयोग किया जाता है। टोकन एमडी 5 (रैंड ()) के माध्यम से उत्पन्न होता है। यदि आप रैंड के उत्पादन की भविष्यवाणी कर सकते हैं () आप किसी के पासवर्ड को बदल सकते हैं, तो मूल के लिए हैश होने या मूल जानने के बिना।
एरिक

@Erik। सही। यदि "रैंडम टोकन" के साथ "यादृच्छिक पासवर्ड" को बदलें, यदि यह मदद करता है। टोकन का केवल तभी दुरुपयोग किया जा सकता है जब कोई व्यक्ति यादृच्छिक संख्या को पुनर्प्राप्त करने के लिए MD5 हैश को खोल सकता है और आश्वासन दे सकता है कि उन्हें अगला यादृच्छिक नंबर मिलेगा। अगले रैंड का पूर्वानुमान केवल एक छोटा सा हिस्सा है। एमडी 5 को खोलना कठिन हिस्सा है।
S.Lott

1
ध्यान दें कि MD5 (रैंड ()) में केवल रैंड () के समान सुरक्षा है। इसमें शामिल संख्याओं के बहुत सीमित सेट के लिए MD5 (रैंड ()) -> रैंड () का लुकअप टेबल बनाना व्यावहारिक है। रैंड () के सीमित डोमेन के साथ आप सरल जानवर बल की कोशिश कर सकते हैं जब तक कि बार-बार के प्रयासों को रोकने के लिए एक तंत्र न हो।
MZB

जवाबों:


28

से अगले मूल्य का अनुमान लगाने की क्षमता यह 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 जब srand1024 के साथ।

स्पष्ट होने के लिए, यह 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 पैकेजों में शामिल करते हैं, जबकि अन्य इसे एक विकल्प बनाते हैं, और अन्य इसे पूरी तरह से अनदेखा करते हैं।

**: प्लेटफ़ॉर्म और अंतर्निहित लाइब्रेरी कॉल का उपयोग करने पर निर्भर करता है, यहां दस्तावेज़ों की तुलना में अलग-अलग अनुक्रम उत्पन्न किए जाएंगे, लेकिन परिणाम तब तक दोहराए जाने चाहिए जब तक कि सुहोसिन पैच का उपयोग न किया जाए।


धन्यवाद चार्ल्स - आपके जवाब के बीच और Tangurena से रैखिक congruence जनरेटर पर लिंक पढ़ने के बीच मुझे लगता है कि मुझे इस पर बेहतर समझ है। मैं पहले से ही "जानता था" कि इस शैली में रैंड () का उपयोग करना एक बुरा विचार था, लेकिन मुझे पता है कि मैं क्यों जानता हूं ।
एरिक

वाह, एक पूरी तरह से अच्छी तरह से जवाब के लिए सहारा, धन्यवाद!
डेविड हॉब्स

10

यह स्पष्ट करने के लिए कि rand()फ़ंक्शन कितना गैर-यादृच्छिक है, यहां एक छवि है जहां सभी पिक्सेल "यादृच्छिक" लाल, हरे और नीले रंग से बने होते हैं:

यादृच्छिक RGB मान

आम तौर पर छवियों में कोई पैटर्न नहीं होना चाहिए।

मैंने srand()विभिन्न मूल्यों के साथ कॉल करने की कोशिश की है , यह नहीं बदलता है कि यह फ़ंक्शन कितना अनुमानित है।

ध्यान दें कि दोनों क्रिप्टोग्राफिक रूप से सुरक्षित नहीं हैं और अनुमानित परिणाम देते हैं।


7

PHP के रैंड () का आउटपुट इसके PRNG के रूप में अनुमानित है

यह एक रेखीय संयोजक जनरेटर है । इसका मतलब है कि आपके पास एक फ़ंक्शन है जो प्रभावी रूप से है NEW_NUMBER = (A * OLD_NUMBER + B) MOD C:। यदि आप NEW_NUMBER बनाम OLD_NUMBER चार्ट बनाते हैं, तो आपको विकर्ण रेखाएँ दिखाई देने लगेंगी। PHP के RAND डॉक्यूमेंटेशन के कुछ नोट्स ऐसा करने के तरीके का उदाहरण देते हैं।

यह सामने आ रहा है क्योंकि मैंने एक ऐसी लाइब्रेरी देखी है जो पासवर्ड खो चुके उपयोगकर्ताओं के लिए टोकन बनाने के लिए रैंड () का उपयोग करती है, और मैंने माना कि यह एक संभावित सुरक्षा छेद था।

एक विंडोज़ मशीन पर, RAND का अधिकतम मूल्य 2 ^ 15 है। इससे हमलावर को केवल 32,768 जांच करने की संभावनाएं मिलती हैं।

क्या कोई व्यक्ति अनुमान लगा सकता है कि कुछ हज़ार अनुमानों के भीतर एक निश्चित समय में रैंड () के माध्यम से क्या यादृच्छिक # उत्पन्न किया गया था? या 10,000 अनुमान भी लगा सकते हैं? कैसे?

हालांकि यह आलेख ठीक वैसा नहीं है जैसा आप खोज रहे हैं, यह दिखाता है कि कैसे कुछ शोधकर्ताओं ने एक यादृच्छिक संख्या जनरेटर के मौजूदा कार्यान्वयन को लिया और इसका इस्तेमाल टेक्सास होल्डम पर पैसा बनाने के लिए किया। 52 हैं! संभव फेरबदल डेक, लेकिन कार्यान्वयन एक 32-बिट यादृच्छिक संख्या जनरेटर (जो एक विंडोज़ मशीन पर mt_getrandmax से अधिकतम संख्या है) का इस्तेमाल किया, और आधी रात के बाद मिलीसेकंड में समय के साथ इसे वरीयता दी। इसने संभावित फेरबदल वाले डेक की संख्या को 2 ^ 226 से घटाकर लगभग 2 ^ 27 कर दिया, जिससे वास्तविक समय में खोज करना और यह पता चल सके कि किस डेक को निपटा दिया गया है।

ऐसा करने के बाद मुझे एहसास हुआ कि अगर मैं बाहर की ओर देख रहा था, तो मुझे पता नहीं होगा कि टोकन का अनुमान कैसे लगाया जाए, यह जानते हुए भी कि यह रैंड का एक md5 था ()।

मैं SHA-2 परिवार में कुछ का उपयोग करने की सलाह दूंगा क्योंकि फेड्स मानते हैं कि md5 टूटा हुआ है। कुछ लोग md5 हैश को डिक्रिप्ट करने के लिए Google का उपयोग करते हैं क्योंकि वे बहुत आम हैं। बस हैश कुछ है तो हैश को एक Google खोज में फेंक दें - मूल रूप से Google एक विशाल इंद्रधनुष तालिका बन गया है ।


1

यह कहना अधिक सटीक है कि एक बेतरतीब ढंग से उत्पन्न संख्या को देखते हुए, अगला एक अपेक्षाकृत पूर्वानुमानित है। केवल इतनी संख्या हो सकती है। लेकिन इसका मतलब यह नहीं है कि आप इसका अनुमान लगा सकते हैं, और अधिक यह कि आप एक प्रोग्राम लिख सकते हैं जो बहुत जल्दी करता है।


1
मुझे लगता है कि अगली संख्या पूरी तरह से नियतात्मक है। "अपेक्षाकृत" नहीं बल्कि बिल्कुल। छद्म यादृच्छिक संख्या जनरेटर के साथ मुद्दा यह है कि एक अनुक्रम सांख्यिकीय परीक्षण पारित करेगा। दो आसन्न संख्याएं, जबकि पूरी तरह से नियतात्मक हैं, वास्तविक यादृच्छिक संख्याओं के साथ आम में सांख्यिकीय गुण होंगे।
S.Lott

1
अगली संख्या पूरी तरह से नियतात्मक है। यही छद्म यादृच्छिक संख्या जनरेटर में "छद्म" का मतलब है। दूसरी ओर, यह निर्धारित करने के लिए आवश्यक जानकारी कि अगली संख्या व्यवहार में प्राप्त करना असंभव है।
रीन हेनरिक

@ एस.लॉट - मैं इस धारणा के तहत था कि कोई संख्या 2 ^ 32 संभावित आउटपुट में कई बार दिखाई दे सकती है और हर बार ऐसा प्रतीत होता है कि एक अलग संख्या हो सकती है। लेकिन एक्स का एक बीज दिया, वाई का एक परिणाम लौटाता है, अगला परिणाम हमेशा एक ही होगा। इस प्रकार, व्यवहार में, कुछ संख्याएं हो सकती हैं जो वाई का पालन करती हैं। हालांकि मैं गलत हो सकता हूं; यह वास्तव में PRNGs को देखने के बाद से एक लंबा समय है।
पीडीआर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.