Поиск по сайту:

Как правильно хранить пароли: соление, хеширование и PBKDF2


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

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

Используйте вместо этого OAuth, если можете

Лучший способ борьбы с паролями — вообще не использовать. Если у вас нет особой необходимости обрабатывать пароли напрямую, вы можете использовать OAuth, чтобы кто-то другой сделал это за вас. Это также называется сторонним входом в систему, и вы, вероятно, сталкивались с этим раньше, если вас когда-либо просили войти в систему с помощью Google или Facebook.

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

Никогда не храните пароли в открытом виде

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

Решение проблемы с открытым текстом — это хеширование. Хэш — это функция, которая принимает значение и генерирует уникальный ключ. Например, фраза «password» имеет хэш SHA256:

6B3A55E0261B0304143F805A24924D0C1C44524821305F31D9277843B8A10F4E

Но изменение даже одной цифры (passwerd) полностью меняет вывод:

0B503AEB841F18131DFA86FA052CEF91D9F4D81D301B89F6D035AF89C2CD8AA5

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

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

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

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

Посолите свои пароли

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

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

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

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

Чтобы предотвратить этот вектор атаки, вы должны добавить соль — случайную строку, которую вы добавляете в конец пароля перед хешированием. Вместо хеширования «пароль» вы должны хешировать:

password + 1D75BCA3...

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

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

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

Используйте безопасный хэш, предназначенный для паролей

Хотя SHA256 является безопасным хэшем, он также предназначен для использования в качестве хэша общего назначения. Это означает, что он должен быть быстрым, потому что он также используется для создания контрольных сумм (которые должны обрабатывать гигабайты данных). Скорость напрямую сокращает время перебора, и даже с «солеными» паролями по-прежнему относительно легко взломать отдельные короткие строки. Соли защищают только от радужных столов.

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

Чтобы в полной мере использовать PBKDF2, вам нужно внедрить какой-то стандарт пароля для своего сайта. Вам не нужно требовать, чтобы у всех были знаки доллара и цифры; длина важнее всего остального. Старайтесь использовать как минимум 8-12-символьные пароли.

Окончательный контрольный список

В заключение, вот контрольный список безопасности, чтобы убедиться, что у вас все настроено:

  • Не используйте пароли и по возможности переключитесь на OAuth.
  • Никогда не храните пароли в открытом виде ни в одной базе данных, журнале или файле и никогда не передавайте их через HTTP-соединения.
  • Хешируйте пароли с помощью безопасной хеш-функции, такой как PBKDF2 или SHA256.
  • Всегда добавляйте случайную соль к хэшам паролей и храните ее вместе с хешем.
  • Избегайте использования MD5 или SHA1. (Они оба сломаны и ненадежны.)
  • Применяйте надежные стандарты паролей для пользователей вашего сайта. (Длина здесь играет ключевую роль.)
  • В идеале ваш сервер должен полностью не знать пароли в открытом виде, в первую очередь выполняя хеширование на стороне клиента. Эта защищенная паролем защита на будущее даже в том случае, если злоумышленник получит полный доступ к памяти вашего сервера.
  • Убедитесь, что сам сервер защищен, заблокировав доступ по SSH и поддерживая все в актуальном состоянии, чтобы у вас, скорее всего, никогда не возникало этой проблемы.