Что делать, если JWT украден?

201

Я пытаюсь реализовать аутентификацию без сохранения состояния с помощью JWT для моих RESTful API.

AFAIK, JWT - это в основном зашифрованная строка, передаваемая в качестве заголовков HTTP во время вызова REST.

Но что, если есть подслушивающий, который видит запрос и ворует токен ? Тогда он сможет подделать запрос с моей личностью?

На самом деле, это относится ко всей аутентификации на основе токенов .

Как это предотвратить? Безопасный канал, такой как HTTPS?

smwikipedia
источник
1
Вот почему токены часто действительны только в течение короткого периода времени. И да, вы должны использовать HTTPS, если вы беспокоитесь о конфиденциальности ваших данных.
Джонатон Рейнхарт
4
@JonathonReinhart Но если срок действия токена скоро истечет, моему клиенту придется получать новый токен, время от времени повторно проходя аутентификацию. Разве это не утомительно?
smwikipedia
@JonathonReinhart Думаю, я понял, почему токен недолговечен. Таким образом, серверу не нужно отслеживать истечение срока действия токена и, таким образом, открывать путь для масштабируемости. Это своего рода trade-offмежду having finer control of token expirationи having better scalability.
smwikipedia
2
Может ли это также помочь? - «Распространенным механизмом безопасности для обнаружения кражи токена является отслеживание происхождения IP-адреса запроса». - подробно описано в последнем разделе здесь - firebase.google.com/docs/auth/admin/manage-sessions
Ula
3
Теоретически, предотвратить кражу токенов невозможно. Лучшее, что мы можем сделать, это обнаружить, что это произошло, и затем отменить сеанс как можно скорее. Наилучшим методом обнаружения является использование вращающихся токенов обновления (в соответствии с RFC 6819). Вот блог , который объясняет это в деталях: supertokens.io/blog/...
Rishabh Poddar

Ответы:

284

Я являюсь автором библиотеки узлов, которая обрабатывает аутентификацию довольно подробно, express-stormpath , поэтому я поделюсь здесь с некоторой информацией.

Во-первых, JWT обычно НЕ зашифрованы. Хотя существует способ шифрования JWT (см .: JWE ), на практике это не очень распространено по многим причинам.

Далее, любая форма аутентификации (с использованием JWT или нет) подвергается атакам MitM (человек посередине). Эти атаки происходят, когда злоумышленник может просматривать ваш трафик в сети, когда вы делаете запросы через Интернет. Это то, что видит ваш провайдер, АНБ и т. Д.

Это то, что SSL помогает предотвратить: зашифровав трафик NETWORK с вашего компьютера -> некоторый сервер при аутентификации, третье лицо, которое отслеживает ваш сетевой трафик, НЕ сможет увидеть ваши токены, пароли или что-то в этом роде, если они каким-то образом не смогут получить копию закрытого SSL-ключа сервера (маловероятно). По этой причине SSL ОБЯЗАТЕЛЬНО для всех форм аутентификации.

Допустим, однако, что кто - то сможет использовать свой SSL и могут просматривать ваш маркер: ответ на ваш вопрос в том , что ДА , злоумышленник будет иметь возможность использовать этот маркер , чтобы выдавать себя за вас и прошу сделать на свой сервер.

Теперь здесь протоколы.

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

ОДНАКО, сами JWT не имеют ничего общего с «безопасностью». Для всех целей и задач JWT - это почти то же самое, что и ключи API: просто случайные строки, которые вы используете для аутентификации на каком-либо сервере.

Что делает ваш вопрос более интересным, так это используемый протокол (скорее всего OAuth2).

Принцип работы OAuth2 заключается в том, что он был разработан для предоставления клиентам ВРЕМЕННЫХ токенов (например, JWT!) Для проверки подлинности ТОЛЬКО В КОРОТКИЙ ПЕРИОД ВРЕМЕНИ!

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

С OAuth2 вам приходится периодически повторять аутентификацию на сервере, предоставляя свои имя пользователя / пароль или учетные данные API, а затем возвращая токен взамен.

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

Надеюсь, это поможет ^^

rdegges
источник
3
Автор следующей статьи утверждает, что недостатком JWT является то, что единственный способ восстановить украденный JWT - это создать новую пару ключей и эффективно отключить всех пользователей. Принимая во внимание, что с идентификаторами сеансов, хранящимися в БД, веб-сайт может удалять только сеансы затронутого пользователя и выходить из него со всех устройств. Я не уверен, как OAuth2 вписывается в рисунок здесь или помогает ли он устранить представленные недостатки. medium.com/@rahulgolwalkar/…
Марсель
5
Автор неверен. Существуют различные шаблоны проектирования, которые можно использовать для аннулирования токенов. Но в целом: использование JWT для любых целей аутентификации - плохая идея. Гораздо эффективнее использовать cookie-файл сеанса со встроенной в него идеей сеанса с криптографической подписью.
Заявления
1
@ rdegges, скажите, пожалуйста, как JWT плохая идея для аутентификации? и как я могу использовать cookie сессии, которые вы упомянули в вашем комментарии выше?
номан туфаил
6
Это слишком долго, чтобы ввести один ответ. Если вы хотите узнать больше, я дал подробный доклад на эту тему. Вы можете проверить мои слайды онлайн: speakerdeck.com/rdegges/jwts-suck-and-are-stupid
rdegges,
2
Теоретически, предотвратить кражу токенов невозможно. Лучшее, что мы можем сделать, это обнаружить, что это произошло, и затем отменить сеанс как можно скорее. Наилучшим методом обнаружения является использование вращающихся токенов обновления (в соответствии с RFC 6819). Вот блог , который объясняет это в деталях: supertokens.io/blog/...
Rishabh Poddar
31

