JWT署名用秘密鍵のハードコーディング

JWT署名用秘密鍵のハードコーディング

説明

JWTの対称署名用秘密鍵をソースコードへ直接保存すると、リポジトリや配布ファイルを読める人が鍵を取得できます。その鍵を信頼するシステムでは、攻撃者がトークンを偽造して認証や権限確認を回避するおそれがあります。

想定される影響

  • 漏えいした鍵で署名したトークンが受け入れられると、他のユーザーへのなりすましや不正な権限取得につながる可能性があります。
  • 取得した権限の範囲でデータを閲覧・変更されるおそれがあります。鍵の交換と既存トークンの無効化が必要になる場合があります。

対処方法

  • 秘密鍵をコードに保存せず、アクセスを制限したシークレットストアやデプロイ環境から供給してください。
  • 十分な長さの暗号学的乱数鍵を使い、環境変数や設定ファイルのアクセス権限、ログへの露出も管理してください。
  • 漏えいした鍵を交換し、その鍵で作られたトークンを信頼しないようにしてください。秘密値がない場合はトークンを発行しないでください。

例

jose 1.28.2の従来の JWT.sign APIを使う抜粋です。新しいコードには、サポートされているバージョンの SignJWT を使ってください。例は鍵の供給方法だけを比較しており、アルゴリズム、発行者、対象、有効期限の方針は別途設定する必要があります。

変更前

javascript
const { JWT } = require('jose')
const payload = {foo: 'bar'}

// ソースコードに秘密鍵を直接記述
const token = JWT.sign(payload, 'my-secret-key')

変更後

javascript
const { JWT } = require('jose')
const payload = {foo: 'bar'}

// 環境変数から秘密鍵を読み込む
const secret = process.env.JWT_SECRET
if (!secret) {
  throw new Error("JWT_SECRET is required")
}
const token = JWT.sign(payload, secret)

解説:

  • 変更前: 秘密鍵 my-secret-key がコードに直接記述されています。閲覧した人がトークンを偽造し、この鍵を信頼するシステムへの不正アクセスを試みる可能性があります。
  • 変更後: process.env.JWT_SECRET から秘密値を読み込み、未設定なら発行を中止します。鍵には十分な乱数品質と保護された保存環境が必要です。環境ごとに別の鍵を供給することもできます。

参考資料