Безопасен ли токен_аутентификатируемого устройства devise?

79

Я создаю простой api с Rails API и хочу убедиться, что здесь я на правильном пути. Я использую devise для обработки логинов и решил использовать token_authenticatableопцию Devise , которая генерирует ключ API, который вам нужно отправлять с каждым запросом.

Я соединяю API с интерфейсом backbone / marionette и обычно задаюсь вопросом, как мне обрабатывать сеансы. Моя первая мысль заключалась в том, чтобы просто сохранить ключ api в локальном хранилище или файле cookie и получить его при загрузке страницы, но что-то в хранении ключа api таким образом беспокоило меня с точки зрения безопасности. Было бы нелегко получить ключ api, просмотрев локальное хранилище / файл cookie или проанализировав любой запрос, который проходит, и использовать его для бессрочного олицетворения этого пользователя? В настоящее время я сбрасываю ключ api при каждом входе в систему, но даже это кажется частым - каждый раз, когда вы входите в систему на любом устройстве, это означает, что вы выходите из системы на каждом другом, что является своего рода болью. Если бы я мог отказаться от этого сброса, я чувствую, что он улучшился бы с точки зрения удобства использования.

Я могу быть здесь совершенно неправ (и надеюсь, что ошибаюсь), может ли кто-нибудь объяснить, является ли аутентификация таким способом надежно безопасным, и если нет, то какой будет хорошая альтернатива? В целом, я ищу способ, которым я могу безопасно сохранить пользователей, которые «вошли в систему» ​​для доступа к API, без частой повторной авторизации.

Джефф Эскаланте
источник

Ответы:

190

token_authenticatableуязвим для атак по времени, что очень хорошо объясняется в этом сообщении в блоге . Эти атаки стали причиной token_authenticatableудаления из Devise 3.1. См. Сообщение в блоге plataformatec для получения дополнительной информации.

Чтобы иметь наиболее безопасный механизм аутентификации токена, токен:

  1. Должен быть отправлен через HTTPS.

  2. Должен быть случайным, криптографической стойкости.

  3. Надо надежно сравнивать.

  4. Не должны храниться непосредственно в базе данных. Здесь может храниться только хеш токена. (Помните, токен = пароль. Мы не храним пароли в виде обычного текста в базе данных, верно?)

  5. Должен истечь по некоторой логике.

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

