×
Закрытие
8
×

Дополнительные материалы бесплатно предоставляются только зарегистрированным пользователям.

Для скачивания исходных файлов необходимо авторизоваться под своим аккаунтом через соответствующую форму.

Для тех кто не зарегистрирован, можно это сделать на вкладке Регистрация.

Статья сборника Как установить графический редактор GIMP

Перейти к статье

Устанавливаем графический редактор GIMP

  1. Выбор графического редактора
  2. Устанавливаем программу GIMP
  3. Устанавливаем Руководство пользователя

Здравствуйте уважаемый посетитель!

При создании и развитии сайта не обойтись без графического редактора. Этот инструмент необходим для формирования и обработки различных графических элементов, без которых сайт попросту не сможет существовать. Поэтому в наборе инструментов вебмастера графический редактор занимает важнейшее место.

В статье Устанавливаем бесплатный графический редактор GIMP речь пойдет о бесплатной программе GIMP, которая позволяет в полной мере решать вопросы по созданию элементов дизайна веб-страниц. И будет показано, как ее установить на локальный компьютер.

Кроме того здесь можно будет посмотреть, как в этот редактор добавить встроенное "Руководство пользователя", а также приведен бесплатный видеокурс, где можно поближе с ним познакомиться.

Для тех же, кто хочет заниматься дизайном на платном Adobe Photoshop (фотошоп), здесь также упомянут и такой вариант, основанный на использовании продления льготного бесплатного периода фотошопа на неопределенное время...

    Cайт на практическом примере

    Текущее состояние создаваемого сайта

    Здесь можно посмотреть текущее состояние сайта, создаваемого в рамках цикла статей Самописный сайт с нуля своими руками.

    Исходные файлы данного сайта можно скачать из прилагаемых к статьям дополнительных материалов.

    Вы здесь: Главная → Сборник статей → Формы → Хеширование паролей php


    Автор: / Дата:

    Хешируем пароли в PHP

    Здравствуйте, уважаемый посетитель!

    В предыдущей статье при отправке данных из формы для защиты пароля от взлома мы применили специальное односторонне преобразование (хеширование).

    В результате, из сравнительно простого пароля, состоящего из 6-ти цифр и букв латинского алфавита, получили довольно сложную комбинацию из 60 символов. И которую, в конечном итоге, сохранили в базе данных в качестве одного из параметров созданной учетной записи пользователя.

    Как ранее было отмечено, хеширование это важнейший элемент защиты такой конфиденциальной информации, как пароль. Поэтому в данной статье будет уделено отдельное внимание этому вопросу.

    В частности, будут даны пояснения в необходимости хеширования паролей и рассмотрены методы, которые позволят существенно усилить защиту паролей от несанкционированного восстановления.

    А в следующей статье рассмотрим на практических примерах использование специальных криптографических функций, применение которых может обеспечить создание хешей паролей с сильными, необратимыми алгоритмами хеширования.

    Содержание


    • Зачем нужно хешировать пароли
    • Вскрываем пароль при слабо защищенном хеше
    • Защищаемся от 'грубой силы' замедляя хеш-функцию
    • Усложняем хеш добавляя 'соль'
    • Исходные файлы сайта

    Зачем нужно хешировать пароли


    Наверное нельзя не согласиться с тем, что в наше время никто не застрахован от взлома серверов баз данных. По крайней мере, нам приходится очень часто слышать в новостях, что взломана какая-то очередная база, содержащая данные десятков, сотен тысяч, а то и миллионов пользователей.

    И понятно, что в случае утечки таких конфиденциальных данных, как пароли учетных записей, могут возникнуть серьезные проблемы в работе ресурса, с которого они были украдены.

    Но кроме этого, для тех пользователей, которые используют не уникальные пароли, а повторяют их при работе с разными интернет-ресурсами, овладение хакерами этой информацией может привести к другим очень серьезным последствиям. Например, в случае использования таких аккаунтов для работы с онлайн банками и другими подобными приложениями, возможно столкнуться с существенными финансовыми потерями.

    Поэтому, чтобы исключить, или по крайней мере, значительно усложнить использование злоумышленниками ворованных данных о паролях, применяется хеширование, которое превращают любое количество знаков в пароле в шифрованную комбинацию символов фиксированной длины.

    При этом такое преобразование является односторонним, что исключает возможность непосредственного обратного преобразования хеша в исходную комбинацию.

    Но, как говорится, против лома нет приема. Поэтому определенные индивидуумы нашли и успешно применяют другие методы восстановления пароля. Например, может быт быть использован полный перебор всевозможных вариантов (метод "грубой силы", англ. brute force). Который при хорошей вычислительной мощности оборудования в ряде случаев может оказаться очень эффективным средством.

    Возможно также применение и атак "по словарю", предусматривающих проверку наиболее часто используемых вариантов пароля. Как правило, этот метод базируется на том, что люди часто создают пароль на основе осмысленного слова и некоторых простых правилах его преобразования. Что позволяет в этом случае значительно упростить вычисления для значительного количества существующих паролей.

    Для эффективности поиска могут применяться и другие массивы данных с заранее вычисленными парами пароль-хэш, так называемыми "радужные" таблицы. В общем, злоумышленники обладают достаточным количеством всевозможных инструментов для совершения своих грязных дел. И к этому нужно быть готовым.

    Поскольку темой данной статьи является защита паролей, а не рассмотрение вопросов их взлома, то мы не будем здесь подробно заниматься различными хакерскими методиками. А более плотно займемся рассмотрением способов, которые напротив позволят более надежно защитить наши данные от несанкционированных воздействий.

    Надо отметить, что в настоящее время тема кибер безопасности стала довольно избитой. Одни американские выборы чего стоят. И вполне возможно, что у некоторых посетителей может сложиться впечатление, что автор здесь гонит очередные хакерские страшилки.

    И вот для того, чтобы это опровергнуть, дальше проведем небольшой эксперимент. И посмотрим, к чему может привести легкомысленное отношение к защите персональных данных, когда применяются не соответствующие методы хеширования паролей.

    А если все же кто-то сомневается в необходимости серьезного отношения к этому вопросу, с дополнительной информацией по этой теме можно ознакомиться из других источников. Например, хорошие разъяснения по вопросам безопасного применения хеширования паролей, с достаточно кратким и понятным изложением рекомендаций, можно найти в этом разделе онлайн справочника по PHP.

    скриншот 37

    Вскрываем пароль при слабо защищенном хеше


    Для того, чтобы убедиться, что слабо защищенный пароль легко вскрыть, проведем небольшую проверку возможности восстановления исходного пароля из хеша, которую проведем в два этапа:

    • Сначала получим хеш какой-нибудь комбинации символов. Например, возьмем вариант, который мы использовали в предыдущей статье при создании пароля для нового пользователя, в виде Z5nC89. В котором применены как цифры, так и буквы латинского алфавита обоих регистров.
    • А затем, используя специальные инструменты, попробуем из хеша восстановить исходный пароль. При этом средствами взлома могут выступать как специальные программы, так различные, специализирующие на этом, онлайн сервисы.

    Сразу отметим, что проверку возможности вскрытия пароля будем проводить на слабо защищенном хеше, сформированном с помощью одного их алгоритмов, которые в настоящее время сами по себе не могут обеспечить надежную защиту данных.

    Это касается в основном таких хеширующих алгоритмов как MD5, SHA1 и т.п. Несмотря на то, что многие профессионалы в сфере информационной безопасности достаточно давно уже не рекомендуют их использовать для хеширования паролей, все-равно и сейчас применение таких функций остается достаточно популярным.

    Низкая защищенность подобных алгоритмов обусловлена в основном тем, что в свое время такие методы шифрования были спроектированы с очень высокой скоростью вычислений. И сегодня при наличии современных технологий и оборудования, при их выполнении стало довольно просто получать нужный результат методом полного перебора возможных вариантов.

    Таким образом, для нашего примера воспользуемся наиболее известным из них, алгоритмом хеширования MD5. Причем при формировании хеш-кода будем использовать только непосредственные возможности соответствующей функции без добавления каких-либо дополнительных мер по усложнению преобразований. Этим мы займемся позднее при рассмотрении способов повышения защищенности данных.

    Итак, приступим. В PHP для вычисления MD5-хэша обычно используют встроенную функцию "md5()", обязательным параметром которой является строковая переменная, соответствующая исходной комбинации.

    Для нашего примера получить такой хеш можно следующим образом. (Здесь и в последующих примерах, строки кода, непосредственно относящиеся к получению хеша будут выделены светлым фоном, вспомогательные, включая, участвующие в выводе результатов вычислений - более темным).

    1. //Получение MD5-хеша с помощью функции md5()

    2. $password = 'Z5nC89';

    3. $hash = md5($password);

    4. echo nl2br('MD5: пароль - '.$password.', хеш - '.$hash."\n");

    5. ?>

    Рис.1 Получение MD5-хэша с помощью функции md5()

    Функция echo nl2br (поз.5) здесь добавлена для контроля полученного результата с помощью вывода значения переменных $password и $hash на страницу сайта.

    Следует отметить, что MD5-хэш можно получить и другим способом, использовав для этого универсальную функцию генерирования хеш-кода "hash()", которая позволяет вычислять хеши различными методами. Для этого нужно лишь в качестве первого параметра указать имя используемого алгоритма.

    В данном случае такой вариант можно представить следующим кодом, заменив предыдущую функцию md5() на hash().

    1. //Получение MD5-хэша с помощью функции hash()

    2. $password = 'Z5nC89';

    3. $hash = hash('md5', $password);

    4. echo nl2br('MD5: пароль - '.$password.', хеш - '.$hash."\n");

    5. ?>

    Рис.2 Получение MD5-хэша с помощью функции hash()

    После того, как мы определились с необходимыми для вычисления функциями, временно выведем полученный результат в какое-нибудь место на сайте, например, на главную страницу. Для чего поместим PHP-код одного из приведенных здесь вариантов в конец файла "main.php", находящегося в папке "articles" корневого каталога.

    В итоге, после обновления главной страницы, в нижней части ее мы должны увидеть MD5-хеш, соответствующий заданному паролю Z5nC89, как показано на скриншоте.

    Получение из пароля MD5-хеш

    Рис.3 Получение из пароля MD5-хеш

    Таким образом мы получили следующее значение хеша: eba7e0c49c4f93cada50dd7803de8f6e.

    А теперь перейдем ко второму этапу и попытаемся с помощью определенных инструментов восстановить из хеша исходный пароль. Начнем с самого простого способа, каким является онлайн сервис.

    Воспользуемся, к примеру, одним из старейших сервисов для расшифровки хешей CMD5, владеющим одной из самых больших баз данных и предлагающим свои услуги на восстановление разных видов хеш-кодов (SHA1, 32 bit MD5, MD4, mysql и т.д.).

    скриншот 35

    Для этого скопируем в соответствующее поле ранее полученный хеш и запустим кнопкой "Искать" выполнение необходимого преобразования.

    Восстановление пароля из MD5-хеша

    Рис.4 Восстановление пароля из MD5-хеша

    Как видно, без каких-либо усилий, мы сразу получили исходную комбинацию символов Z5nC89. Причем для данного варианта сделали это совершенно бесплатно, затратив на это ничтожно малое время в пределах всего одной секунды.

    Этот пример наглядно показывает, что использовать для хеширования паролей алгоритм MD5, не применяя при этом никаких дополнительных мер усложнения вычислений, весьма легкомысленно.

    Так как делает такие важные конфиденциальные данные просто беззащитными перед злоумышленниками. Которые с удивительной легкостью могут вскрываться даже такими средствами, как онлайн сервисы, не говоря уже о других более серьезных инструментах взлома.

    Поэтому дальше мы рассмотрим способы, которые позволяют в большой степени усложнить хешы паролей, и сделать их довольно сложными для взлома даже при использовании функций, не совсем подходящих для этих целей. В данном случае для примера будем использовать MD5-функцию.

    Защищаемся от 'грубой силы' замедляя хеш-функцию


    Как ранее было сказано, применение алгоритмов, которые имеют высокую скорость вычислений, приводит к тому, что при наличии хорошей вычислительной мощности оборудования, стало довольно просто получать исходные пароли с помощью "грубой силы", используя полный перебор возможных вариантов.

    Если конкретнее, то попробуем подсчитать, сколько времени понадобится для восстановления пароля из хеша, созданного с помощью MD5-функции на обычном пользовательском компьютере.

    Возьмем, к примеру, тот же пароль с длиной в шесть символов Z5nC89. Перебрав в таком варианте пароля все возможные символы (0-9, a-z, A-Z, всего 62 символа), получим 56`800`235`584 хешей (62 символа в 6-ой степени).

    Таким образом, нетрудно подсчитать, что при переборе всех возможных вариантов такого 6-ти символьного пароля на простом обычном компьютере, скажем, со скоростью обработки в районе одного миллиона хешей в секунду, понадобиться менее одного дня (56`800`235`584 / 1`000`000 ≈ 56`800 сек. ≈ 20 час.).

    А что говорить, если для этих целей применить другое более производительное оборудование, позволяющее обрабатывать миллиарды операций в секунду. В таких случаях подобная задача может бы быть решена вообще за считанные секунды.

    При более сложном пароле, например, при использовании восьми символов, на машине с одним миллиардом операций в секунду можно обработать массив из 218 триллионов хешей (62 символа в 8-ой степени) за время не более 60 часов. Что тоже вполне реально.

    Для повышения защиты паролей можно, конечно, с помощью определенных шаблонов заставить пользователей вводить довольно сложные комбинации с большим количеством символов. Но не исключено, что при таком подходе некоторые пользователи не станут заморачиваться и просто не будут регистрироваться, либо вообще уйдут с такого ресурса.

    Поэтому, чтобы усложнять жизнь не пользователям, а хакерам, которые для совершения своих дел используют метод полного перебора, применяется способ замедления хеш-функций. При котором время, необходимое на выполнение операции хеширования, увеличивается на определенную величину, достаточную для того, чтобы такой метод стал слишком затратными как по времени, так и по стоимости используемого оборудования.

    Исходя из этого, для защиты от взлома "грубой силы" полученного в предыдущем примере хеш-кода, увеличим время выполнения такого преобразования, скажем в пятьсот тысяч раз. Соответствующий такой операции PHP-код показан в следующей таблице.

    1. //Вычисление хэша с замедлением MD5-функции

    2. $password = 'Z5nC89';

    3. $start_time = microtime(true);

    4. $hash = md5($password);

    5. for ($i = 0; $i < 500000; $i++) {

    6. $hash = md5($hash);

    7. }

    8. $delta_time = microtime(true) - $start_time;

    9. $cash_time = round($delta_time * 1000000, 0).'мкс.';

    10. echo nl2br('MD5: пароль - '.$password.', хеш - '.$hash.', время вычисления - '.$cash_time."\n");

    11. ?>

    Рис.5 Вычисление хеша с замедлением MD5-функции

    Как видно, здесь к полученному MD5-хешу (поз.5), с помощью конструкции цикла for (поз.6) добавлено выполнение еще 500`000 аналогичных повторных операций (поз.7).

    При этом, для того, чтобы определить реальное время, затраченное на получение результата, включено еще три вспомогательные строки кода.

    Сначала с помощью функции microtime() переменной $start_time присваивается отметка времени начала выполнения преобразования (поз.4). Которое соответствует количеству секунд, прошедших с начала, так называемой, Эпохи Unix (1 января 1970 0:00:00 GMT).

    А затем, с помощью получения разности значений меток времени до и после преобразований в виде $delta_time (поз.9) и округления этого значения с помощью функции round(), умноженного на 1`000`000, получается реальное время получения хеша в микросекундах (поз.10).

    После вышеуказанных дополнений снова обновим главную страницу и посмотрим на результат.

    Результат замедления MD5-функции

    Рис.6 Результат замедления MD5-функции

    Как видно, в этом случае время получения одного хеша на используемом в этом примере оборудования составило 270`437 мкс (примерно одна треть секунды). Что означает, что в одну секунду при таких параметрах может быть выполнено не более 3 вычислений.

    Очевидно, что при данной скорости обработки, невозможно в реальности на таком железе перебрать все комбинации. Ведь для этого потребуются сотни лет (56`800`235`584 / 3 / 60 / 60 / 24 / 365 ≈ 600 лет).

    А на более производительном оборудовании, скажем в тысячу, для этого случая понадобится до полугода непрерывной работы. И понятно, что здравомыслящий человек этим тоже заниматься не будет.

    Для сравнения, нетрудно подсчитать, что время разового выполнения MD5-функции для данного примера составляет менее одной микросекунды (270`437 / 500`000 = 0.54 мкс).

    Поэтому, если бы мы не уменьшили скорость обработки, то на таком же оборудовании можно было бы перебрать все варианты всего за несколько часов (56`800`235`584 / 2`000`000 / 60 / 60 / 24 / 365 ≈ 9 часов), что вполне реально. Как говорится, результат налицо.

    Стоит отметить, что величина времени выполнения хеш-функции выбирается с учетом разумной достаточности. Очевидно, что задав время в пределах 100÷300 миллисекунд, пользователь при отправке формы даже это и не заметит. Но зато как это плодотворно скажется на защите от атак "грубой силы" злоумышленников.

    Усложняем хеш добавляя 'соль'


    В предыдущем разделе мы рассмотрели способ защиты от "грубой силы". Теперь же попробуем защититься от методов вскрытия паролей, основанных на поиске по заготовленным массивам пар пароль-хэш, с использованием упомянутых ранее "радужных" таблиц.

    И чтобы максимально затруднить работу хакеров, в этом случае будем при вычислении хеша добавлять к исходному паролю дополнительные данные, так называемую "соль".

    Суть в том, что при таком дополнении используя готовые таблицы будет невозможно найти исходный пароль по таким модифицированным хешам. Ведь готовых таблиц для таких данных в природе просто не существует. И атакующему придётся создать огромное количество отдельных "радужных таблиц", что, практически трудно выполнимо.

    Весь процесс этих преобразований можно представить в несколько действий.

    При сохранении пароля:

    • формируем соль из случайной последовательности, полученной с помощью криптографического генератора псевдослучайных чисел;
    • смешиваем соль с паролем и вычисляем хеш с помощью хеш-функции;
    • присоединяем соль к полученному хешу и сохраняем результирующий хеш-код вместе с "солью" в базе данных пользователей.

    При проверке пароля:

    • Извлекаем по отдельности соль и хеш из сохраненного ранее в базе данных результирующего хеш-кода;
    • смешиваем соль с вновь введенным паролем и вычисляем хеш-код с помощью хеш-функции с учетом заданного количества интераций (повторное многократное применение обработки данных), которые были применены для замедления функции на этапе сохранения пароля;
    • сравниваем хеш введенного пароля с хешем, полученным из базы данных. При совпадении - пароль введен правильно. При не совпадении - пароль не верен.

    И для того, чтобы посмотреть, как это выглядит на практике, приведем наш ранее сформированный PHP-код получения MD5-хеша к следующему виду.

    1. //Добавление соли в MD5-хэш

    2. $password = 'Z5nC89';

    3. $start_time = microtime(true);

    4. $salt = substr(sha1(mt_rand()),6,16);

    5. $mod_pass = $salt.$password;

    6. $hash = md5($mod_pass);

    7. for ($i = 0; $i < 500000; $i++) {

    8. $hash = md5($hash);

    9. }

    10. $hash = $salt.$hash;

    11. $delta_time = microtime(true) - $start_time;

    12. $cash_time = round($delta_time * 1000000, 0).'мкс.';

    13. echo nl2br('MD5: пароль - '.$password.', соль - '.$salt.', хеш - '.$hash.', время вычисления - '.$cash_time."\n");

    14. ?>

    Рис.7 Добавление соли в MD5-хэш

    Здесь для получения соли используется вариант, при котором сначала с помощью функции mt_rand() генерируется случайное число с дальнейшем получением из него sha1-хэша виде 40-символьного шестнадцатеричного числа. А затем после извлечения функцией substr() строки, начинающейся с шестой позиции sha1-хэша и длиной в 16 символов, образуется 16-символьная соль в виде переменной $salt (поз.5). Чуть позже будет понятно, почему для этого случая мы выбрали такую длину соли.

    А далее, полученная соль смешивается с паролем, образуя значение переменной $mod_pass (поз.6), которое в дальнейшем будет использовано для вычисления хеша (поз.7).

    Для замедления MD5-функции здесь также с помощью цикла for (поз.8) применяется цикличные повторные вычисления, образующие хеш $hash (поз.9) с заданным замедлением, соответствующим 500`000 циклов.

    Окончательное формирование результирующего хеш-кода происходит путем сложения соли с хешем, полученным на выходе цикла (поз.11).

    Таким образом после выполнения всех этих преобразований должен получиться хеш, состоящий не из 32-ух, а уже из 48-ми символов. Причем первая его часть из 16 символов будет представлять соль, а вторая - хеш, полученный из пароля, смешанного с солью и с прогонкой через MD5-функцию 500`000 раз.

    После внесенных дополнений снова обновим станицу и посмотрим, так ли это.

    Получение хеша с добавленной солью

    Рис.8 Получение хеша с добавленной "солью"

    Как видно, результат подтвердил ранее сказанное. На выходе мы получили 48-символьный результирующий хеш-код. Который образован с использованием 16-ти символьной соли. Но к этому нужно добавить еще очень важный момент.

    Дело в том, что мы получили хеш-код с замедленной MD5-функцией и с добавлением соли, используя для этого специально созданный PHP-скрипт. Поэтому, для того, чтобы иметь хоть какие-то шансы на взлом таких хешей, необходимо не только получить их из базы данных, но и взломать непосредственно файлы сайта и разобраться с заданным в них алгоритмом преобразований.

    В противном случае, не зная алгоритма, владея только хешами из базы данных, невозможно знать что использовано для замедления функции, каково количество интераций, в каком месте результирующего хеш-кода добавлена соль. А при определенных условиях невозможно вообще понять какая функция была использована при хешировании.

    Например, в приведенном примере сознательно была использована соль с длиной в 16 символов. И в итоге мы получили результирующий хеш-код в 48 символов, который по количеству и типу символов полностью повторяет хеш, образованный в результате выполнения другой криптографической хеш-функции типа Тiger/192. Ниже показаны вариант кода и результат вычисления такого хеша.

    1. //Получение MD5-хэша с помощью функции hash()

    2. $password = 'Z5nC89';

    3. $hash = hash('tiger192,3', $password);

    4. echo nl2br('MD5: пароль - '.$password.', хеш - '.$hash."\n");

    5. ?>

    Рис.9 PHP-код получения хэша по алгоритму Тiger/192

    Результат получения хеша с помощью функции tiger/192

    Рис.10 Результат получения хеша с помощью функции tiger/192

    Как видно хеш, сформированный с применением алгоритма Tiger/192 по виду ничем не отличается от ране полученного нами MD5-хеша с добавленной солью.

    Вот и поди разберись, не зная алгоритма преобразования, с помощью каких функций получены эти хеши. А при желании, можно применить и другие нестандартные решения, чем еще больше запутать взломщиков.

    Таким образом на примере обычной MD5-функции мы рассмотрели возможные механизмы, применение которых позволяет существенно повысить защиту паролей от несанкционированного восстановления. Где получили хеш, для взлома которого прийдется очень и очень потрудиться.

    А если соотнести стоимости затрат, которые для этого могут потребоваться, к величине возможной выгоды в случае успешного вскрытия паролей, не исключено, что перед тем как начать, многие подумают, а стоит ли с этим вообще связываться.

    В следующей статье рассмотрим другие варианты хеширования с использованием функций, специально предназначенные для этих целей. Которые достаточно просто, без необходимости использования каких-либо дополнительных преобразований, позволяют создавать хорошо защищенные хеши паролей с необратимыми алгоритмами хеширования.

    Исходные файлы сайта


    Знак папкиИсходные файлы сайта с обновлениями, которые были сделаны в данной статье, можно скачать из прилагаемых дополнительных материалов:

    • Файлы каталога www
    • Таблицы базы данных MySQL

    При этом, временно сформированные в данной статье PHP-скрипты, размещенные в файле "main.php" папки "articles" корневого каталога, закомментированы. Для проверки рассмотренных здесь примеров, следует раскомментировать соответствующие фрагменты кода.

    Дополнительные материалы бесплатно предоставляются только зарегистрированным пользователям.

    Для скачивания исходных файлов необходимо авторизоваться под своим аккаунтом через соответствующую форму.

    Для тех кто не зарегистрирован, можно это сделать на вкладке Регистрация.

    С уважением,


    Комментарии


    Если у Вас возникли вопросы, или есть какие-либо пожелания по представлению материала, либо заметили какие-нибудь ошибки, а быть может просто хотите выразить свое мнение, пожалуйста, оставьте свои комментарии. Такая обратная связь очень важна для возможности учета мнения посетителей.

    Буду Вам за это очень признателен!