ИНСТР-JWT-SECSecurityOWASP · RFC 7519ревизия 2026-05-07

JWT безопасность

Топ-5 атак на JWT и защита: алгоритмы, secrets management, refresh token rotation. OWASP best practices 2024.

⏱ работает в браузере · без регистрации
Инструмент · ИНСТР-JWT-SEC|real-time
calcal.ru / jwt-token-secrets-bezopasnost
Загрузка...
5
Top атак
256+бит
Длина secret
RS256
Для микросервисов
0
Запросов к серверу

Top-5 атак на JWT

JWT — мощный инструмент для авторизации, но его легко неправильно использовать. По данным OWASP и Snyk Security Reports, 60% уязвимостей JWT в production вызваны типичными ошибками реализации, не дырами в самом стандарте. Разберём топ-5 атак и как от них защититься.

1. None Algorithm Attack

Самая известная атака. JWT-стандарт включает алгоритм «none» — токен без подписи. В ранних версиях библиотек (jsonwebtoken до 9.0) это принималось по умолчанию.

Атака:
1. Берём оригинальный токен от пользователя:
   eyJhbGciOiJIUzI1NiI...   (header: HS256)

2. Меняем header на:
   {"alg":"none","typ":"JWT"}

3. Меняем payload (например, добавляем admin):
   {"sub":"123","role":"admin","exp":...}

4. Удаляем signature (оставляем только пустую часть):
   header.payload.

5. Сервер проверяет: "alg":"none" → подпись не нужна → принимает!

Защита:
jwt.verify(token, secret, {
  algorithms: ["HS256"]  // ← обязательно указать!
});

2. Algorithm Confusion (HS vs RS)

Атакующий меняет алгоритм с RS256 на HS256, использует публичный ключ как HMAC secret.

Атака:
1. Сервер использует RS256 с публичным ключом для verify
2. Атакующий меняет alg на HS256
3. Подписывает HMAC-SHA-256 с публичным ключом как secret
4. Сервер думает что HS256, использует "secret" (publickey) для verify
5. Подпись валидна!

Защита:
Жёстко привязать алгоритм к ключу:
- Если ключ private RSA → только RS256
- Если HMAC secret → только HS256

В коде:
const algorithm = isRSAKey(key) ? "RS256" : "HS256";
jwt.verify(token, key, { algorithms: [algorithm] });

3. Weak Secret

Если secret для HS256 — это слово «password» или «mysecret123», атакующий подберёт его за секунды.

Атака:
$ jwt-cracker eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
[+] Trying password... [no]
[+] Trying secret123... [no]
[+] Trying mysecret... [MATCH!]

Атакующий теперь может подделывать любые токены.

Защита:
1. Минимум 256 бит = 32 байта случайных
2. Генерируйте через CSPRNG:
   $ openssl rand -hex 64
   # 76b0e5a23f8d4c91b6e5...

3. Храните в env переменных, секретных хранилищах
4. Никогда не commitите в git!

4. Stolen Secret

Самая частая утечка — secret в git-истории, логах, error messages, dump памяти.

Где утекают secrets:
❌ Hard-coded в коде: const secret = "abc123";
❌ В .env, который попал в git
❌ В commit истории (даже после удаления из текущего файла!)
❌ В Sentry / Datadog logs (попал из-за ошибки кода)
❌ В GitHub public gist / Pastebin
❌ В headers логов nginx
❌ В memory dump через debugging endpoint

Защита:
✅ Используйте Vault, AWS Secrets Manager, Yandex Cloud Lockbox
✅ Pre-commit hooks: detect-secrets, gitleaks
✅ Rotate secrets каждые 90 дней
✅ Если есть подозрение что утёк — немедленный rotation
✅ Логируйте только safe-redacted токены: "eyJ...***"

5. Replay Attack

Украденный токен (через MITM, XSS, Phishing) используется атакующим до истечения exp.

Защита:
1. Короткий exp: 15 минут вместо 24 часов
2. Refresh token rotation
3. JTI (JWT ID) blacklist для немедленного отзыва
4. Привязка к IP (но проблема с мобильными — IP меняется)
5. Привязка к User-Agent (для критичных операций)
6. HTTPS обязателен — защита от MITM
7. HTTPOnly cookies — защита от XSS-кражи
Most JWT vulnerabilities arise not from the standard itself, but from misuse: weak secrets, accepting arbitrary algorithms, storing tokens insecurely on the client. Defence-in-depth requires careful implementation at every layer.OWASP — JSON Web Token Cheat Sheet, 2024

Выбор алгоритма

АлгоритмТипКогда
HS256HMAC-SHA-256Монолит, простые системы
HS512HMAC-SHA-512Усиленная версия HS256
RS256RSA-SHA-256Микросервисы, OAuth (РЕКОМЕНДУЕМ)
ES256ECDSA-SHA-256Микросервисы (короче RS256)
EdDSAEdwards-curveСовременный, безопасный
noneНИКОГДА не используйте

Хранение токенов

На клиенте (браузер)

  • localStorage — удобно, но уязвимо к XSS. Не используйте для access token.
  • HTTPOnly Secure SameSite=Strict cookie — лучшее для refresh token. Недоступно из JS, защита от XSS.
  • In-memory переменная — лучшее для access token. Сбрасывается при перезагрузке (получите новый через refresh).
  • SessionStorage — компромисс между localStorage и in-memory. Сохраняется до закрытия вкладки.

На сервере

  • Refresh tokens — в БД. С user_id, expires_at, family_id (для rotation), revoked флагом.
  • JTI blacklist (для отзыва) — в Redis. Быстрая проверка на каждый запрос.
  • Secrets — в Vault / AWS Secrets Manager / Yandex Cloud Lockbox. Никогда в env переменных production.
  • Public keys (для RS256) — в JWKS endpoint. /.well-known/jwks.json — стандарт OAuth/OIDC.

Security Checklist

  • ☐ Алгоритм явно указан в jwt.verify (whitelist)
  • ☐ Secret минимум 256 бит, сгенерирован через CSPRNG
  • ☐ Secret в Vault / Secrets Manager, не в коде
  • ☐ Secret rotation процедура (раз в 90 дней)
  • ☐ Access token exp ≤ 15 минут
  • ☐ Refresh token в HTTPOnly Secure cookie
  • ☐ Refresh token rotation (single-use)
  • ☐ JTI blacklist для немедленного отзыва
  • ☐ HTTPS only (нет HTTP)
  • ☐ В payload нет sensitive данных (паролей, ПИН, паспорта)
  • ☐ Логирование redacted: "eyJ...***"
  • ☐ Pre-commit hooks для detect secrets в коде
  • ☐ Алерты на массовые failed verify (брутфорс)
ИСТОЧНИКИ
  1. OWASP — JSON Web Token Cheat Sheet. OWASP. cheatsheetseries.owasp.org/cheatsheets/JSON_Web_Token_for_Java_Cheat_Sheet.html. 2024.
  2. RFC 7519 — JSON Web Token (JWT). IETF. datatracker.ietf.org/doc/html/rfc7519. 2015.
  3. Critical vulnerabilities in JSON Web Token libraries. Tim McLean / Auth0. auth0.com/blog/critical-vulnerabilities-in-json-web-token-libraries. 2015.
  4. JWT Best Current Practices. IETF RFC 8725. datatracker.ietf.org/doc/html/rfc8725. 2020.
ЧАСТЫЕ ВОПРОСЫ

Часто задаваемые вопросы

