Я что-нибудь пропустил? Есть ли какие-то дополнительные действия по хранению паролей к БД?
Сохранение пароля:
Проведя как можно больше исследований по этому вопросу, я пришел к выводу, что лучший способ хранить пароли пользователей в БД веб-приложений (в моем случае MySQL + PHP) выглядит следующим образом:
- Назначьте статическую соль по всему сайту. (16 случайных символов, включая 0-9, a-z, A-Z, [] / * - ')
- Назначьте случайную соль для каждого пользователя (хранящуюся в БД).
- Сохраните результат hash_function ($ userPassword + $ sitewideSalt + $ randomSalt)
- Сохраните $ randomSalt вместе с полученным хешем.
- Используйте регулируемое хеширование рабочей нагрузки bcrypt
Атака №1. Злоумышленник выгружает базу данных с помощью SQL-инъекции.
Результаты нашей хэш-функции и случайной соли для каждого пользователя в базе данных.После дампа злоумышленник мог получить $ userPassword и $ randomSalt, просмотрев свою учетную запись. Затем, угадав хэш-функцию, такую как md5, он мог начать радужную атаку на $ sitewideSalt. Но это может занять до 1,41 миллиона столетий [1].
Использование этого типа безопасности не позволяет дамп БД поставить под угрозу сохраненные пароли. Пользователь все равно должен найти $ sitewideSalt другим способом.
Атака №2: Злоумышленник находит вектор включения локального файла (LFI).
Злоумышленник может получить необработанный код для нашего веб-приложения.
После использования веб-приложения с помощью возможного LFI или RFI [2] злоумышленник считывает исходный код нашего веб-приложения и получает наш простой алгоритм и сохраненную
$ sitewideSalt.
Куда дальше?
Теперь у злоумышленника есть обе возможности, и он может начать поиск реальных паролей. За исключением того, что он должен создать по одной радужной таблице для каждого пользователя, поскольку у каждого пользователя есть своя соль, специфичная для случайного пользователя ($ randomSalt).
«Современный сервер может вычислять хэш MD5 размером около 330 МБ каждую секунду. Если у ваших пользователей есть пароли в нижнем регистре, буквенно-цифровые и длиной 6 символов, вы можете попробовать каждый возможный пароль такого размера примерно за 40 секунд».
«... CUDA, вы можете собрать свой собственный небольшой суперкомпьютерный кластер, который позволит вам пробовать около 700 000 000 паролей в секунду ...» [3]
Что нам нужно сделать сейчас, так это расширить функцию хеширования, используя трудоемкий алгоритм, такой как bcrypt. Коэффициент загрузки bcrypt может быть на 5-6 порядков больше, чем у более простых хеш-функций. На взлом одного пароля могут уйти годы, а не минуты. И в качестве бонуса bcrypt уже генерирует случайную соль для каждого хэша и сохраняет ее в результирующем хэше.