मुख्य मजकुराकडे जा
友田 陽大
実践Webハッキング技法
セキュリティ
ホワイトハッカー
JWT
脆弱性診断
Webセキュリティ

JWT攻撃の完全攻略【2026】alg:none・鍵ブルートフォース・アルゴリズム混同・jwk/jku/kid注入 — 公式ドキュメント忠実版

JWT(JSON Web Token)攻撃の手法を、PortSwigger Web Security Academyに忠実に深掘り。署名検証の不備(任意署名の受理・alg:none)、HS256の弱い秘密鍵のhashcatブルートフォース、jwk/jku/kidヘッダ注入、RS256→HS256のアルゴリズム混同(鍵混同)攻撃の仕組みと、アルゴリズム固定・厳格な署名検証・jkuホスト許可リストによる根本対策までを、自分のラボ限定の実例で解説します。

Published
Reading time
7 min read
Author
友田 陽大
शेअर करा

JWT(JSON Web Token)は、現代のSPAやマイクロサービスの認証・セッション管理で広く使われます。だからこそ、JWTの検証を一つ間違えると、認証が丸ごと崩壊します。PortSwigger が言う通り「JWTベースの仕組みの安全性は、暗号署名に大きく依存」しており、攻撃の大半はその署名検証の手抜きを突きます。本記事は、その攻撃手法を公式に忠実に解説します。

絶対の前提: 全手順は 合法ラボ または許可スコープでのみ。他人のトークンの偽造・なりすましは、検証目的でも無許可なら不正アクセスです(→ 法律ガイド)。地図は ピラー。JWTを含むトークン設計の基礎は IDトークンとアクセストークンの違い も参照。


1. JWTの構造 — 3つのパート

JWTは header.payload.signature の3つをドット区切りで base64url エンコードしたものです。

eyJhbGciOiJIUzI1NiJ9 . eyJzdWIiOiJ3aWVuZXIifQ . <署名>
└─ header ────────┘   └─ payload ──────────┘
{"alg":"HS256"}        {"sub":"wiener","role":"user"}
  • header:署名アルゴリズム(alg)などのメタ情報。
  • payload:クレーム(誰か・権限・有効期限など)。Base64は暗号化ではないので、誰でも中身を読める。
  • signature:header+payload を鍵で署名したもの。改ざん検出はここだけが頼り

つまり、署名検証が甘ければ、payloadを "role":"admin" に書き換え放題になります。


2. 署名検証の不備を突く

2.1 署名を検証していない / 任意署名の受理

開発者が「デコード」と「検証」を混同し、署名を検証せずにpayloadを信用しているケース。payloadを書き換えるだけで通ります。

# payload の "sub":"wiener" を "sub":"administrator" に書き換えて送るだけで通る
# (Burp の JWT Editor 拡張でワンクリック改ざん→送信できる)

2.2 alg:none

JWS仕様には「署名なし(alg:none)」が存在します。サーバーがこれを受理すると、署名を空にしてpayloadを自由に改ざんできます。

# header を {"alg":"none"} にし、署名部分を空にする
eyJhbGciOiJub25lIn0 . eyJzdWIiOiJhZG1pbmlzdHJhdG9yIn0 .
                                                       └─ 署名は空

単純な none が弾かれても、PortSwigger が指摘する通り NonenOnE・予期しないエンコードといった難読化で検証フィルタを抜けることがあります。


3. 弱い秘密鍵のブルートフォース(HS256)

HMAC系(HS256)は**「任意の文字列」を秘密鍵**にします。鍵が弱い/既定値だと、hashcat で割れます。

# JWTを辞書攻撃(-m 16500 が JWT モード)。割れた鍵が標準出力に出る
hashcat -a 0 -m 16500 jwt.txt /usr/share/wordlists/jwt.secrets.list

# 鍵が判明したら、任意のpayloadを「正規に」署名できる = 完全な認証バイパス
# 例: {"sub":"administrator"} を割れた鍵で署名して送る

鍵が割れたら終わりです。だから秘密鍵は十分に長く・ランダムでなければなりません(弱い既定鍵の流用が事故の典型)。応用暗号と鍵管理の原則は パスワードハッシュ・暗号・鍵管理ガイド を参照。


4. ヘッダ・パラメータ注入(jwk / jku / kid)

JWT仕様は、署名検証に使う鍵をヘッダで指定する仕組みを持ちます。サーバーがこれを無検証で信用すると、攻撃者の鍵で検証させられます。

パラメータ意味攻撃
jwk公開鍵をトークン内に直接埋め込む自分の鍵ペアで署名し、公開鍵をjwkに埋めて送る
jku鍵セット(JWK Set)のURLを指す攻撃者サーバーのJWK SetをURLに指定
kid使う鍵のID(ファイル/DB参照に使われがち)パストラバーサル(../../dev/null)やSQLiで鍵を操作
# jwk 注入の例(header に自前の公開鍵を埋め、その秘密鍵で署名)
{"alg":"RS256","typ":"JWT","jwk":{"kty":"RSA","n":"<攻撃者の公開鍵>","e":"AQAB"}}

