Правильная реализация аутентификации пользователей

Введение Написание на днях о Passport.js [/ add-authentication-to-express-with-паспорт /] заставило меня задуматься о том, как на самом деле работает аутентификация, и, что более важно, во многих случаях, когда это может пойти не так. Наивное решение - просто сохранить имя пользователя / адрес электронной почты и пароль непосредственно в базе данных, а затем сравнить отправленный пароль с сохраненным. Хотя это, по сути, то, что должно происходить во время аутентификации, на самом деле это гораздо больше. На протяжении всей этой статьи

Вступление

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

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

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

Требования к паролю

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

Следующие требования - хорошее место для начала:

  • Минимум 8 символов
  • Должен содержать хотя бы 1 строчную букву (az)
  • Должен содержать как минимум 1 заглавную букву (AZ)
  • Должен содержать хотя бы 1 цифру (0-9)
  • Должен содержать как минимум 1 специальный символ (!, @, #, $,%, ^ И т. Д.)

По какой-то причине некоторые веб-сайты устанавливают максимальную длину паролей, чего вам категорически не следует делать . Вы будете хешировать пароли до того, как они будут сохранены в базе данных, поэтому все они в любом случае будут иметь одинаковую длину символа, независимо от того, вводит ли пользователь пароль из 8 или 150 символов. Не делай этого .

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

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

Для дополнительной безопасности:
Заставляет пользователя периодически менять свой пароль через определенный период времени, например, один раз в год. Вы также можете делать то, что делает Google, и не разрешать пользователю повторно использовать какой-либо из своих старых паролей.

Передача данных

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

Раньше было дорого и неудобно покупать сертификаты SSL и управлять ими, но теперь есть некоторые услуги, которые стоят всего 16,00 долларов в год за сертификат с подтверждением домена. Возьмем, к примеру, SSLMate - они позволяют покупать и устанавливать сертификаты прямо из командной строки вашего сервера. И если вы решите это сделать, вы можете автоматически обновлять и автоматически устанавливать свои сертификаты. Не так много оправданий тому, что у вас нет HTTPS, если у вас есть пользовательское веб-приложение.

Боковое примечание: Нет, SSLMate мне не платит, у меня только что был хороший опыт работы с их продуктом.

Помимо использования HTTPS, вы должны использовать только метод POST для отправки конфиденциальных данных, а не в строках запроса URL через GET. Подумайте только, что если вы вошли на веб-сайт, используя URL-адрес, например:

 https://stackabuse.com/login?username=scott&password=myPassword 

Хотя технически это могло сработать, это было бы не очень разумно. Если вы отправляете конфиденциальные данные с помощью этого метода, то URL-адрес будет сохранен в истории вашего браузера и, скорее всего, также будет сохранен в журналах сервера. Данные POST обычно не регистрируются, если явно не настроены для этого, что бывает редко, поэтому это намного безопаснее, чем методы GET. Журналы обычно намного легче получить (и обращаться с ними более осторожно), чем данные в базе данных, поэтому лучше хранить все данные своих пользователей оттуда.

Для дополнительной безопасности:
Используйте HTTP Strict Transport Security , которая представляет собой стандартизированную политику веб-безопасности, которая позволяет веб-серверам указывать браузеру клиента взаимодействовать с этим веб-сайтом только через HTTPS, а не через HTTP . Это не только гарантирует, что ваши пользователи получают преимущества соединения HTTPS, но также защитит веб-сайты HTTPS от атак перехода на более раннюю версию .

Хеширование паролей

Во-первых, никогда не храните пароли в виде простого текста. Серьезно, просто не надо. Хешировать пароль настолько невероятно просто, что нет никаких причин не делать этого. Я даже покажу вам код, как это сделать на нескольких разных популярных языках, чтобы вы начали.

Существует довольно много типов алгоритмов хеширования (MD5, SHA-0, SHA-1, SHA-3 и т. Д.), Поэтому может быть неочевидно, какой из них лучше всего использовать. bcrypt широко считается лучшим алгоритмом хеширования (ну, технически это функция получения ключа), в основном потому, что это адаптивная функция. Это означает, что вы можете увеличить количество итераций (количество раундов расширения ключа), чтобы сделать его медленнее, что поможет ему оставаться устойчивым к атакам грубой силы.

Вот код для хеширования паролей с помощью bcrypt на нескольких популярных языках:

JavaScript:

 var bcrypt = require('bcryptjs'); 
 var hash = bcrypt.hashSync('somePassword', bcrypt.genSaltSync(10)); 

Python:

 import bcrypt 
 hash = bcrypt.hashpw('somePassword', bcrypt.gensalt()) 

Рубин:

 require 'bcrypt' 
 hash = BCrypt::Password.create('somePassword') 

Видишь, это не так уж плохо, правда?

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

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

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

  • sha3(sha2(password + salt))
  • sha3(sha1(password) + md5(salt))

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

Делаем ваши хэши сильнее

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

 salt = genSalt() 
 hash = hashAlg('somePassword' + salt) 

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

Это верно только в том случае, если соль уникальна и непредсказуема для каждого пользователя, поэтому убедитесь, что вы используете криптографически безопасный генератор псевдослучайных чисел (CSPRNG) для генерации соли. os.urandom в Python и java.security.SecureRandom в Java - это CSPRNG.

Вот как выглядит хэш пароля:

 hash1 = sha3('somePassword' + 'N7v4bL1YZU4xJw5A') // b7854b0f3c9422b4ee4f6e590d8c95897c53aacce9ab6e0c0ab05f0a4d986407 
 hash2 = sha3('somePassword' + 'z8WnrKRcu9D3BeOK') // df56f4a8876f53900575b784a594bbce7e2ab3e913ba146f13c6817c295e5f09 

Заключение

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

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

Какие еще у вас есть советы по обеспечению безопасности процесса аутентификации? Дайте нам знать об этом в комментариях!

comments powered by Disqus