JWTの「時限爆弾」を防げ!`iat`と`nbf`で守る、あなたのアプリケーションの安全な鍵管理
こんにちは。現場で泥臭いインシデント対応を繰り返してきたセキュリティエンジニアです。
今日は、Web開発で避けては通れない「JWT(JSON Web Token)」についてお話しします。JWTは、Webサービスの「通行証」のようなものですが、実は「発行された時間」と「使えるようになる時間」を正しくチェックしないと、思わぬスキを突かれることがあります。
専門用語だらけで難しそうに見えますが、家の鍵に例えれば一発で理解できます。一歩ずつ、安全な実装の世界へ踏み出していきましょう。
—
1. なぜ「時間」のチェックが重要なのか?
皆さんが家を出る時、鍵を閉めますよね。では、もし「未来の時刻が書かれた鍵」や「何年も前の古い鍵」が勝手に作られたらどうなるでしょう?
JWTの世界でも同じことが起きます。
- `iat` (Issued At): この鍵が「いつ発行されたか」を示すスタンプです。
- `nbf` (Not Before): この鍵が「いつから使えるようになるか」を示す解禁時刻です。
もし、悪意ある攻撃者があなたの鍵を盗み取った(リプレイ攻撃)とします。ここで「この鍵、いつ作られたもの?」というチェックがないと、攻撃者は古い鍵を何度も使い回して、あなたのシステムに侵入し続けられるわけです。
—
2. 攻撃者の視点:盲点はどこにある?
攻撃者は、システムが「有効期限(`exp`)」さえ見ていれば安心しきっていることを知っています。
例えば、「発行時刻(`iat`)が現在よりも未来になっている鍵」を送りつけたらどうなるでしょう? もしサーバーが「有効期限内ならOK」としか判断していなければ、システムは混乱し、場合によっては脆弱性を突かれる原因になります。
また、`nbf`を無視すると、「まだ使う予定じゃなかった鍵」を無理やり強行突破させることも可能です。これらは、「鍵の鮮度」を管理していないから起きる事故なのです。
—
3. 実装で差をつける!コードで見る防衛ライン
では、実際にどうやって検証すればいいのでしょうか。Node.jsのライブラリ(`jsonwebtoken`など)を使った、現場で使える基本的な実装例を見てみましょう。
const jwt = require(‘jsonwebtoken’);
// トークンを検証する関数
function verifyToken(token) {
try {
// サーバーの現在時刻を取得
const now = Math.floor(Date.now() / 1000);
const decoded = jwt.verify(token, process.env.JWT_SECRET, {
// 許容する時刻のズレ(クロックスキュー)を数秒持たせるとサーバー負荷が減ります
clockTolerance: 30,
});
// 1. iat (Issued At) の検証:発行時刻が未来ではないか?
if (decoded.iat > now + 30) {
throw new Error(“未来のトークンです。不正な試行の可能性があります。”);
}
// 2. nbf (Not Before) の検証:まだ解禁前ではないか?
if (decoded.nbf && decoded.nbf > now + 30) {
throw new Error(“このトークンはまだ利用できません。”);
}
console.log(“鍵は正常です。アクセスを許可します。”);
return decoded;
} catch (err) {
console.error(“セキュリティエラー:”, err.message);
// ここでログをしっかり残すのが、インシデントハンドリングの基本です!
}
}
ポイント解説
- `clockTolerance`: サーバーとクライアントの時計は、どうしてもミリ秒単位でズレます。この設定を入れておかないと、正しい鍵なのに「未来の鍵だ!」と弾かれてしまうことがあり、ユーザー体験を損ねます。30秒程度の猶予を持たせるのが現場の知恵です。
- 「未来の`iat`を弾く」: これをするだけで、悪意を持って偽造された時刻のトークンをシャットアウトできます。
—
4. セキュリティ担当者からのアドバイス
「JWTの検証なんて、ライブラリに任せておけばいいんでしょ?」と思っているとしたら、それは少し危険です。
1. 時計を合わせる: サーバー同士の時刻同期(NTP)がズレていると、このチェックは全く機能しません。インフラ側の基本設定を疎かにしないことが、実は最強の防御です。
2. ログを監視する: 「未来の`iat`が送られてきた」というログが多発したら、それは攻撃の予兆です。ただエラーを返すだけでなく、異常を検知できる仕組みを持っておきましょう。
—
まとめ:セキュリティは「疑うこと」から始まる
JWTの`iat`や`nbf`を検証することは、あなたのシステムの門番を強化することに他なりません。「渡された鍵は、本当に今使えるものなのか?」という疑いの目を持つだけで、システムは驚くほど強固になります。
最初は難しく感じるかもしれませんが、一度この仕組みを実装してしまえば、それがあなたの「当たり前」になります。まずは、今動いているアプリケーションのコードを覗いてみて、「時間制限のチェックは入っているかな?」と確認することから始めてみてください。
一歩ずつ、安全な開発ライフを目指していきましょう!応援しています。

コメント