Я знаю, что это старый вопрос, но я думаю, что я могу отбросить свои $ 0,50 здесь, возможно, кто-то может улучшить или предоставить аргумент, чтобы полностью отказаться от моего подхода. Я использую JWT в RESTful API через HTTPS (ofc).

Чтобы это работало, вы всегда должны выдавать краткосрочные токены (зависит от большинства случаев, в моем приложении я фактически устанавливаю expтребование на 30 минут и ttlна 3 дня, чтобы вы могли обновить этот токен, пока ttlон все еще работает. действительный и токен не попал в черный список )

Для того authentication service, чтобы аннулировать токены, мне нравится использовать слой кэша в памяти ( redis в моем случае) как JWT blacklist/ ban-listперед, в зависимости от некоторых критериев: (я знаю, что это нарушает философию RESTful, но сохраненные документы действительно недолговечен, так как я в черном списке за оставшееся у них время жизни - ttlпретензия-)

Примечание: жетоны в черном списке не могут быть автоматически обновлены

  • Если user.passwordили user.emailбыло обновлено (требуется подтверждение пароля), служба аутентификации возвращает обновленный токен и аннулирует (черный список) предыдущий (ие), поэтому, если ваш клиент обнаружит, что личность пользователя каким-то образом была скомпрометирована, вы можете попросить этого пользователя изменить свой пароль. , Если вы не хотите использовать черный список для него, вы можете (но я не призываю вас) проверить iat(выдано в) претензию против user.updated_atполя (если jwt.iat < user.updated_atтогда JWT недействителен).
  • Пользователь намеренно вышел из системы.

Наконец, вы проверяете токен как обычно.

Примечание 2: вместо того, чтобы использовать сам токен (который очень длинный) в качестве ключа кеша, я предлагаю сгенерировать и использовать токен UUID для jtiутверждения. Это хорошо, и я думаю (не уверен, так как это только что пришло мне в голову), вы можете использовать этот же UUID в качестве токена CSRF, вернув с ним secure/ non-http-onlycookie и правильно реализовав X-XSRF-TOKENзаголовок с помощью js. Таким образом вы избегаете вычислительной работы по созданию еще одного токена для проверок CSRF.

Frondor
источник
9
Никогда не поздно внести свою идею. Спасибо за ваш ответ.
smwikipedia
2
Если вы храните черный список на сервере, который необходимо проверять для каждого запроса, почему бы просто не использовать старый старый сеанс?
Франклин Ю
@FranklinYu Черный список намного дешевле, чем полный магазин сессий. Так как вы храните недолговечные объекты значения ключа (в зависимости от оставшегося времени жизни, которое должно быть довольно коротким), и это происходит только для действий выхода из системы и таких действий, которые делают недействительными токены, поэтому не каждый токен является хранится в оф.
Фрондор
2
Как дешево это может быть? Прежде всего, если вы все еще храните что-либо на стороне сервера, вы не получаете преимущества «масштабируемости», заявленного JWT, потому что есть центральный сервер черного списка, с которым все серверы приложений должны общаться, прежде чем что-либо делать. Если вам нужно хранить только 1 КБ черного списка из-за быстрого истечения срока действия, вы можете сделать то же самое для сеансов и, следовательно, вам нужно хранить только 1 КБ сеансов.
Франклин Ю
3
Мне нравится этот подход. На самом деле вам не нужно проверять черный список по каждому запросу, только по запросу, который происходит после истечения срока действия JWT (который вы можете прочитать из самого токена) и вплоть до периода TTL после. В «стандартном» случае использования это должно происходить не более одного раза в жизни данного токена. После обновления вы можете отклонить любые будущие запросы на обновление. Спасибо @Frondor
Джон Акерман
7

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

1) rdegges добавил отличное замечание о том, что JWT не имеет ничего общего с «безопасностью» и просто проверяет, запутался ли кто-нибудь с полезной нагрузкой или нет (подписание); SSL помогает предотвратить от нарушений.

2) Теперь, если ssl также каким-то образом скомпрометирован, любой подслушивающий может украсть наш токен на предъявителя (JWT) и выдать себя за подлинного пользователя, следующий шаг уровня, который можно сделать, - найти «доказательство владения» JWT у клиента ,

3) Теперь при таком подходе презентатор JWT обладает определенным ключом подтверждения владения (POP), который получатель может криптографически подтвердить, является ли запрос от того же аутентичного пользователя или нет.

Я сослался на статью Proof of Possesion и убедился в этом.

Я буду в восторге, если смогу что-нибудь внести.

Приветствия (у)

yanky_cranky
источник
0

Разве мы не можем просто добавить ip исходного хоста, который запросил генерацию этого токена JWT, как часть заявки? Теперь, когда JWT похищается и используется с другого компьютера, когда сервер проверяет этот токен, мы можем проверить, совпадает ли IP-адрес запрашиваемого компьютера с тем, который указан в заявке. Это не будет соответствовать и, следовательно, токен может быть отклонен. Кроме того, если пользователь пытается манипулировать токеном, устанавливая свой собственный ip для токена, токен будет отклонен при изменении токена.

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