【入門編】 JWTのkid(Key ID)パラメータ注入による署名検証回避 – オフェンシブセキュリティ & リバースエンジニアリング防御ガイド

泥棒が「合鍵」を偽造する?JWTのkidパラメータに潜む罠

こんにちは!セキュリティの世界へようこそ。
今日は、開発現場でよく使われる「JWT(JSON Web Token)」という技術の中に潜む、ちょっと怖い「鍵のすり替え」というテクニックについてお話しします。

「JWTって何?」という方も安心してください。まずは身近な例えから入っていきましょう。

—

JWTとkidって何?:マンションのオートロックで例えると

JWTは、Webサービスで「私、本人です!」と証明するためのデジタルな通行証のようなものです。

この通行証には、「どの鍵を使って封印したか」を明記するkid(Key ID)というラベルが付いています。

  • JWT本体:通行証の中身(名前や権限など)
  • 署名(Signature):通行証が偽造されていないかを確認する「封印」
  • kid:サーバーに対して「この封印は、あの棚にある『鍵A』で開けてね!」と指示を出すラベル

ここで、もし泥棒がこのラベルを書き換えて、「この封印は、その辺に落ちている『適当な金属片』で開けてね!」とサーバーに嘘をついたらどうなるでしょうか?

サーバーがうっかりその言葉を信じて、指示されたものを鍵として使ってしまったら……。これが、今回のテーマである「kidパラメータ注入攻撃」の正体です。

—

なぜkidを操作されると危ないの?

攻撃者は、サーバーが持っている「秘密のファイル(鍵)」を読み込ませるようにkidを操作します。

本来、kidはサーバー側が用意したリスト(kid: "key-01" は key-01.pub を使う、など)から選ばれるべきものです。しかし、実装が甘いと、攻撃者はこのように細工をします。

{
  "alg": "HS256",
  "kid": "../../../etc/passwd" 
}

この../../../etc/passwdという記述を見てください。これは「サーバーの深い場所にある、システムの大事なファイルを鍵として使え!」という指示になります。もしサーバーが「はい、わかりました」とこれを読み込んでしまったら、そのファイルを「署名の正当性を検証する鍵」として使ってしまい、攻撃者は自由に通行証を偽造できるようになってしまうのです。

—

「一歩ずつ対策を学んでいきましょう!」

この攻撃を防ぐための鉄則はシンプルです。「ユーザーの言いなりにならない」ことです。

1. ホワイトリストで管理する

「どのファイルを使っていいか」をサーバー側で厳格に管理しましょう。ユーザーから送られてきた kid をそのまま使うのではなく、許可されたものだけを許すリストを用意します。

(ダメな例:ユーザーの指示をそのままファイルパスとして使う)

// 絶対にやってはいけません!
$keyPath = "/keys/" . $jwtHeader['kid']; 
$publicKey = file_get_contents($keyPath); // 攻撃者がパスを指定できてしまう

(良い例:許可リストでチェックする)

// ホワイトリストを作成して管理しましょう
$allowedKeys = [
    "key-01" => "/keys/public_01.pem",
    "key-02" => "/keys/public_02.pem"
];

$requestedKid = $jwtHeader['kid'];

// リストにある鍵か確認してからロードする
if (array_key_exists($requestedKid, $allowedKeys)) {
    $publicKey = file_get_contents($allowedKeys[$requestedKid]);
} else {
    // 許可されていない鍵ならエラーにする
    throw new Exception("不正な鍵の指定です");
}

2. ファイルパスを直接扱わない

そもそも、kidにファイルパスそのものを含める設計を避けるのがベストです。kidはあくまで「DB上のID」や「名前」として扱い、実際の鍵データはパスとは無関係な場所から安全に取得する仕組みを作りましょう。

—

最後に:セキュリティは「疑うこと」から始まる

セキュリティエンジニアとして現場にいると、「プログラムが動くこと」と「安全に動くこと」は別物だと痛感します。

今回のkidの例も、開発者が「便利だから」と思って実装した機能が、実は泥棒に合鍵を作るヒントを与えてしまっていた、という典型的なケースです。

「本当にこの値は信用していいのか?」「このファイルを開く権限は誰にあるのか?」
そんな風に、少しだけ意地悪な目で自分のコードを見返してみてください。その「疑う姿勢」こそが、最強の防御の第一歩になります。

また次回の記事で、より深く、泥臭いセキュリティの世界を覗いていきましょう!

コメント

タイトルとURLをコピーしました