【入門編】JWTの署名アルゴリズム ‘none’ 脆弱性と検証の不備 – アプリケーションセキュリティ & 安全な開発防御ガイド

こんにちは。現場の最前線でセキュリティと格闘しているエンジニアの皆さん、お疲れ様です。

今日は、Webアプリケーションの「身分証明書」として広く使われているJWT(JSON Web Token)の、ちょっと怖くて面白い脆弱性についてお話しします。

「JWT? なんか難しそう…」と思ったあなたも大丈夫。まずは身近な例から、一緒に紐解いていきましょう。

—

1. JWTは「改ざん防止機能付きの身分証」

JWTは、サーバーが発行する「あなたは〇〇さんですね」というデジタルな身分証です。これを見せれば、毎回パスワードを入力しなくてもサイトを利用できますよね。

この身分証には、大きく分けて3つのパーツがあります。
1. ヘッダー(どんな形式の身分証か)
2. ペイロード(名前や権限などの情報)
3. 署名(シグネチャー)(これが一番大事!「サーバーが本物だと認めた」というハンコ)

この「署名」があるおかげで、もし泥棒が勝手に情報を書き換えても、サーバーは「あれ? このハンコ、うちのじゃないな」とすぐに見抜くことができる仕組みになっています。

2. 泥棒が狙う「署名アルゴリズム ‘none’」の罠

さて、ここで悪意ある泥棒(攻撃者)が考えます。
「このハンコがなければ、中身を書き換えてもバレないんじゃないか?」と。

そこで登場するのが、署名アルゴリズム none という脆弱性です。

JWTのヘッダー部分には、署名にどのアルゴリズムを使っているかが書かれています。普通は HS256(共通鍵)や RS256(公開鍵)などが使われますが、これをnone(なし)に書き換えてしまうのです。

どうやって攻撃するの?

1. 泥棒は、自分のログイン情報をJWTで入手します。
2. そのJWTのヘッダーにある "alg": "HS256" という部分を "alg": "none" に書き換えます。
3. さらに、ペイロードのユーザーIDを管理者IDに書き換えます。
4. 最後に、署名部分を空っぽ(削除)にします。

ライブラリの設定が甘いと、サーバーは「お、この身分証は『署名なし』でいい設定だな。じゃあ中身を確認しなくていいや」と信じ込んでしまい、まんまと管理者としてログインできてしまうのです。これが「認証回避」の恐ろしい実態です。

3. どう守ればいい? 対策の基本ステップ

「署名なんていらない」と主張する偽の身分証を、門前払いする仕組みを作りましょう。

① デフォルト設定を信じない

多くのJWTライブラリは、便利な反面、柔軟すぎることがあります。「none アルゴリズムを許可しない」という明示的な設定が必要です。

② 厳格な検証を実装する

以下のように、受け取るアルゴリズムを厳格に制限しましょう。

// 良い例:検証時にアルゴリズムを固定する
const jwt = require(‘jsonwebtoken’);

// サーバー側で検証する際、必ずアルゴリズムを明示する
jwt.verify(token, publicKey, { algorithms: [‘RS256’] }, (err, decoded) => {
if (err) {
// 署名が合わない、あるいはアルゴリズムが異なればエラーにする
console.error(“不正な身分証です!”);
return;
}
// 正常な場合
console.log(“認証成功:”, decoded);
});

③ 公開鍵暗号(RS256)の推奨

共通鍵(HS256)は、サーバーとクライアント(または複数のサーバー)で鍵を共有するため、鍵が漏洩するリスクが高いです。RS256(公開鍵方式)を使えば、サーバーは「秘密鍵」で署名し、検証する側は「公開鍵」でチェックするだけで良いため、より安全に運用できます。

—

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

駆け出しの頃、私は「ライブラリがよしなにやってくれるはず」と信じ切っていました。しかし、セキュリティの現場では「ライブラリのデフォルト設定ほど、攻撃者に研究し尽くされているものはない」というのが教訓です。

今回紹介したJWTの脆弱性は、ほんの一例です。

  • 「本当にこの設定で大丈夫か?」
  • 「もし攻撃者がヘッダーを書き換えたらどうなる?」

そんな「疑いの目」を持つことが、あなたの書くコードを、そしてユーザーのデータを守る最強の武器になります。

一歩ずつで構いません。まずは今使っているライブラリのドキュメントを開いて、「署名の検証設定」がどうなっているか確認することから始めてみませんか?

皆さんの開発が、よりセキュアで、自信に満ちたものになることを応援しています!

コメント

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