Если вы можете декодировать JWT, как они защищены?


302

Если я получу JWT и смогу декодировать полезную нагрузку, насколько это безопасно? Разве я не могу просто извлечь токен из заголовка, декодировать и изменить информацию о пользователе в полезной нагрузке и отправить ее обратно с тем же правильным закодированным секретом?

Я знаю, что они должны быть в безопасности, но мне бы очень хотелось понять технологии. Чего мне не хватает?


2
md5('original messaged' + secret) != md5('changed message' + secret)таким образом, если кто-то изменяет сообщение, вы можете обнаружить его
Pithikos

правда, для идеального случая md5 имеет коллизии. @Pithikos
Яш Кумар Верма

@YashKumarVerma да, это просто чтобы продемонстрировать суть этого, так как все знают md5.
Питикос,

1
@ user1955934 это кодировка base64, НЕ зашифрована. Вы можете просто декодировать его любым декодером base64.
Питикос

1
клиенту нужно будет отправить и хэш, и токен jwt? и позже на стороне сервера они попытаются хешировать токен jwt, используя секрет, и сравнить с хешем?
user1955934

Ответы:


387

JWT могут быть подписаны, зашифрованы или оба. Если токен подписан, но не зашифрован, каждый может прочитать его содержимое, но если вы не знаете секретный ключ, вы не сможете его изменить. В противном случае получатель заметит, что подпись больше не будет совпадать.

Ответ на ваш комментарий: Я не уверен, правильно ли я понимаю ваш комментарий. Просто чтобы быть уверенным: вы знаете и понимаете цифровые подписи? Я просто кратко объясню один вариант (HMAC, который является симметричным, но есть много других).

Давайте предположим, что Алиса хочет отправить JWT Бобу. Они оба знают какой-то общий секрет. Мэллори не знает этого секрета, но хочет вмешаться и изменить JWT. Чтобы предотвратить это, Алиса вычисляет Hash(payload + secret)и добавляет это как подпись.

При получении сообщения Боб также может вычислить Hash(payload + secret), совпадает ли подпись. Однако, если Мэллори что-то изменит в контенте, она не сможет рассчитать соответствующую подпись (что было бы Hash(newContent + secret)). Она не знает секрета и не может его узнать. Это означает, что если она что-то изменит, подпись больше не будет совпадать, и Боб просто не примет JWT больше.

Предположим, я отправил другому человеку сообщение {"id":1}и подписал его Hash(content + secret). (+ это просто конкатенация здесь). Я использую функцию SHA256 Hash, а подпись я получаю: 330e7b0775561c6e95797d4dd306a150046e239986f0a1373230fda0235bda8c. Теперь ваша очередь: сыграйте роль Мэллори и попытайтесь подписать сообщение {"id":2}. Вы не можете, потому что вы не знаете, какой секрет я использовал. Если я полагаю, что получатель знает секрет, он МОЖЕТ вычислить подпись любого сообщения и проверить его правильность.


8
Таким образом, подпись меняется, когда меняется полезная нагрузка? У меня сложилось впечатление, что токен был в формате [заголовок]. [Полезная нагрузка]. [Подпись] вычисляется ли подпись по комбинации полезной нагрузки и секрета? Если бы это было так, разве полезная нагрузка с другим идентификатором не была бы одинаковой для этого секрета? Например, если бы данные были {id: 1} и использовались для вычисления части подписи токена с секретом, это не означало бы, что {id: 2} будет действительным для пользователя 2, и поэтому пользователь 1 может измениться id до 2 и токен будет таким же?
PixMach

7
Я дал вам пример, чтобы прояснить ситуацию, но я не буду объяснять вам всю концепцию цифровых подписей и HMAC. Пожалуйста, прочитайте об этих вещах, есть много материала, объясняющего это.
Миш

