Я читал в многочисленных источниках, что вывод PHP rand () предсказуем как PRNG, и я в основном принимаю это как факт просто потому, что видел его во многих местах.
Я заинтересован в проверке концепции: как бы я мог предсказать вывод rand ()? Прочитав эту статью, я понимаю, что случайное число - это число, возвращаемое из списка, начинающегося с указателя (начального числа), - но я не могу представить, насколько это предсказуемо.
Может ли кто-нибудь разумно выяснить, какой случайный # был сгенерирован с помощью rand () в данный момент времени в течение нескольких тысяч предположений? или даже 10000 догадок? Как?
Это происходит потому, что я увидел библиотеку аутентификации, которая использует rand () для создания токена для пользователей, которые потеряли пароли, и я предположил, что это потенциальная дыра в безопасности. С тех пор я заменил метод хэшированием смеси openssl_random_pseudo_bytes()
, оригинального хэшированного пароля и микротайма. После этого я понял, что если бы я смотрел снаружи, я бы не знал, как угадать токен, даже зная, что это md5 из rand ().
Ответы:
Способность угадать следующее значение
rand
зависит от способности определять, чтоsrand
вызывалось. В частности, посевsrand
с заданным числом приводит к предсказуемому результату ! Из интерактивной подсказки PHP:Это не просто случайность. Большинство версий PHP * на большинстве платформ ** будут генерировать последовательность 97, 97, 39, 77, 93, когда
srand
с 1024.Чтобы было ясно, это не проблема с PHP, это проблема с его реализацией
rand
. Та же проблема возникает в других языках, которые используют ту же (или похожую) реализацию, включая Perl.Хитрость в том, что любая здравомыслящая версия PHP будет предварительно заполнена
srand
«неизвестным» значением. О, но это не совсем неизвестно. Отext/standard/php_rand.h
:Итак, это некоторая математика с
time()
, PID и результатphp_combined_lcg
, который определен вext/standard/lcg.c
. Я не собираюсь заходить сюда, так как мои глаза застеклены, и я решил прекратить охоту.Немного Googling показывает, что другие области PHP не обладают лучшими свойствами генерации случайности , и призывает
php_combined_lcg
выделиться здесь, особенно этот фрагмент анализа:Да, это
uniqid
. Кажется, что значениеphp_combined_lcg
- это то, что мы видим, когда смотрим на полученные шестнадцатеричные цифры после вызоваuniqid
со вторым аргументом, установленным в истинное значение.Теперь, где мы были?
О да.
srand
,Итак, если код, из которого вы пытаетесь предсказать случайные значения , не вызывает
srand
, вам нужно будет определить значениеphp_combined_lcg
, которое вы можете получить (косвенно?) Через вызовuniqid
. С этим значением в руке, это возможно , чтобы перебор остальных значений -time()
, то PID и некоторые математики. Связанная проблема безопасности связана с прерыванием сеансов, но здесь будет работать та же техника. Опять же из статьи:Просто замените этот последний шаг, как требуется.
(Об этой проблеме безопасности сообщалось в более ранней версии 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
, только без необходимости установки расширения. Polyfill доступен для PHP5 .*: Исправление безопасности Suhosin изменяет поведение
rand
и такmt_rand
, что они всегда появляются заново при каждом вызове. Suhosin предоставляется третьей стороной. Некоторые дистрибутивы Linux включают его в свои официальные пакеты PHP по умолчанию, в то время как другие делают это опцией, а другие полностью ее игнорируют.**: В зависимости от платформы и используемых библиотечных вызовов будут генерироваться последовательности, отличные от задокументированных здесь, но результаты должны быть повторяемыми, если не используется исправление Suhosin.
источник
Чтобы наглядно проиллюстрировать неслучайную
rand()
функцию, вот изображение, где все пиксели сделаны из «случайных» значений красного, зеленого и синего:Обычно на изображениях не должно быть рисунков.
Я пробовал вызывать
srand()
с разными значениями, это не меняет предсказуемость этой функции.Обратите внимание, что оба они не криптографически безопасны и дают предсказуемые результаты.
источник
Это линейный генератор конгруэнтности . Это означает , что у вас есть функция, которая эффективно:
NEW_NUMBER = (A * OLD_NUMBER + B) MOD C
. Если вы построите график NEW_NUMBER против OLD_NUMBER, вы начнете видеть диагональные линии. В некоторых примечаниях к документации RAND PHP приведены примеры того, как это сделать.На Windows-машине максимальное значение RAND составляет 2 ^ 15. Это дает атакующему только 32 768 возможностей для проверки.
Хотя эта статья не совсем та, которую вы ищете, она показывает, как некоторые исследователи взяли существующую реализацию генератора случайных чисел и использовали ее для заработка на Техасском Холдеме. Есть 52! возможны перемешанные колоды, но реализация использовала 32-битный генератор случайных чисел (который является максимальным числом из mt_getrandmax на машине с Windows), и затравил его временем в миллисекундах с полуночи. Это уменьшило число возможных перетасованных колод с примерно 2 226 до примерно 2 27, что позволило осуществлять поиск в реальном времени и знать, какая колода была сдана.
Я бы порекомендовал использовать что-то в семействе SHA-2, так как федералы считают md5 неработающим. Некоторые люди используют Google для расшифровки хэшей md5, потому что они очень распространены. Просто зашифруйте что-нибудь, а затем добавьте хеш в поиск Google - в основном Google превратился в гигантскую радужную таблицу .
источник
Действительно точнее сказать, что с учетом случайно сгенерированного числа следующее относительно предсказуемо. Там может быть только так много цифр. Но это не значит, что вы можете догадаться об этом, более того, вы можете написать программу, которая делает это довольно быстро.
источник