説明
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なら署名を検証し、このハンドラーは検証に失敗したトークンを拒否します。許可するアルゴリズム、必要なクレーム、利用者のアクセス権限は別途確認してください。