(1) <strong>None алгоритм</strong> — атакующий меняет alg на "none", удаляет signature, библиотека принимает. (2) <strong>Algorithm confusion</strong> — токен подписан HS256, но публичный ключ передан как secret. Атакующий использует public key для подписи новых токенов. (3) <strong>Weak secret</strong> — секрет «password123» подбирается через JWT secret cracker за минуты. (4) <strong>Stolen secret</strong> — secret в git, в логах, в memory dump. (5) <strong>Replay attack</strong> — украденный токен используется до истечения exp.
Никогда не доверяйте полю alg из header. При verify явно укажите список разрешённых алгоритмов. В большинстве библиотек: <code>jwt.verify(token, secret, { algorithms: ["HS256"] })</code> — без указания algorithms библиотека может принять любой. Никогда не разрешайте "none" в production. Если используете несколько алгоритмов — указывайте все: <code>algorithms: ["HS256", "RS256"]</code>.
HS256 (HMAC-SHA256) — симметричный. Один секрет используется и для подписи, и для проверки. Все сервисы должны иметь один секрет. Хорошо для монолита, плохо для микросервисов (много мест где хранится secret). RS256 (RSA-SHA256) — асимметричный. Authentication Server подписывает приватным ключом, остальные сервисы проверяют публичным. Лучше для микросервисов: компрометация одного сервиса не даёт возможности подделать токены. Используйте RS256 для production микросервисов.
HS256 требует МИНИМУМ 256 бит = 32 байта. Используйте больше — 512 бит (64 байта) или больше. Генерируйте через crypto: <code>crypto.randomBytes(64).toString("hex")</code> в Node.js, или <code>openssl rand -hex 64</code> в shell. Никогда не используйте слова или фразы — атакующие применяют JWT secret cracker (jwt-cracker, hashcat) и подбирают за минуты.
Нативно — нет. Это главный недостаток JWT. Решения: (1) Короткий exp (15 минут) + refresh token. После отзыва пользователя отзываете refresh, через 15 мин access перестанет работать. (2) Blacklist в Redis. Каждый запрос проверяет, нет ли JTI в blacklist. Усложняет логику, но позволяет немедленный отзыв. (3) Очень короткий exp (1 минута) — почти real-time отзыв, но создаёт нагрузку. (4) Альтернатива — opaque session tokens вместо JWT, если отзыв критичен.
Главный спор. Варианты: (1) <strong>localStorage</strong> — удобно, но уязвимо к XSS. Любой JS на странице может прочитать. (2) <strong>sessionStorage</strong> — то же что localStorage, но сбрасывается при закрытии вкладки. (3) <strong>HTTPOnly Secure SameSite cookie</strong> — недоступно из JS, защищено от XSS. Уязвимо к CSRF (но SameSite=Strict защищает). (4) <strong>In-memory</strong> — JS-переменная. Сбрасывается при перезагрузке. Лучшая практика 2024: HTTPOnly cookie для refresh, in-memory для access.
НЕ КЛАДИТЕ: пароли, секретные ключи, API tokens к третьим сервисам, паспортные данные / СНИЛС / ПИН-коды (152-ФЗ), номера кредиток. Payload — открытый текст после Base64URL декодирования. Любой может прочитать. КЛАДИТЕ: user_id, email (если не sensitive), роли/права, exp, iat, jti. Если нужна конфиденциальность — JWE (encrypted JWT) или храните чувствительные данные отдельно с ID в JWT.
Refresh token должен быть: (1) В HTTPOnly Secure cookie — недоступно из JS. (2) С коротким exp — 7-30 дней максимум. (3) Single-use — после использования генерируется новый, старый инвалидируется (Refresh Token Rotation). (4) Привязан к family — если детект использования старого refresh, инвалидируйте всю family (атакующий пытается переиспользовать). (5) С возможностью отзыва на сервере (хранение в БД с user_id).
Лиана Арифметова
АВТОРverifiedред. calcal.ru

Лиана Арифметова

Создатель и главный редактор

Миссия: демократизировать сложные расчёты. Превратить страх перед числами в ясность и контроль. Девиз: «Любая повторяющаяся задача заслуживает своего калькулятора».

Mathematical Engineering · МФТИ · редактирует каталог с 2012 года

Был ли этот калькулятор полезен?

ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ

Инструмент справочный — не заменяет эксперта

Только для информационных целей. Все расчёты, результаты и данные, предоставляемые инструментом, носят исключительно ознакомительный и справочный характер. Они не являются профессиональной консультацией — медицинской, юридической, финансовой, инженерной или иной.

Точность результатов. Калькулятор основан на общепринятых формулах и методиках, однако фактические результаты могут отличаться в зависимости от индивидуальных условий, исходных данных и применяемых стандартов. Мы не гарантируем полноту, точность или актуальность приведённых расчётов.

Профессиональные решения — медицинские, финансовые, инженерные — должны приниматься только после консультации с квалифицированным специалистом. Не используйте автоматический расчёт как единственное основание для важных решений.

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