11
О, теперь я понимаю. Я не знаю, почему мне не хватало идеи, что секретный хэш будет неправильным, когда вы изменили полезную нагрузку, потому что секретный хэш должен быть пересчитан. По некоторым причинам я все еще думал, что это было независимо. Этот последний бит действительно пробурил это домой для меня. Спасибо, что рассказал мне об этом.
PixMach

30
У меня есть связанный вопрос. Что мешает кому-то выдать себя за Алису с помощью скопированного JWT?
Morrowless

25
Если у кого-то есть JWT, он может выдать себя за Алису. Поэтому вы должны быть осторожны, как вы храните и отправляете. Вы также должны установить срок его действия в полезной нагрузке. Таким образом, если кто-то ворует JWT, у него будет ограниченный период времени для его использования. Взгляните на stormpath.com/blog/…
Герайнт Андерсон

134

Вы можете перейти jwt.io, вставить свой токен и прочитать содержимое. Поначалу это раздражает многих людей.

Короткий ответ: JWT не занимается шифрованием. Это заботится о проверке. То есть он всегда может получить ответ на вопрос «Управлялось ли содержимым этого токена»? Это означает, что пользовательские манипуляции с токеном JWT бесполезны, поскольку сервер будет знать и игнорировать токен. Сервер добавляет подпись на основе полезной нагрузки при выдаче токена клиенту. Позже он проверяет полезную нагрузку и соответствующую подпись.

Логичный вопрос: что является мотивацией для того, чтобы не интересоваться зашифрованным содержимым?

  1. Самая простая причина заключается в том, что предполагается, что это по большей части решенная проблема. Если вы работаете с таким клиентом, как веб-браузер, например, вы можете сохранить токены JWT в файле cookie, который secure(не передается по HTTP, только через HTTPS) и httpOnly(не может быть прочитан Javascript), и общается с сервером через зашифрованный канал (HTTPS). Как только вы узнаете, что у вас есть безопасный канал между сервером и клиентом, вы можете безопасно обмениваться JWT или чем-то еще, что вам нужно.

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

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

Это не слишком отличается от того, как сами куки работают. Файлы cookie часто содержат незашифрованные данные. Если вы используете HTTPS, то все хорошо. Если нет, то желательно зашифровать конфиденциальные файлы cookie. Невыполнение этого условия будет означать, что атака «человек посередине» возможна - прокси-сервер или Интернет-провайдер читает файлы cookie, а затем воспроизводит их позже, притворяясь вами. По тем же причинам JWT всегда следует обмениваться через безопасный уровень, такой как HTTPS.


4
Имей это в виду! JWT всегда следует обменивать через безопасный уровень, такой как HTTPS
codemirror

Но если JWT защищен только через HTTPS, почему бы просто не отправить полезную нагрузку? POST -> имя пользователя, пароль. Это все еще зашифровано верно?
GeekPeek

@GeekPeek для этого вы должны прочитать об основах JWT, но Session Auth, как вы упомянули, часто это все, что вам нужно. JWT предлагает некоторые другие преимущества , но делает некоторые компромиссы webskeleton.com/webdev/2019/10/22/...
aleemb

17

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

Важно понимать разницу между эмитентом и верификатором. Получатель токена отвечает за его проверку.

Существует два критических этапа безопасного использования JWT в веб-приложении: 1) отправить их по зашифрованному каналу и 2) проверить подпись сразу после ее получения. Асимметричная природа криптографии с открытым ключом делает возможной проверку подписи JWT. Открытый ключ подтверждает, что JWT был подписан соответствующим закрытым ключом. Никакая другая комбинация клавиш не может выполнить эту проверку, тем самым предотвращая попытки олицетворения. Выполните эти два шага, и мы можем с математической уверенностью гарантировать подлинность JWT.

More reading: Как открытый ключ проверяет подпись?


2

Давайте с самого начала отрицать:

