JWT署名の検証漏れ

JWT署名の検証漏れ

説明

JWTの署名を検証せずにデコードするだけでは、サーバーが偽造されたトークンを受け入れる可能性があります。トークンの完全性や真正性を確認できず、認証の回避や権限昇格につながるおそれがあります。

想定される影響

  • 攻撃者が作成したトークンで認証を回避される可能性があります。
  • 偽造されたクレームにより、強い権限を持つ利用者としてアクセスされるおそれがあります。
  • 未検証のトークンを信頼すると、機密情報が漏えいする可能性があります。

対処方法

  • JWTを認証・認可に使う前に署名を検証してください。
  • デコードのオプションやライブラリ設定で、検証が有効になっていることを確認してください。
  • 信頼する署名鍵や検証鍵を適切に保護してください。
  • 保守されているJWTライブラリを使い、サービスが許可するアルゴリズム、発行者、対象、有効期限の条件を検証してください。

例

jwt-simpleの署名検証オプションを比較する抜粋です。Authorizationヘッダーからのトークン抽出と鍵設定の検証は省略しています。通常のBearerヘッダーでは、接頭辞を取り除いてJWT文字列だけを渡してください。

変更前

javascript
const jwt = require('jwt-simple');
const secret = process.env.JWT_SECRET;

app.get('/profile', (req, res) => {
  const token = req.headers.authorization;
  // ⚠️ 署名を検証せずにデコード
  const decoded = jwt.decode(token, secret, true);
  res.json({ user: decoded.username });
});

変更後

javascript
const jwt = require('jwt-simple');
const secret = process.env.JWT_SECRET;

app.get('/profile', (req, res) => {
  const token = req.headers.authorization;
  try {
    // ✅ 署名を検証
    const decoded = jwt.decode(token, secret, false); // またはnoVerify引数を省略
    res.json({ user: decoded.username });
  } catch (error) {
    res.status(401).json({ error: 'Unauthorized. Invalid token.' });
  }
});

第3引数はnoVerifyです。trueを渡すと検証が省略され、偽造トークンで認証を回避される可能性があります。falseなら署名を検証し、このハンドラーは検証に失敗したトークンを拒否します。許可するアルゴリズム、必要なクレーム、利用者のアクセス権限は別途確認してください。

参考資料