JWT состоит из трёх частей: заголовок (header), полезная нагрузка (payload) и подпись (signature). Частая ошибка — воспринимать payload как защищённую область. На практике он лишь закодирован в Base64URL, но не зашифрован. Это приводит к утечке конфиденциальных данных, если внутрь токена помещаются пароли, ключи или персональная информация.
Причина: путаница между кодированием и шифрованием, а также неверное представление о безопасности токена.
Одной из критических ошибок является использование алгоритма
none или отсутствие строгой проверки алгоритма при
верификации. Это позволяет злоумышленнику подменить подпись и
сформировать валидный токен без знания секретного ключа.
Также часто встречается ситуация, когда сервер принимает токены, подписанные разными алгоритмами, не ограничивая список допустимых.
Причина: неправильная конфигурация библиотеки и отсутствие явного указания допустимых алгоритмов при проверке токена.
При работе с библиотекой jose возможно использование как симметричных алгоритмов (например, HS256), так и асимметричных (RS256, ES256). Ошибка возникает, когда публичный ключ используется как секрет для HMAC-алгоритма.
Это позволяет атакующему подписывать токены самостоятельно, если он имеет доступ к публичному ключу.
Причина: непонимание различий между типами алгоритмов и их областями применения.
JWT может содержать поле exp, указывающее срок действия
токена. Игнорирование этого поля приводит к тому, что устаревшие токены
продолжают считаться валидными.
Некоторые разработчики отключают проверку времени ради удобства тестирования и забывают вернуть её в продакшене.
Причина: упрощение логики проверки или неправильная настройка параметров верификации.
Поле aud определяет, для какого сервиса предназначен
токен. Если не проверять это значение, токен, выданный для одного
сервиса, может быть использован в другом.
Причина: недооценка важности ограничения области применения токена.
Секретные ключи часто:
В случае асимметричных ключей возможны ошибки при их загрузке, например, использование неправильного формата (PEM vs JWK).
Причина: отсутствие практики безопасного управления ключами и слабая интеграция с системами хранения секретов.
JWT часто используется как долгоживущий токен без механизма обновления. Это увеличивает риск компрометации: если токен украден, он остаётся валидным до истечения срока действия.
Причина: отсутствие архитектуры refresh-токенов и стратегии ротации.
Иногда разработчики просто декодируют JWT, не проверяя подпись. Это полностью нарушает модель безопасности, так как любой может изменить payload.
Причина: использование методов decode вместо verify или misunderstanding API библиотеки jose.
Ошибки верификации (например, неверная подпись или истёкший токен) могут игнорироваться или обрабатываться некорректно. В некоторых случаях приложение продолжает работу, даже если токен невалиден.
Причина: недостаточная обработка исключений и отсутствие строгой логики отказа.
Один и тот же ключ может использоваться для подписи, шифрования и в разных сервисах. Это нарушает принцип разделения ответственности и увеличивает риск компрометации.
Причина: упрощение инфраструктуры за счёт безопасности.
При использовании набора ключей (JWKS) ошибки возникают в следующих случаях:
kidЭто может привести к невозможности проверки токена или использованию устаревшего ключа.
Причина: сложность работы с динамическими ключами и отсутствие механизма обновления.
JWT сильно зависит от временных меток (iat,
nbf, exp). Если серверы имеют разное системное
время, валидный токен может считаться недействительным.
Причина: отсутствие синхронизации времени (например, через NTP).
JWT может передаваться:
Это делает его уязвимым к перехвату.
Причина: неправильное понимание безопасных способов передачи токенов (например, через HTTPS и заголовки Authorization).
Часто JWT сохраняется в localStorage, что делает его доступным для XSS-атак. Более безопасный вариант — использование httpOnly cookie.
Причина: удобство разработки и недостаточное внимание к клиентской безопасности.
JWT не предназначен для хранения большого объёма данных. Перегруженный payload:
Причина: попытка использовать JWT как универсальное хранилище состояния.
JWT по своей природе статичен: после выпуска его нельзя “отозвать”, если не реализован дополнительный механизм (черный список, short-lived токены).
Причина: архитектурное ограничение JWT и отсутствие дополнительной логики на сервере.
Ошибки, специфичные для jose:
jwtVerify и
SignJWTПричина: поверхностное изучение API библиотеки и отсутствие тестирования крайних случаев.
JWT применяется даже в случаях, где достаточно сессий на сервере. Это усложняет архитектуру без реальной необходимости.
Причина: следование трендам без анализа требований.
Без логирования невозможно отследить:
Причина: недооценка важности наблюдаемости системы.
Некорректная работа с Base64URL может привести к невозможности корректного декодирования токена. Например, использование стандартного Base64 вместо URL-safe варианта.
Причина: различия в стандартах кодирования и ручная обработка токена вместо использования библиотеки.
JWT описан в RFC 7519 и связанных документах. Отклонение от стандарта приводит к несовместимости и уязвимостям.
Причина: реализация “на глаз” без изучения спецификации.
При использовании зашифрованных токенов (JWE) внутри подписанных (JWS) возможны ошибки порядка операций:
Причина: сложность комбинирования криптографических операций.
JWT-интеграции редко покрываются тестами на безопасность:
Причина: фокус на функциональности вместо безопасности.
В серверных приложениях middleware может:
Причина: неправильная интеграция JWT-проверки в цепочку обработки запросов.
JWT не является “серебряной пулей”. Он не защищает от:
Причина: неверное представление о возможностях технологии.