Нужно проверить, действительно ли сервис проверяет подпись JWT перед использованием его утверждений. Как построить такую проверку?
Измените утверждение в JWT, например роль или идентификатор пользователя, не изменяя его исходную подпись. Безопасный сервис должен отклонить такой токен до использования изменённых данных; успешное выполнение операции указывает на отсутствие или обход проверки подписи.
Проверка должна также подтвердить, что сервис принимает только разрешённый алгоритм и проверяет токен доверенным ключом. Одного декодирования содержимого JWT недостаточно: его полезная нагрузка обычно доступна для чтения и сама по себе не доказывает подлинность.
JWT появился как компактный способ передавать утверждения между компонентами распределённой системы без хранения состояния сессии на каждом сервисе. Подписываемый токен решает проблему целостности: получатель может проверить, что его содержимое сформировал доверенный издатель и оно не изменялось.
При этом JWT не предназначен для сокрытия данных по умолчанию. Если требуется конфиденциальность, применяются отдельные механизмы шифрования и управления ключами.
Сервис может ошибочно разобрать полезную нагрузку токена и сразу использовать поля пользователя, роли или срока действия. В таком случае злоумышленник изменяет эти поля локально и получает доступ, соответствующий поддельным утверждениям.
Последствия зависят от доверяемых данных: подмена идентификатора может привести к доступу к чужому аккаунту, а подмена роли — к повышению привилегий. Особенно опасен этот дефект в микросервисной архитектуре, где несколько компонентов самостоятельно принимают решения по одному токену.
Сначала нужно получить корректный токен с минимальными правами и зафиксировать ответ сервиса. Затем следует изменить одно значимое утверждение, сохранив остальные части токена и старую подпись. Изменённый токен отправляют в тот же запрос; ожидаемый результат — отказ в аутентификации, а не выполнение операции с изменёнными полномочиями.
Отдельно проверяют токен с подписью, созданной неизвестным сервису ключом. Он также должен быть отклонён. Нельзя считать достаточной проверку только наличия поля подписи или успешного синтаксического разбора токена.
Проверка подписи должна использовать доверенный ключ, соответствовать разрешённому алгоритму и быть обязательной для каждого защищённого маршрута. Кроме подписи, обычно проверяются издатель, аудитория, срок действия и ещё не наступившее время начала действия токена. Эти проверки решают другие задачи, поэтому валидная подпись сама по себе не делает токен допустимым.
Следует отдельно исключить опасное автоматическое принятие алгоритма из самого токена. Сервис должен задавать допустимый набор алгоритмов на стороне конфигурации, а не позволять отправителю выбирать способ проверки. Тест также должен учитывать кэширование и границы между шлюзом и внутренними сервисами: отказ на одном уровне не гарантирует отказ на другом.
В системе шлюз проверял подпись токена, но внутренний сервис при прямом обращении к своему маршруту только разбирал его поля. Рассматривались два варианта: проверять JWT только на шлюзе либо повторять проверку в каждом сервисе. Первый вариант проще в сопровождении, но опасен при обходе шлюза или ошибочной маршрутизации; второй требует централизованного управления ключами и единых правил, зато защищает каждый компонент независимо.
Было выбрано обязательное подтверждение токена на каждом сервисе, дополненное проверкой на шлюзе. В тесте изменённое поле роли принималось шлюзом только как текст, но внутренний сервис должен был отказать при проверке подписи. После исправления подделанный токен стал получать отказ, а корректные токены продолжили работать.
Нет. Нужно проверить несколько утверждений, влияющих на безопасность: идентификатор субъекта, аудиторию, издателя и срок действия. Если подпись проверяется, но, например, игнорируется аудитория, токен одного сервиса может быть принят другим.
Нет. Обычный подписанный JWT не скрывает полезную нагрузку; её можно прочитать и изменить, но после изменения подпись станет недействительной. Для конфиденциальности нужны шифрование, минимизация чувствительных данных в токене и защита ключей.
Внутренний маршрут может стать доступным из-за ошибочной сетевой настройки, альтернативного канала или нового потребителя. Если сервис принимает решения по JWT самостоятельно, он должен сам проверять подпись, алгоритм и обязательные утверждения. Централизованный шлюз уменьшает дублирование, но не должен быть единственной границей доверия.