В спецификациях JOSE (JSON Object Signing and Encryption) и в
экосистеме JWT ключевую роль играет заголовок JWS, в частности поле
alg, определяющее алгоритм подписи. Именно оно сообщает
библиотеке и проверяющей стороне, как интерпретировать подпись токена:
HS256, RS256, ES256 и другие варианты.
На практике это поле часто воспринимается как техническая метка, однако его неконтролируемое доверие приводит к целому классу критических уязвимостей. Библиотека jose в JavaScript реализует строгую модель проверки, но при неправильной интеграции разработчиком безопасность легко нарушается.
Ключевая ошибка многих реализаций JWT-систем заключается в том, что
значение alg используется для выбора механизма верификации
напрямую из входящего токена.
Типичная ошибочная логика выглядит так:
header.algПроблема заключается в том, что заголовок является частью данных, пришедших от потенциально недоверенного источника. Это означает, что он не может определять криптографическую политику.
Правильный подход заключается в том, что алгоритм должен быть зафиксирован на стороне сервера заранее и не должен зависеть от содержимого токена.
Исторически одной из самых опасных проблем JWT стала путаница между симметричными и асимметричными алгоритмами.
Ошибка возникает, когда система:
alg: HS256 из токенаВ результате публичный ключ начинает выступать как секретный ключ HMAC, что делает подпись полностью подделываемой.
Это не гипотетический сценарий, а исторически массовая уязвимость реальных систем.
Еще один критический режим связан с alg: none. Он
предназначался для сценариев без подписи, но во многих реализациях стал
источником обхода аутентификации.
Если библиотека или обвязка:
noneто токен может быть принят без криптографической проверки.
В современных версиях jose такие сценарии блокируются по умолчанию, но проблема часто возникает на уровне архитектуры приложения, а не библиотеки.
Заголовок JWS не только определяет алгоритм, но в некоторых реализациях косвенно влияет на выбор ключа. Это приводит к более сложным атакам:
kid (Key ID) в связке с уязвимой системой
хранения ключейПоэтому политика выбора ключа и алгоритма должна быть жестко зафиксирована и изолирована от данных токена.
Библиотека jose реализует безопасный подход, при котором алгоритмы явно задаются разработчиком.
Пример проверки JWT:
import { jwtVerify, createRemoteJWKSet } from 'jose'
const JWKS = createRemoteJWKSet(new URL('https://example.com/.well-known/jwks.json'))
const { payload } = await jwtVerify(token, JWKS, {
algorithms: ['RS256']
})
Здесь ключевой момент заключается в том, что:
alg из токена не влияет на выбор допустимых
методов проверкиСистемная защита должна учитывать несколько принципов:
В jose это реализуется через явное указание допустимых алгоритмов и строгую проверку соответствия ключей.
JWT часто ошибочно воспринимается как “защищенный JSON”, тогда как его безопасность полностью определяется криптографической проверкой подписи. Если атакующий получает возможность влиять на выбор алгоритма, он фактически получает контроль над механизмом проверки целостности.
Это приводит к фундаментальному нарушению модели доверия:
Именно поэтому поле alg должно рассматриваться как
вспомогательная метаинформация, а не как управляющий параметр
безопасности.
Корректная архитектура работы с JOSE в JavaScript строится вокруг изоляции:
Любое отклонение от этой модели приводит к тому, что криптография становится зависимой от входных данных, что принципиально недопустимо в системах аутентификации.