Безопасность в Jwt: распространённые ошибки и как эффективно их избежать

Что такое JWT и зачем он нужен

Безопасность в JWT: типичные ошибки и как их избежать - иллюстрация

JSON Web Token (JWT) — это компактный, URL-безопасный формат для передачи информации между двумя сторонами. Чаще всего его используют как механизм аутентификации и авторизации в веб-приложениях. Внутри JWT находится три части: заголовок (header), полезная нагрузка (payload) и подпись (signature). Заголовок указывает алгоритм подписи, payload содержит пользовательские данные (например, ID или роли), а подпись подтверждает целостность токена. Благодаря своей простоте и удобству JWT стал очень популярным, но вместе с этим пришли и типичные ошибки безопасности в JWT, о которых важно знать каждому разработчику.

Ошибка №1: Использование небезопасного алгоритма подписи

Одна из наиболее пугающих уязвимостей — это использование алгоритма “none” или слабых алгоритмов, таких как HS256 с предсказуемым секретом. В реальной практике был случай, когда разработчики оставили возможность клиенту указать алгоритм “none” в заголовке JWT. Это привело к тому, что злоумышленник мог сгенерировать токен без подписи и обойти аутентификацию. Чтобы избежать подобной ситуации, сервер должен жестко проверять допустимые алгоритмы и игнорировать те, что приходят от клиента.

Визуально это можно представить так:
Клиент → Отправляет JWT с alg=none → Сервер не проверяет подпись → Доступ разрешён
Правильный путь:
Сервер → Проверяет alg=HS256 или RS256 → Проверяет подпись по собственному ключу → Только тогда разрешает доступ

Ошибка №2: Хранение чувствительной информации в payload

Payload в JWT не шифруется, а только кодируется в base64. Это значит, что любой, у кого есть токен, может его расшифровать и прочитать содержимое. В одном случае финансовый сервис передавал в JWT номер банковского счёта клиента. Хакеры, получив токен, смогли просматривать счета других пользователей. Это классический пример того, как избежать уязвимостей в JWT можно было простым правилом: не класть в payload конфиденциальные данные.

Вот что можно сделать:
- Не включайте в payload пароли, номера карт, адреса и другие чувствительные данные.
- Если нужно передать такие данные, шифруйте их отдельно, до включения в токен.
- Используйте короткоживущие токены и минимальный контент.

Ошибка №3: Отсутствие валидации срока действия токена

Разработчики порой забывают проверять или правильно интерпретировать поля `exp` (expiration), `nbf` (not before) и `iat` (issued at). Это приводит к тому, что просроченные токены продолжают действовать. Пример из практики: в одном проекте токены генерировались с полем `exp`, но сервер никак его не проверял. В результате злоумышленник мог повторно использовать старые токены и получать доступ к ресурсам.

Чтобы обеспечить безопасность токенов JWT, необходимо:
- Обязательно проверять `exp` при каждом запросе.
- Настраивать разумное время жизни токенов: 15 минут для доступа, 7 дней для обновления.
- Удалять или блокировать токены при выходе пользователя или при подозрении на компрометацию.

Ошибка №4: Необходимость ротации ключей и отзыва токенов

JWT по своей природе stateless — сервер не хранит информацию о выданных токенах. Это хорошо для производительности, но плохо для контроля. Если токен скомпрометирован, отозвать его почти невозможно. Это становится особенно опасным, если ключ подписи утёк. Один инцидент в медицинском стартапе показал, как разработчики забыли сменить секретный ключ после утечки, что привело к массовым несанкционированным доступам.

Чтобы избежать подобных рисков:
- Регулярно меняйте ключи подписи (ротация).
- Используйте «чёрный список» (blacklist) для отзыва токенов.
- Реализуйте механизмы обновления токенов с проверкой состояния сессии.

Ошибка №5: Недостаточная защита от атак с подстановкой токенов

Безопасность в JWT: типичные ошибки и как их избежать - иллюстрация

Злоумышленники могут перехватывать или подменять JWT, особенно если токены хранятся в небезопасных местах, например в localStorage. В случае XSS-атаки злоумышленник легко получает доступ к токену. Был случай, когда в SPA-приложении токен хранился в localStorage, и через уязвимость в DOM злоумышленник получил доступ ко всем токенам пользователей.

Для защиты JWT от атак типа подстановки нужно:
- Хранить токены в httpOnly cookie, недоступной JavaScript.
- Использовать Content Security Policy (CSP).
- Добавлять проверку IP-адреса или user-agent в токен или на сервере.

JWT vs Сессионный подход: что безопаснее?

Сессионный подход (например, через session ID и cookie) лучше подходит для случаев, где необходим контроль над пользователем и возможностью отзыва доступа. JWT удобен в распределённых системах, где требуется масштабируемость и независимость от состояния. Однако при неправильной реализации типичные ошибки JWT делают его уязвимым.

Сравнение можно представить так:
- JWT: масштабируемость, автономия, но сложнее защищать.
- Сессии: централизованное управление, легче контролировать, но требуют состояния.

Вопрос не в том, что лучше, а что подходит конкретно под ваш кейс. Главное — понимать, как избежать уязвимостей в JWT и не допустить, чтобы они стали слабым звеном в вашей архитектуре.

Вывод: как защитить JWT от атак

Безопасность токенов JWT — это не "установил библиотеку и забыл". Это постоянное внимание к деталям: от правильной конфигурации алгоритма до безопасного хранения и регулярной ротации ключей. Если вы используете JWT — убедитесь, что ваш сервер не подвержен типичным ошибкам JWT. Проверьте, что вы:

- Не используете алгоритм "none"
- Проверяете срок действия токена
- Не храните чувствительные данные в payload
- Ограничиваете доступ к токенам с помощью httpOnly cookie
- Обеспечиваете ротацию и отзыв токенов при необходимости

И помните: даже идеальный токен может стать уязвимым, если им неправильно управляют.

Прокрутить вверх