Если вы можете декодировать JWT, как они защищены?
Я люблю JWT. С ним действительно весело работать. У меня такой вопрос: если я получу JWT и смогу декодировать полезную нагрузку, насколько это безопасно? Не мог бы я просто извлечь токен из заголовка, декодировать и изменить информацию о пользователе в полезной нагрузке и отправить ее обратно с тем же правильным закодированным секретом?
Я знаю, что они должны быть в безопасности, но мне бы очень хотелось понять технологии. Что мне не хватает? Спасибо!
10 ответов
JWT могут быть подписаны, зашифрованы или оба. Если токен подписан, но не зашифрован, каждый может прочитать содержимое токена, но если вы не знаете секретный ключ, вы не сможете его изменить. В противном случае получатель заметит, что подпись больше не будет совпадать.
Ответ на ваш комментарий: Я не уверен, правильно ли я понимаю ваш комментарий. Просто чтобы быть уверенным: вы знаете и понимаете цифровые подписи? Я просто кратко объясню один вариант (HMAC, который является симметричным, но есть много других).
Давайте предположим, что Алиса хочет отправить JWT Бобу. Они оба знают какой-то общий секрет. Мэллори не знает этого секрета, но хочет вмешаться и изменить JWT. Чтобы предотвратить это, Алиса вычисляет Hash(payload + secret)
и добавляет это как подпись.
При получении сообщения Боб также может рассчитать Hash(payload + secret)
проверить, совпадает ли подпись. Однако, если Мэллори что-то изменит в контенте, она не сможет рассчитать соответствующую подпись (что было бы Hash(newContent + secret)
). Она не знает секрета и не может его узнать. Это означает, что если она что-то изменит, подпись больше не будет совпадать, и Боб просто не примет JWT больше.
Предположим, я отправил другому человеку сообщение {"id":1}
и подпишите его Hash(content + secret)
, (+ это просто конкатенация здесь). Я использую хэш-функцию SHA256 и получаю подпись: 330e7b0775561c6e95797d4dd306a150046e239986f0a1373230fda0235bda8c
, Теперь твоя очередь: сыграй роль Мэллори и попробуй подписать сообщение {"id":2}
, Вы не можете, потому что не знаете, какой секрет я использовал. Если я полагаю, что получатель знает секрет, он МОЖЕТ вычислить подпись любого сообщения и проверить его правильность.
Разберемся с самого начала:
JWT - это очень современный, простой и безопасный подход, который распространяется на веб-токены Json. Веб-токены Json - это решение для аутентификации без сохранения состояния. Таким образом, нет необходимости сохранять какое-либо состояние сеанса на сервере, что, конечно, идеально подходит для спокойных API. Restful API всегда должны быть без сохранения состояния, и наиболее широко используемой альтернативой аутентификации с JWT является просто сохранение состояния входа пользователя на сервере с использованием сеансов. Но тогда, конечно, не следует принципу, гласящему, что успокаивающие API должны быть без сохранения состояния, и поэтому такие решения, как JWT, стали популярными и эффективными.
Итак, теперь давайте узнаем, как на самом деле работает аутентификация с Json Web Tokens. Предположим, у нас уже есть зарегистрированный пользователь в нашей базе данных. Таким образом, клиент пользователя начинает с отправки почтового запроса с именем пользователя и паролем, затем приложение проверяет, существует ли пользователь, и если пароль правильный, тогда приложение сгенерирует уникальный веб-токен Json только для этого пользователя.
Токен создается с использованием секретной строки, которая хранится на сервере. Затем сервер отправляет этот JWT обратно клиенту, который сохранит его либо в файле cookie, либо в локальном хранилище.
Точно так же пользователь аутентифицируется и в основном входит в наше приложение, не выходя из состояния на сервере.
Таким образом, сервер фактически не знает, какой пользователь на самом деле вошел в систему, но, конечно, пользователь знает, что он вошел в систему, потому что у него есть действующий веб-токен Json, который немного похож на паспорт для доступа к защищенным частям приложения.
Итак, еще раз, просто чтобы убедиться, что вы поняли идею. Пользователь входит в систему, как только он получает свой уникальный действительный веб-токен Json, который нигде не сохраняется на сервере. Таким образом, этот процесс полностью не имеет гражданства.
Затем каждый раз, когда пользователь хочет получить доступ к защищенному маршруту, например, к данным его профиля пользователя. Он отправляет свой Json Web Token вместе с запросом, так что это немного похоже на показ своего паспорта, чтобы получить доступ к этому маршруту.
Как только запрос попадет на сервер, наше приложение затем проверит, действительно ли веб-токен Json действителен, и если пользователь действительно тот, кем он себя называет, тогда запрошенные данные будут отправлены клиенту, а если нет, то будет быть ошибкой, сообщающей пользователю, что ему не разрешен доступ к этому ресурсу.
Вся эта связь должна происходить через https, поэтому безопасный зашифрованный HTTP, чтобы никто не мог получить доступ к паролям или веб-токенам Json. Только тогда у нас будет действительно безопасная система.
Таким образом, Json Web Token выглядит как левая часть этого снимка экрана, который был взят из отладчика JWT на jwt.io По сути, это строка кодирования, состоящая из трех частей. Заголовок, полезная нагрузка и подпись. Теперь заголовок - это просто некоторые метаданные о самом токене, а полезная нагрузка - это данные, которые мы можем закодировать в токен, любые данные, которые мы действительно хотим. Таким образом, чем больше данных мы хотим здесь закодировать, тем больше будет JWT. В любом случае, эти две части представляют собой простой текст, который будет закодирован, но не зашифрован.
Так что любой сможет их расшифровать и прочитать, мы не можем хранить здесь какие-либо конфиденциальные данные. Но это совсем не проблема, потому что в третьей части, то есть в подписи, все становится действительно интересно. Подпись создается с использованием заголовка, полезной нагрузки и секрета, который сохраняется на сервере.
И весь этот процесс затем называется подписанием веб-токена Json. Алгоритм подписи использует заголовок, полезные данные и секрет для создания уникальной подписи. Так что только эти данные плюс секрет могут создать эту подпись, ясно? Затем вместе с заголовком и полезной нагрузкой эта подпись формирует JWT, который затем отправляется клиенту.
Как только сервер получает JWT для предоставления доступа к защищенному маршруту, ему необходимо проверить его, чтобы определить, действительно ли пользователь является тем, кем он себя называет. Другими словами, он проверит, не изменил ли никто заголовок и данные полезной нагрузки токена. Итак, снова этот этап проверки будет проверять, действительно ли третья сторона не изменила ни заголовок, ни полезную нагрузку Json Web Token.
Итак, как на самом деле работает эта проверка? Что ж, на самом деле это довольно просто. Как только JWT получен, проверка будет принимать его заголовок и полезную нагрузку, и вместе с секретом, который все еще сохраняется на сервере, в основном создает тестовую подпись.
Но исходная подпись, сгенерированная при первом создании JWT, все еще находится в токене, верно? И это ключ к проверке. Потому что теперь все, что нам нужно сделать, это сравнить тестовую подпись с исходной подписью. И если тестовая подпись совпадает с исходной подписью, это означает, что полезная нагрузка и заголовок не были изменены.
Потому что, если бы они были изменены, то тестовая подпись должна была бы быть другой. Поэтому в этом случае, когда данные не были изменены, мы можем аутентифицировать пользователя. И, конечно, если две подписи на самом деле разные, то это означает, что кто-то подделал данные. Обычно при попытке изменить полезную нагрузку. Но эта третья сторона, манипулирующая полезной нагрузкой, конечно же, не имеет доступа к секрету, поэтому они не могут подписать JWT. Таким образом, исходная подпись никогда не будет соответствовать обработанным данным. И поэтому в этом случае проверка всегда будет неудачной. И это ключ к тому, чтобы вся эта система работала. Это волшебство, которое делает JWT таким простым, но в то же время чрезвычайно мощным.
Ты можешь пойти в jwt.io
, вставьте свой токен и прочитайте содержимое. Поначалу это раздражает многих людей.
Короткий ответ: JWT не занимается шифрованием. Это заботится о проверке. Иными словами, он всегда может получить ответ на вопрос "Управлялись ли содержимым этого токена"? Это означает, что пользовательские манипуляции с токеном JWT бесполезны, потому что сервер будет знать и игнорировать токен. Сервер добавляет подпись на основе полезной нагрузки при выдаче токена клиенту. Позже он проверяет полезную нагрузку и соответствующую подпись.
Логичный вопрос: что является мотивацией для того, чтобы не интересоваться зашифрованным содержимым?
Самая простая причина заключается в том, что предполагается, что это по большей части решенная проблема. Если вы работаете с таким клиентом, как веб-браузер, например, вы можете сохранить токены JWT в файле cookie, который
secure + httpsOnly
(не может быть прочитан Javascript + не может быть прочитан HTTP) и общается с сервером по зашифрованному каналу (HTTPS). Как только вы узнаете, что у вас есть безопасный канал между сервером и клиентом, вы можете безопасно обмениваться JWT или любым другим способом.Это делает вещь простой. Простая реализация упрощает адаптацию, но также позволяет каждому уровню делать то, что у него получается лучше всего (пусть HTTPS обрабатывает шифрование).
JWT не предназначен для хранения конфиденциальных данных. Как только сервер получает токен JWT и проверяет его, он может свободно искать идентификатор пользователя в своей собственной базе данных для получения дополнительной информации для этого пользователя (например, разрешения, почтовый адрес и т. Д.). Это делает JWT небольшим по размеру и предотвращает непреднамеренную утечку информации, потому что каждый знает, как не хранить конфиденциальные данные в JWT.
Это не слишком отличается от того, как сами куки работают. Файлы cookie часто содержат незашифрованные данные. Если вы используете HTTPS, то все хорошо. Если нет, то желательно зашифровать конфиденциальные файлы cookie. Невыполнение этого условия будет означать, что атака "человек посередине" возможна - прокси-сервер или Интернет-провайдер читает файлы cookie, а затем воспроизводит их позже, притворяясь вами. По тем же причинам JWT всегда следует обмениваться через безопасный уровень, такой как HTTPS.
Содержимое веб-токена JSON (JWT) не является по своей сути безопасным, но есть встроенная функция для проверки подлинности токена. JWT - это три хэша, разделенных точками. Третья подпись. В системе с открытым / закрытым ключом эмитент подписывает подпись токена закрытым ключом, который может быть проверен только его соответствующим открытым ключом.
Важно понимать разницу между эмитентом и верификатором. Получатель токена отвечает за его проверку.
Существует два важных этапа безопасного использования JWT в веб-приложении: 1) отправлять их по зашифрованному каналу и 2) проверять подпись сразу после ее получения. Асимметричная природа криптографии с открытым ключом делает возможной проверку подписи JWT. Открытый ключ подтверждает, что JWT был подписан соответствующим закрытым ключом. Никакая другая комбинация клавиш не может выполнить эту проверку, предотвращая попытки подмены. Выполните эти два шага, и мы можем с математической уверенностью гарантировать подлинность JWT.
More reading: Как открытый ключ проверяет подпись?
Я бы объяснил это на примере.
Скажем, я занял у вас 10 долларов, а затем дал вам долговую расписку со своей подписью. Я верну вам деньги всякий раз, когда вы или кто-то другой вернете мне эту долговую расписку, я проверю подпись, чтобы убедиться, что она моя.
Я не могу гарантировать, что вы никому не покажете содержание этой долговой расписки или даже не передадите ее третьему лицу, меня волнует только то, что эта долговая расписка подписана мной, когда кто-то показывает мне эту долговую расписку и просит меня заплати за это.
JWT работает точно так же, сервер может только удостовериться, что полученный токен был выдан им самим.
Вам нужны другие меры, чтобы сделать его безопасным, например, шифрование при передаче с помощью HTTPS, обеспечение безопасности локального хранилища, в котором хранится токен, настройка источников.
Ссылка - Структура и безопасность JWT
Важно отметить, что JWT используется для авторизации, а не для аутентификации.
Таким образом, JWT будет создан для вас только после того, как вы прошли аутентификацию на сервере, указав учетные данные. После создания JWT для всех будущих взаимодействий с сервером можно использовать JWT. Таким образом, JWT сообщает этому серверу, что этот пользователь аутентифицирован, позвольте ему получить доступ к конкретному ресурсу, если у него есть роль.
Информация в полезной нагрузке JWT видна всем. Может быть атака "Человек посередине", и содержимое JWT может быть изменено. Поэтому мы не должны передавать конфиденциальную информацию, например пароли, в полезную нагрузку. Мы можем зашифровать данные полезной нагрузки, если хотим сделать их более безопасными. Если полезная нагрузка подделана, сервер ее распознает.
Итак, предположим, что пользователь прошел аутентификацию и получил JWT. Сгенерированный JWT имеет утверждение, определяющее роль администратора. Также подпись генерируется с
Этот JWT теперь изменен, и предположим, что роль изменилась на суперадминистратора.
Затем, когда сервер получит этот токен, он снова сгенерирует подпись, используя секретный ключ (который есть только у сервера) и полезную нагрузку. Он не будет соответствовать подписи в JWT. Таким образом, сервер будет знать, что JWT был подделан.
Только privateKey JWT, который находится на вашем сервере, расшифровывает зашифрованный JWT. Те, кто знает privateKey, смогут расшифровать зашифрованный JWT.
Скрывайте приватный ключ в безопасном месте на вашем сервере и никогда никому не сообщайте о приватном ключе.
Я не специалист по криптографии, и поэтому (надеюсь) мой ответ может помочь кому-то, кто не является ни тем, ни другим.
Существует два возможных способа использования криптографии в программировании:
- Подписание / проверка
- Шифрование/дешифрование
Мы используем подписывание, когда хотим убедиться, что данные поступают из надежного источника. Мы используем шифрование, когда хотим защитить данные.
Подписание/проверка использует асимметричные алгоритмы, т.е. мы подписываем одним ключом (закрытым), а получатель данных использует другой (открытый) ключ для проверки.
Симметричный алгоритм использует один и тот же ключ для шифрования и дешифрования данных.
Шифрование может быть выполнено с использованием как симметричных, так и асимметричных алгоритмов.относительно простая статья на тему
Вышеизложенное общеизвестно, ниже мое мнение.
Когда JWT используется для простой идентификации между клиентом и сервером, нет необходимости в подписи или асимметричном шифровании. JWT можно зашифровать с помощью AES, который является быстрым и сверхбезопасным. Если сервер может его расшифровать, это означает, что именно сервер его зашифровал.
Резюме: незашифрованный JWT небезопасен. Вместо подписи можно использовать симметричное шифрование, если не участвует третья сторона.
Я бы посоветовал взглянуть на 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
Данные внутри JWT подписаны и зашифрованы, это не значит, что они безопасны. JWT не дает гарантии на конфиденциальные данные.
Данные шифруются с использованием закрытого ключа, который известен обеим сторонам, т. е. отправителю и получателю. Злоумышленник может заблокировать ключ и изменить содержимое.
Насколько мне известно, JWT не обеспечивает безопасность.
Спасибо