non-functionalchecklists

JWT-токены: что должен проверять QA

JWT (JSON Web Token) — стандарт авторизации в современных приложениях. После логина клиент получает токен, отправляет его в Authorization: Bearer <token> заголовке. Подходов к ломанию JWT — много. Базовый набор тестов для каждого QA.

Структура JWT

Токен состоит из трёх частей, разделённых точкой:

header.payload.signature

Header (base64): {"alg":"HS256","typ":"JWT"} — алгоритм подписи. — Payload (base64): {"sub":"user123","exp":1234567890,"role":"admin"} — данные. — Signature: HMAC от header+payload, подписанный секретом.

Header и payload не шифруются — это просто base64. Любой может прочитать.

Базовые проверки

1. Просрочка (expiration)

exp: 1234567890  ← timestamp когда токен истекает

— Передал просроченный токен → 401. — Передал токен который ещё на 1 секунду валидный, потом подожди 2 секунды → 401.

2. Подделка (signature)

Берёшь свой JWT, меняешь role: "user" на role: "admin" в payload, оставляешь старую подпись → должен быть 401, потому что подпись больше не соответствует.

Если сервер не валидирует подпись — критическая уязвимость.

3. alg: none атака

Самая известная атака на JWT. Меняешь header на {"alg":"none","typ":"JWT"}, убираешь signature → некоторые библиотеки принимают.

В payload ставишь role: "admin" → если принимает — получаешь админ-доступ без знания секрета.

4. Алгоритм-confusion атака

Сервер ожидает RSA-подпись (RS256), а атакующий присылает HS256, подписанный публичным ключом RSA как HMAC-секретом. Старые библиотеки уязвимы.

5. Replay attack

Один и тот же JWT можно использовать много раз. Если токен утёк (например, через logs) — атакующий может использовать.

— Должен быть revocation list или короткий exp (15 минут). — На critical actions (transfer money) — short-lived токены или дополнительные подтверждения.

Чек-лист QA

✅ Просроченный токен → 401. ✅ Токен с modified payload (без знания secret) → 401. ✅ alg: none → не принимается. ✅ Refresh token не вечный — есть expiration. ✅ Logout инвалидирует токен — после logout с тем же токеном не пускает. ✅ Token не в URL (?token=...) — это попадает в логи прокси, history браузера. ✅ Token в HttpOnly cookie или Authorization header — не в localStorage если XSS-риск. ✅ iss (issuer) и aud (audience) проверяются сервером, не только подпись.

Инструменты

jwt.io — декодировать JWT, посмотреть payload. — Postman: вкладка Authorization → Bearer Token. — Burp Suite JWT plugin — автоматизированные JWT-атаки.

Что часто пропускают

Длинный exp. «Дайте срок жизни 30 дней» — это удобно юзеру, но если токен утечёт, атакующий имеет месяц. — Sensitive data в payload. Payload base64, не encrypted. Не клади туда password или PII. — Один и тот же secret годами. Должен ротироваться. На случай утечки. — Нет аудита токенов. Если злоумышленник создал валидный токен — без логов даже не узнаешь.

Подробнее: JWT — OWASP Cheat Sheet, jwt.io introduction.