Совет по безопасности: Увеличьте раунды bcrypt
В статье приводится предыстория, но если нужно только краткое изложение, пропустите её!
bcrypt — функция хэширования паролей, используемая для защиты паролей в базах данных, чтобы их не мог определить и использовать тот, кто получит доступ к исходному хэшу. В настоящее время она является алгоритмом хэширования по умолчанию как в Laravel, так и в самом PHP, и на момент написания статьи это самый безопасный вариант хэширования паролей.
Время от времени возникают разговоры о переходе на Argon2, и его часто продвигают как лучшую альтернативу bcrypt, однако в Argon2 есть некоторые фундаментальные недостатки, делающие его неподходящим для веб-приложений. Этот вопрос поднимался в моем PR и в рассылки PHP internals, а один из экспертов, участвовавших в выборе Argon2, публично заявил, что выбор его был ошибочным.
В качестве краткого обзора можно сказать, что хэширование паролей используется для защиты паролей при хранении на сервере или в базе данных. При вводе только что созданного пароля он передаётся в функцию хэширования, и полученный хэш сохраняется. Поскольку хэш является односторонней операцией, извлечь хэшированный пароль невозможно. Когда пользователь пытается войти в систему или требуется проверить пароль, исходное значение пароля, полученное при его вводе, хешируется, и два хеша сравниваются. Если хэши одинаковы, то и пароль должен быть одинаковым.
Хотя напрямую извлечь хэшированный пароль невозможно, его можно угадать перебором, генерируя миллионы/миллиарды паролей в секунду и сравнивая их с хэшем. Этот процесс позволяет взломать простые/известные пароли за несколько секунд. Более сложные пароли требуют больше времени, но с ростом вычислительной мощности время, необходимое для взлома паролей, уменьшается.
Поэтому по мере роста вычислительной мощности необходимо повышать безопасность хэширования паролей. Это достигается за счёт Раундов / Стоимости / Рабочего Фактора, которые эффективно замедляют работу функции хэширования. Таким образом, если на генерацию хэша пароля уходит больше времени, то и на перебор хэшей паролей уходит больше времени, а для достаточно сложного пароля этот перебор становится невыполнимым в любом реалистичном сценарии.
Поддержка хеширования паролей с помощью bcrypt появилась в PHP 11 лет назад и по умолчанию составляла 10 раундов. Аналогично, в Laravel по умолчанию используется bcrypt и 10 раундов. Однако как я только что упомянул, вычислительные мощности постоянно растут, и 10 раундов уже не считаются достаточными для хэширования паролей. В связи с этим в PHP существует открытый RFC, позволяющий повысить значение по умолчанию с 10 до 11 или 122, и чтобы последовать их примеру, мы сделали то же самое в Laravel, повысив значение по умолчанию до 12.
RFC прошёл, и 12 было выбрано в качестве нового значения раундов по умолчанию в PHP 8.4.
Итак... всё это для того, чтобы сказать, что мы увеличили количество раундов bcrypt по умолчанию с 10 до 12!
- Laravel skeleton PR: [10.x] Increase bcrypt rounds to 12 #6245
- Laravel framework PR: [10.x] Increase bcrypt rounds to 12 #48494
Поскольку это значение определено в файле config/hashing.php
, необходимо найти значение bcrypt.rounds
и изменить его на 12 с 10.
'bcrypt' => [
'rounds' => env('BCRYPT_ROUNDS', 12),
],
Вот и всё! 🙂
Хеши паролей обратно совместимы, и системы аутентификации должны быть настроены на автоматический перехеширование паролей при встрече со старыми хешами, чтобы исключить риск взлома.
Ещё немного теории: Мы выбрали 12 раундов, потому что, согласно бенчмаркам, генерация хэша всё ещё не достигает отметки 500 мс, после чего запросы, связанные с хэшированием, могут заметно замедлиться, и производительность системы может пострадать. Однако стоит отметить, что если вам требуется высокий уровень безопасности или у вас много ресурсов, вы можете увеличить количество раундов до 13+. Просто следите за влиянием производительности и выбирайте тот уровень, который вам подходит.
Обновление: Чтобы прояснить вопрос "почему именно сейчас?", следует сказать, что нам нужно быть проактивными в вопросах безопасности. С ростом вычислительных мощностей время вычисления хэша уменьшается, и тем легче становится перебирать хэши. OWASP рекомендует: "Как правило, вычисление хэша должно занимать менее одной секунды". Если совместить это с простыми бенчмарками, которые показывают, что на выполнение 10 раундов уходит менее 0,05 секунды, а на 12 — около 0,2-0,3 секунды, то преимущества в плане безопасности становятся очевидными.
- PHP 8.4: Стоимость Bcrypt по умолчанию изменена с 10 на 12
- Автоматическое перехэширование паролей в Laravel 11