Приветствую! На этой неделе мы отправимся в интересный и сложный мир механизм хэширования паролей, и рассмотрим очень простое изменение, которое Вы должны сделать в своих приложениях для повышения безопасности, основываясь на двух PR, которые я недавно отправил в Laravel.
Увеличьте количество проходов bcrypt
(Я привёл некоторые справочные данные. Пропустите их, если Вам нужна краткая информация)
bcrypt - это функция хэширования паролей, используемая для их защиты в базах данных чтобы их не смог использовать тот, кто получит доступ к исходному кэшу. В настоящее время bcrypt является алгоритмом шифрования по-умолчанию как в Laravel, так и в самом PHP, и на момент написания статьи является наиболее безопасным вариантом хэширования паролей.
В качестве краткого обзора можно сказать, что хэширование паролей используется для их защиты при сохранении на сервере или в базе данных. При вводе только что созданного пароля он передаётся в функцию хэширования сохраняя результат. Поскольку хэш является односторонней операцией, извлечь хэшированный пароль невозможно. Когда пользователь пытается войти в систему или требуется проверить пароль, исходное значение поля, полученное при его вводе, хэшируется, и два хэша сравниваются. Если хэши одинаковы, то и пароль должен быть одинаковым.
Несмотря на то что напрямую извлечь хэшированный пароль невозможно, его можно "угадать" при помощи брутфорса, генерируя миллионы/миллиарды паролей в секунду, сравнивая их с хэшем. Этот процесс позволяет взломать простые/известные пароли за несколько секунд. Более сложные пароли требуют больше времени, но с ростом вычислительной мощности время, необходимое для взлома паролей, уменьшается.
Поэтому по мере роста вычислительной мощности необходимо повышать безопасность хэширования паролей. Это достигается за счёт Rounds / Costs / Work Factor, которые эффективно замедляют работу функции хэширования. Таким образом, если для генерации хэша пароля требуется больше времени, то и для перебора потребуется больше времени, а для достаточно сложных паролей этот перебор становится невыполнимым в любом реалистичном сценарии.
Поддержка хэширования паролей с помощью bcrypt
была реализована в PHP 11 лет назад и начиналась с 10 проходов по-умолчанию. Аналогично и в Laravel используется 10 проходов bcrypt. Однако, как я уже говорил, вычислительные мощности растут и 10 проходов уже не считаются достаточными для обеспечения безопасности. В связи с этим, в PHP проводится опрос по RFC, рекомендующий повысить значение по-умолчанию с 10 до 11 или 12. И, следуя их примеру, мы сделали то же самое в Laravel, повысив стандартную версию до 12.
И это всё для того чтобы сказать об увеличении количество проходов bcrypt по-умолчанию с 10 до 12!
Laravel skeleton PR: https://github.com/laravel/laravel/pull/6245
Laravel framework PR: https://github.com/laravel/framework/pull/48494
Поскольку это значение определяется в файле config/hashing.php
, необходимо найти и заменить значение bcrypt.rounds
с 10 на 12:
'bcrypt' => [
'rounds' => env('BCRYPT_ROUNDS', 12),
],
И всё! ????
Хэши паролей обратно совместимы и системы аутентификации должны быть настроены на автоматическое перехэширование паролей при встрече со старыми версиями, чтобы исключить риск взлома.
Ещё немного теории: мы выбрали значение 12, поскольку, согласно бенчмаркам, генерация хэша всё ещё не достигает отметки в 500 мс, при которой связанные с хэшированием запросы могут заметно замедлиться, а производительность системы пострадать. Однако следует отметить, что если Вам требуется более высокий уровень безопасности или у Вас много ресурсов, то можно увеличить количество проходов до 13+. Просто следите за производительностью и выбирайте наиболее подходящее для Вас число.
Чтобы прояснить вопрос "почему именно сейчас?", следует отметить, что нам нужно быть проактивными в вопросах безопасности. С ростом вычислительных мощностей время вычисления хэша уменьшается и тем проще становится их перебор. OWASP рекомендует: "как правило, вычисление хэша должно занимать менее одной секунды". В сочетании с простыми бенчмарками, показывающими менее 0.05 секунды за 10 проходов, выполнение 12 проходов за 0.2-0.3 секунды является показателем преимущества в плане безопасности.
FanatPHP
Через год и дефолтное значение подтянется PHP RFC: Increasing the default BCrypt cost (непонятно, почему в 8.3 не попало)
arokettu
Потому что голосование по RFC должно заканчиваться до первого RC релиза в который оно должно попасть
SerafimArts
С другой стороны bcrypt/blowfish уже считается относительно устаревшим (PHP 7.2+) в пользу актуального на данный момент argon.