# kid をパストラバーサルに:既知内容のファイルを鍵に使わせ、署名を予測可能にする
{"alg":"HS256","kid":"../../../../../../dev/null"}
# /dev/null は空 → 鍵が空文字列になり、攻撃者が署名を作れる

5. アルゴリズム混同(鍵混同)攻撃 — RS256 → HS256

最も巧妙なのが**アルゴリズム混同(algorithm confusion / key confusion)**です。サーバーがRS256(非対称:公開鍵で検証・秘密鍵で署名)を想定しているのに、検証時にalgを固定していないと成立します。

仕組み:

  1. RS256の公開鍵は誰でも入手できる(JWKエンドポイントや証明書から)。
  2. 攻撃者は algHS256(対称)に変えたトークンを作る。
  3. そのトークンを、公開鍵の文字列を「HMACの秘密鍵」として署名する。
  4. サーバーは「HS256だな」と判断し、手元の公開鍵をHMAC鍵として検証 → 一致してしまう。
# 概念:本来 RS256 のサーバーへ、HS256 で署名したトークンを送る
# 署名鍵 = サーバーのRSA「公開」鍵(PEM文字列そのもの)
header  = {"alg":"HS256"}
payload = {"sub":"administrator"}
signature = HMAC-SHA256(base64(header)+"."+base64(payload), <RSA公開鍵PEM>)

公開鍵は秘密でないため、攻撃者は正規に「見える」トークンを偽造できる。これが鍵混同の怖さです(Burpの JWT Editor でPoC可能)。


6. 【守る側】根本対策

攻撃の構造がわかれば、防御は明快です。PortSwigger の推奨に沿います。

// ✅ 検証時にアルゴリズムを「固定」する(最重要)。none も他algも受け付けない
import { jwtVerify } from "jose";

const { payload } = await jwtVerify(token, publicKey, {
  algorithms: ["RS256"], // ← 許可リスト。これが無いと alg 混同/none を許す
  issuer: "https://auth.example",
  audience: "https://api.example",
});

設計原則:

  • アルゴリズムをサーバー側で固定(許可リスト)。alg:none を拒否し、トークンのalgを信用しない。これだけで alg混同・none の大半を封じる。
  • 検証は必ず行う:「デコード」関数(decode)と「検証」関数(verify)を混同しない。
  • jku/jwk のホストを許可リスト化(任意URLの鍵を信用しない)。kid はパストラバーサル/SQLi 対策を施す。
  • 秘密鍵は長くランダムに(HS256の弱鍵を避ける)。鍵のローテーションを設計。
  • 実績ある最新ライブラリを、ドキュメント通りに使う(自前実装しない)。jose / jsonwebtoken 等。
  • 有効期限(exp)と失効:短い有効期限 + リフレッシュトークン + 失効リストで、漏洩時の被害を限定。
  • 保存場所:XSSでの窃取を避けるため、ブラウザでは HttpOnly Cookie を検討(→ XSS対策)。

認証基盤としての堅牢な設計(Cognito/Auth0/Clerk/Supabase Authの選定と、RS256のJWKS検証)は 認証プラットフォーム選定Cognito JWT RS256検証 で詳説しています。


7. まとめ

  • JWTの安全性は署名検証に全依存:検証の手抜き(未検証・alg:none・甘い検証)が主な穴。
  • 弱鍵はhashcatで割れる:HS256の鍵は長くランダムに。
  • ヘッダ注入:jwk/jku/kid をサーバーが無検証で信用すると攻撃者の鍵で通る。
  • アルゴリズム混同:alg未固定だと、公開鍵をHMAC鍵にされ偽造される。
  • 根本対策:アルゴリズム固定 + 必ず検証 + jku/kid厳格化 + 長鍵 + 最新ライブラリ + exp/失効。

次は、ログイン機構そのものを狙う 認証の脆弱性の完全攻略 へ。


参考(公式一次情報)

友田

友田 陽大

मंत्री (METI) पुरस्कारप्राप्त उत्पादनाचे विकसक. TypeScript + Python + AWS वापरून मी एकटाच SaaS, औद्योगिक डिजिटल परिवर्तन आणि उत्पादनयोग्य जनरेटिव्ह एआय (RAG) — गरजा निश्चित करण्यापासून पायाभूत सुविधा व संचालनापर्यंत — सुरुवातीपासून शेवटपर्यंत देतो.

What if this attack were reproduced on your app?

Web-app vulnerability assessment & penetration testing

I actually reproduce and assess the SQLi, XSS, SSRF, JWT, auth, and SSTI attacks covered here on your app, and take it through from design to fix. Only those who know the attacker's moves can preempt where it breaks at the design stage. You're welcome to visualize the current state with the free OSS first.

प्रकल्पाधारित काम आणि तांत्रिक सल्लागार — दोन्हीसाठी उपलब्ध. ३० मिनिटांच्या मोफत सल्लामसलतीने सुरुवात करा.

最短ルート:カレンダーから直接予約

相談内容が固まっている方は、フォーム送信よりその場で日程を確定する方がスムーズです。下記から空き時間をお選びください。

  • 30分のオンライン無料相談
  • Google Meet / Zoom / Microsoft Teams
  • NDA 商談前締結可・無理な営業はいたしません
無料相談の空き枠を予約する

हेही वाचण्यासारखे