JWT - это очень современный, простой и безопасный подход, который распространяется на Json Web Tokens. Json Web Tokens - это решение для аутентификации без сохранения состояния. Поэтому нет необходимости хранить какое-либо состояние сеанса на сервере, что, конечно, идеально подходит для спокойных API. API Restful всегда должны быть без сохранения состояния, и наиболее широко используемая альтернатива аутентификации с помощью JWT - просто сохранять состояние входа пользователя в систему на сервере с использованием сеансов. Но тогда, конечно, не следует принципу, согласно которому спокойные API должны быть без сохранения состояния, и поэтому такие решения, как JWT, стали популярными и эффективными.

Итак, теперь давайте узнаем, как на самом деле работает аутентификация с Json Web Tokens. Предполагая, что у нас уже есть зарегистрированный пользователь в нашей базе данных. Таким образом, клиент пользователя начинает с отправки запроса с именем пользователя и паролем, затем приложение проверяет, существует ли пользователь, и, если пароль правильный, приложение сгенерирует уникальный веб-токен Json только для этого пользователя.

Токен создается с использованием секретной строки, которая хранится на сервере . Затем сервер отправляет этот JWT обратно клиенту, который сохранит его либо в файле cookie, либо в локальном хранилище. введите описание изображения здесь

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

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

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

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

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

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

введите описание изображения здесь

Таким образом, веб-токен Json выглядит как левая часть этого скриншота, который был взят из отладчика JWT в jwt.io, так что по сути это строка кодирования, состоящая из трех частей. Заголовок, полезная нагрузка и подпись. Теперь заголовок - это просто метаданные о самом токене, а полезная нагрузка - это данные, которые мы можем закодировать в токене, любые данные, которые нам действительно нужны. Таким образом, чем больше данных мы хотим закодировать, тем больше JWT. В любом случае, эти две части - просто текст, который будет закодирован, но не зашифрован.

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

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

Как только сервер получает JWT для предоставления доступа к защищенному маршруту, он должен проверить его, чтобы определить, действительно ли пользователь является тем, кем он себя считает. Другими словами, он проверит, если никто не изменил заголовок и данные полезной нагрузки токена. Итак, еще раз, этот шаг проверки проверит, действительно ли никакая третья сторона не изменила ни заголовок, ни полезную нагрузку веб-токена Json.

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

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

Потому что если бы они были изменены, то подпись теста должна была бы быть другой. Следовательно, в этом случае, когда данные не были изменены, мы можем затем аутентифицировать пользователя. И, конечно, если две подписи на самом деле разные, ну, значит, кто-то подделал данные. Обычно пытаясь изменить полезную нагрузку. Но эта третья сторона, управляющая полезной нагрузкой, конечно, не имеет доступа к секрету, поэтому они не могут подписать JWT. Таким образом, оригинальная подпись никогда не будет соответствовать манипулируемым данным. И поэтому в этом случае проверка всегда будет неудачной. И это ключ к созданию всей этой системы. Это магия, которая делает JWT настолько простым, но и чрезвычайно мощным.


1

Только privateKey JWT, который находится на вашем сервере, расшифровывает зашифрованный JWT. Те, кто знает privateKey, смогут расшифровать зашифрованный JWT.

Скрывайте приватный ключ в безопасном месте на вашем сервере и никогда никому не сообщайте о приватном ключе.


1
JWT не всегда зашифрованы. Они могут быть подписаны, зашифрованы, подписаны, затем зашифрованы или зашифрованы, а затем подписаны.
csauve

0

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

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


-1

Я бы посоветовал взглянуть на JWE, используя специальные алгоритмы, которых нет в jwt.io для расшифровки

Ссылочная ссылка: https://www.npmjs.com/package/node-webtokens

jwt.generate('PBES2-HS512+A256KW', 'A256GCM', payload, pwd, (error, token) => {
  jwt.parse(token).verify(pwd, (error, parsedToken) => {
    // other statements
  });
});

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

Простой пример, который я создал: https://github.com/hansiemithun/jwe-example

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.