【入門編】JWTの脆弱性:アルゴリズム「none」の悪用と鍵混同攻撃の防御 – アプリケーションセキュリティ & 安全な開発防御ガイド

JWTの「魔の扉」をどう守る?初心者でもわかるアルゴリズム悪用と鉄壁の防御策

こんにちは!セキュリティの世界へようこそ。
日々、開発の現場でコードを書いていると、「JWT(JSON Web Token)」という言葉を耳にすることがあるはずです。最近のWebサービスでは、ログイン状態を管理する「デジタル通行手形」として非常によく使われていますよね。

でも、この通行手形、実は作り方を一歩間違えると、泥棒に裏口を開け渡すような大穴になってしまうことをご存知でしょうか?

今日は、新人開発者の皆さんが必ず一度はハマる、JWTの「アルゴリズムの罠」について、身近な例えを交えながら深掘りしていきましょう。

そもそも、JWTって何?家の鍵に例えてみよう

JWTを、「身分証明書付きの通行手形」だと想像してみてください。
この手形には、あなたの名前や権限が書かれています。そして、偽造を防ぐために「封印(署名)」が施されています。

「この手形は、うちのサーバーという信頼できる主人が発行したよ」という証明ですね。この封印があるからこそ、サーバーは「この人は本物だ」と信じることができるわけです。

狙われる「algフィールド」:泥棒のトリック

さて、ここからが本題です。JWTには「ヘッダー」と呼ばれる部分があり、そこに「この手形はどうやって封印したか(アルゴリズム)」という情報が書かれています。

攻撃者は、このヘッダーを書き換えて悪さをします。これが「アルゴリズムの脆弱性」です。

1. 「none」攻撃:封印を無効化する

一番有名なのが「none」攻撃です。
本来、手形には「HS256」のような頑丈な暗号方式で封印がされています。しかし、攻撃者はヘッダーをこっそり書き換えます。

  • 攻撃前: `{“alg”: “HS256”, …}` (「HS256という鍵で封印したよ」)
  • 攻撃後: `{“alg”: “none”, …}` (「封印なんてないよ。誰でも中身を見れるよ」)

もしサーバー側が「ふーん、アルゴリズムが『none』なら、署名チェックはしなくていいや!」と手抜きをしてしまったら……?
泥棒は、自分の身分証明書を自由に書き換えて、サーバーに堂々と侵入できてしまうのです。

2. 「鍵混同攻撃」:鍵をすり替える

これはもっと巧妙です。
公開鍵暗号(RS256)という、「鍵を作るための鍵(秘密鍵)」と「鍵が正しいか確認する鍵(公開鍵)」が別の方式を悪用します。攻撃者は、「RS256」で署名されているはずの手形を、「HS256(共通鍵)」として無理やり検証させようとします。

サーバー側が「公開鍵」を「共通鍵」として読み間違えてしまうと、攻撃者が適当に作った署名でも「あ、これ正しい鍵でチェックできたわ!」と勘違いして認証を通してしまうんです。

どうやって守る?「鉄壁のアルゴリズム固定」

では、私たちはどうやって身を守ればいいのでしょうか? 答えはシンプル、「サーバー側でルールをガチガチに決めておくこと」です。

対策:ライブラリの設定でアルゴリズムを固定する

開発で使うJWTライブラリには、必ず「どのアルゴリズムを許可するか」を指定する設定があります。これを曖昧にしてはいけません。

以下は、Node.jsのライブラリ(jsonwebtoken)を使った、正しい防御の実装例です。

const jwt = require(‘jsonwebtoken’);

// サーバーで使う秘密鍵
const secretKey = process.env.JWT_SECRET;

// ユーザーから送られてきたトークン
const userToken = req.headers.authorization;

try {
// 【最重要】アルゴリズムを必ず固定する!
// 外部から渡されたalgフィールドを信用せず、HS256のみを許可する設定
const decoded = jwt.verify(userToken, secretKey, {
algorithms: [‘HS256’] // ここに許可するアルゴリズムを明記する
});

console.log(“認証成功!”, decoded);
} catch (err) {
// 署名が一致しない、またはアルゴリズムが異なればここでエラーになる
console.error(“不正なトークンです!”, err.message);
}

なぜこれが安全なの?

`algorithms: [‘HS256’]` と書くことで、仮に攻撃者がヘッダーを `{“alg”: “none”}` に書き換えてきても、ライブラリが「許可リストにnoneなんて入っていないぞ!」と即座に拒否してくれます。

これが「玄関の鍵を二重にする」という行為です。外部からの指示を疑い、自分たちのルールを貫くことが、最強の防御になるのです。

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

今日覚えて帰っていただきたいことは一つ。「外部から送られてくる情報は、すべて泥棒の変装かもしれない」ということです。

JWTのヘッダーも、URLのパラメータも、APIのデータも、基本的には「信用してはいけないもの」として扱ってください。
「アルゴリズムの固定」は、その疑う心を実現するための、最初の一歩であり、最も強力な防犯対策です。

最初は難しく感じるかもしれませんが、こうして一つずつ「なぜ守る必要があるのか」を理解していけば、皆さんは必ず優秀なエンジニアになれます。応援していますよ!

また次の記事で、現場で役立つ「泥臭いセキュリティ」についてお話ししましょう。それでは!

コメント

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