JWT authentication bypass via kid header path traversal
概要
JWTのヘッダーにある kid (Key ID) パラメータに対してパストラバーサル攻撃を行い、サーバー上の任意のファイルを署名鍵として参照させることで、署名検証を回避し管理者権限を取得する。
調査
-
JWTの特定: ログイン後のリクエストに含まれるJWTをデコードし、ヘッダーに
kidパラメータが存在することを確認する。 -
署名検証の仕組み: サーバーが
kidの値をファイルパスやデータベースのキーとして使用し、対応する鍵を取得して署名を検証していると推測する。 -
脆弱性の仮説:
kidパラメータの入力値検証が不十分な場合、../(パストラバーサル) を含めることで、サーバーのファイルシステム上の意図しないファイル(例:/dev/null)を鍵として読み込ませることができる可能性がある。
攻撃手順
-
対称鍵の作成:
/dev/nullは空のファイルであるため、その内容は空バイト(Base64エンコードするとAA==)となる。これを利用し、空の秘密鍵で署名されたJWTを作成する。- Burp Suiteの拡張機能「JWT Editor」などで、新しいSymmetric Keyを作成し、
kの値をAA==(空) に設定する。
- Burp Suiteの拡張機能「JWT Editor」などで、新しいSymmetric Keyを作成し、
-
JWTの改ざん:
- ヘッダーの
kidパラメータを../../../../../../../dev/nullに変更する。 - ペイロードの
sub(subject) などをadministratorに変更する。
- ヘッダーの
- 署名の生成: 作成した空の対称鍵を使用してJWTに署名を行う。
- リクエスト送信: 改ざんしたJWTを使用してリクエストを送信し、管理者として認証されるか確認する。
対策
-
入力値検証:
kidパラメータに対して厳格なホワイトリスト検証を行う(許可された文字種、パスの形式など)。 -
鍵の管理: ユーザー入力(
kid)をそのままファイルパスとして使用しない。代わりに、IDと鍵のマッピングを安全なデータベースやKey Vaultで管理する。 - ライブラリの更新: 既知の脆弱性が修正された最新のJWTライブラリを使用する。
クリアするまでにかかった時間
20m
所感
-
kidがファイルパスとして解釈される実装パターンがあることを学んだ。 -
/dev/nullを利用することで、秘密鍵を知らなくても署名を偽造できるテクニックは強力だと感じた。
メモ
-
kid (Key ID) とは
- JWTの署名に使用された鍵を識別するためのヒントとなるパラメータ。複数の鍵をローテーションで使用している場合などに、どの鍵で検証すべきかをサーバーに伝える役割を持つ。
- RFC 7515 (JWS) で定義されている。
-
../../../../../../../dev/null の意味
-
パストラバーサル:
../を重ねることで、アプリケーションのルートディレクトリから遡り、ファイルシステムのルート(/)まで移動しようとする試み。 - dev/null: UNIX系OSにおける特殊ファイル。読み込むと常に「空(EOF)」を返す。
-
攻撃の原理: サーバーが
kidをファイルパスとして処理している場合、この値を指定することでサーバーは/dev/nullを読み込む。結果として「空のバイト列」が署名鍵として使用されることになる。攻撃者は手元で「空のバイト列」を鍵としてHMAC署名を生成すれば、サーバー側と同じ鍵を使ったことになり、正当な署名として検証を通過できる。
-
パストラバーサル: