JWT
Last updated
Last updated
Непроверенная инфа: jwt нельзя отзывать, потому что на сервере они не хранятся
JWT: https://research.securitum.com/jwt-json-web-token-security/
Стандарт JWT крутится вокруг четырех понятий — JWK, JWS, JWE, JWT.
JWK — стандарт, описывающий ключи подписи и шифрования
JWS — стандарт, описывающий как подписывать информацию и хранить всю нужную информацию. Защищает целостность информации при передачи.
JWE — стандарт, описывающий как шифровать информацию и хранить всю нужную информацию. Защищает конфиденциальность информации при передачи.
JWT — стандарт, описывающий как кодировать и декодировать key-value данные в формат для передачи куда-либо.
По сути, у нас есть пара значений key и value:
JWT: оберни key и value в json и перегони в строку
JWK: сгенерируй ключ для подписи и/или шифрования
JWE: зашифруй свои данные (payload)
JWS: подпиши свои данные (payload)
JWT: а еще добавь в заголовок необходимую информацию, чтобы другая сторона смогла расширфовать и/или проверить подпись твоего токена
Access Token — от 5 минут до суток
Refresh Token — до месяца
Пробуем заменить в заголовке параметр alg
на none
. В этом случае токен подписывать не надо. Если сервер доверяет такому токену -> можем имперсонироваться под любую другую сессию.
Токен может быть подписан с использованием асимметричных алгоримов (например, rsa или ec). В этом случае, проверка токена осуществляется по public key, который может быть указан в заголовке или хранится на сервере в jwks.json
параметре (а в заголовке jku
ссылка на этот файл).
Мы можем попробовать подписать токен на своем ключе и добавить информацию о публичном ключе в jwk параметр в заголовок токена или указать ссылку на свой сервер, где расположили jwks.json
файл.
Вообще, сервер не должен доверять чужим публичным ключам (список публичных ключей должен храниться в белом списке каком-то), но разработчики ошибаются)
Пример: https://portswigger.net/web-security/jwt, смотри про Injecting self-signed JWTs via the jwk parameter
.
kid нужен в тех случаях, когда на стороне сервера используются несколько секретов для работы с шифрованием и подписями.
Стандарт JWT не регламентирует, что такое kid и каким образом и где он должен хранится. Как результат, в этом месте поверхность атаки может расширится, а именно:
Если kid — это файл, то можно попробовать сделать path traversal. Например: ../../../../../../../dev/null
и подписываем токен на null-байте на алгоритме HS256, например.
Если kid хранится в базе, можно попробовать сделать SQLi.
Исходные: JWT токен, поддерживает HS и RS алгоритмы подписи.
Находим публичный ключ (например, в /.well-known/jwks.json
), кодируем его в нужный формат, переставляем алгоритм подписи в HS и подписываем на этом ключе как на секрете.
С какой-то долей вероятности, на стороне сервера, в качестве секрета (по заголовку) возьмется открытый ключ, а в коде на этапе проверки посмотрят на заголовок alg и проверят на этом секрете — PROFIT.
Lab of PortSwigger: https://portswigger.net/web-security/jwt/algorithm-confusion
Пример: https://hackerone.com/reports/1210502
И даже если мы не знаем публичный ключ(и), имея два JWT с подписью RSA, можем восстановить публичный ключ сервера (CVE-2017-11424). Получить публичные ключи можем с помощью специально подготовленного Docker-контейнера:
На выходе получаем base64 закодированные сертификаты в формате X509 и PKCS1 и переподписанные на них как на секретах по алгоритму HS256 токены (если нам не надо ничего менять внутри этих токенов, то можем их сразу отправить для теста).
cty (Content Type) - Sometimes used to declare a media type for the content in the JWT payload. This is usually omitted from the header, but the underlying parsing library may support it anyway. If you have found a way to bypass signature verification, you can try injecting a cty
header to change the content type to text/xml
or application/x-java-serialized-object
, which can potentially enable new vectors for XXE and deserialization attacks.
x5c
(X.509 Certificate Chain) - Sometimes used to pass the X.509 public key certificate or certificate chain of the key used to digitally sign the JWT. This header parameter can be used to inject self-signed certificates, similar to the jwk
header injection attacks discussed above. Due to the complexity of the X.509 format and its extensions, parsing these certificates can also introduce vulnerabilities. Details of these attacks are beyond the scope of these materials, but for more details, check out CVE-2017-2800 and CVE-2018-2633.
См внизу: https://portswigger.net/web-security/jwt
Декодер - https://jwt.io/
Про токены, JSON Web Tokens (JWT), аутентификацию и авторизацию. Token-Based Authentication: https://gist.github.com/zmts/802dc9c3510d79fd40f9dc38a12bccfc
JSON Object Signing and Encryption (JOSE) — проект, в котором перечислены все возможные параметры JWT и операции над ними: https://www.iana.org/assignments/jose/jose.xhtml
Библиотека для работы с JWT, JWS, JWK, ... — jwcrypto. Примеры использования можно найти в тестах к этой библиотеки. Мои примеры работы с этой библиотекой (реализовывал атаки на JWT).
JWT Security Testing https://mazinahmed.net/blog/breaking-jwt