Расширяя и поясняя свой ответ:

  1. Используйте HTTPS . Это определенно самый важный момент, потому что он касается снифферов.

    Если вы не используете HTTPS, многое может пойти не так. Например:

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

    • В Rails 3 файлы cookie закрываются только кодировкой Base64, поэтому их довольно легко обнаружить. См. Раздел « Декодирование файлов cookie сеанса Rails» для получения дополнительной информации.

      Однако, начиная с Rails 4, хранилище файлов cookie зашифровано, поэтому данные проверяются в цифровом виде и не читаются злоумышленником. Файлы cookie должны быть безопасными до тех пор, secret_key_baseпока не произойдет утечка ваших данных .

  2. Создайте свой токен с помощью:

    • SecureRandom.hex только если вы используете Ruby 2.5+.
    • Драгоценный камень, sysrandomесли вы используете более старый Ruby.

    Для объяснения того, почему это необходимо, я предлагаю прочитать sysrandomREADME и сообщение в блоге Как сгенерировать безопасные случайные числа на различных языках программирования .

  3. Найдите запись пользователя, используя идентификатор пользователя, адрес электронной почты или какой-либо другой атрибут. Затем сравните токен этого пользователя с токеном запроса с помощью Devise.secure_compare(user.auth_token, params[:auth_token]. Если вы используете Rails 4.2.1+, вы также можете использовать ActiveSupport::SecurityUtils.secure_compare.

    Вы не найдете запись пользователя с искателем Rails , как User.find_by(auth_token: params[:auth_token]). Это уязвимо для атак по времени!

  4. Если у вас будет несколько приложений / сеансов одновременно для каждого пользователя, у вас есть два варианта:

    • Сохраните незашифрованный токен в базе данных, чтобы его можно было использовать на всех устройствах. Это плохая практика, но я думаю, вы можете сделать это от имени UX (и если вы доверяете своим сотрудникам доступ к БД).

    • Храните столько зашифрованных токенов на пользователя, сколько вы хотите разрешить текущие сеансы. Поэтому, если вы хотите разрешить 2 сеанса на 2 разных устройствах, сохраните в базе данных 2 разных хэша токенов. Этот вариант немного сложнее реализовать, но он определенно безопаснее. Он также имеет положительную сторону, позволяя вам предоставить вашим пользователям возможность завершить текущие активные сеансы на определенных устройствах, отозвав их токены (как это делают GitHub и Facebook).

  5. Должен быть какой-то механизм, который приводит к истечению срока действия токена. При реализации этого механизма учитывайте компромисс между UX и безопасностью.

    Google истекает срок действия токена, если он не использовался в течение шести месяцев .

    Facebook истекает срок действия токена, если он не использовался в течение двух месяцев :

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

  6. Обновите до Rails 4, чтобы использовать его зашифрованное хранилище файлов cookie. Если вы не можете, зашифруйте хранилище файлов cookie самостоятельно, как предложено здесь . Не было бы никаких проблем с сохранением токена аутентификации в зашифрованном хранилище файлов cookie.

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

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

Ашитака
источник
Отлично, это очень помогает - спасибо! Это почти наверняка даст правильный ответ. Щедрость ваша, если вы добавите к этому свое мнение / рекомендацию (в частности) о том, как лучше всего обрабатывать аутентификацию API :)
Джефф Эскаланте
1
Хотя оба метода генерируют случайную строку, urlsafe_base64генерирует строку, безопасную для URL. Все дело в названии. Если вы не хотите использовать свой токен в своем URL-адресе ( чего не следует делать ), используйте hex.
Ashitaka,
2
токен! = пароль. Нет ничего плохого в том, чтобы хранить токен в виде обычного текста. Проблема с хранением паролей в виде обычного текста заключается в том, что пароль можно использовать где-то еще, чего не должно быть с вашим токеном.
fatfrog
2
@fatfrog Нет. Токен == пароль. Если хакер или недовольный сотрудник имеет доступ к вашей базе данных, он не сможет пройти аутентификацию как определенный пользователь или администратор.
Ashitaka
1
Я не согласен, если хакер или недовольный сотрудник имеет доступ к вашей базе данных, то токены - это последнее, о чем вам нужно беспокоиться. У них уже есть ваши данные.
fatfrog
3

Вы можете попробовать использовать rails4 со своим API, он обеспечивает большую безопасность и использует devise 3.1.0rc

  • В Rails 4.0 некоторые функции были перенесены в драгоценные камни.

    • ActiveRecord :: SessionStore
    • Кэширование действий
    • Кэширование страницы
    • Кэширование Russian Doll через истечение срока действия ключа с автоматическим управлением зависимостями вложенных шаблонов.
      http://blog.envylabs.com/post/41711428227/rails-4-security-for-session-cookies
  • Devise 3.1.0.rc работает как на Rails 3.2, так и на Rails 4.0. http://blog.plataformatec.com.br/2013/08/devise-3-1-now-with-more-secure-defaults/

  • Devise является устаревшим TokenAuthenticatableв версии 3.1.0rc, но вы можете создать свой собственный TokenAuthenticatable метод для решения проблем безопасности. Это надежнее и безопаснее.

Для токена, хранилища сеансов вы можете пройти через http://ruby.railstutorial.org/chapters/sign-in-sign-out и http://blog.bigbinary.com/2013/03/19/cookies-on-rails .html для более стабильной работы.

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

Гаурав Шарма
источник
Есть ли у кого-нибудь пример альтернативы, созданной на заказ?
Дэниел Моррис