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

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

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

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

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

Категории

Все категории
Loading categories
CVE-2026-19490-check — Безопасное обнаружение обхода аутентификации SAML в Citrix NetScaler CVE-2026-19490 | Kitploit
Инструменты/GitHubGitHub/bishopfox/cve-2026-19490-check
Оборонительные ИнструментыСканеры уязвимостейСканеры веб-уязвимостейАнализ уязвимостейСбор информацииВеб-безопасностьСетевая безопасностьТестирование на ПроникновениеАутентификация
GitHubbishopfox/cve-2026-19490-check

CVE-2026-19490-check

Безопасное обнаружение обхода аутентификации SAML в Citrix NetScaler CVE-2026-19490

117 ч 18 мин назадЕщё не проверено

Популярное

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

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

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

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

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

Обход аутентификации через контекст nFactor в Citrix NetScaler SAML — скрипт обнаружения уязвимости

Безопасная проверка уязвимости без аутентификации для CVE-2026-19490 — обхода аутентификации до её прохождения в пути поставщика услуг SAML Citrix NetScaler ADC / NetScaler Gateway (CTX696939, опубликовано 2026-08-19). CWE-288, CVSS v4.0 9.3 (AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:L/SI:L/SA:L). Сообщено Samarth Vashisht из команды тестирования на проникновение JPMorgan Chase.

Устройство декодирует base64 параметр RelayState SAML-ответа и, когда открытый текст начинается с ctx=, передаёт остаток десериализатору контекста nFactor. На неисправленной сборке сбой десериализации передаёт длину декодированного RelayState в качестве внутреннего кода диспозиции запроса вместо ошибки, поэтому неаутентифицированный атакующий выбирает, какую внутреннюю ветвь устройство выберет далее, просто выбирая длину RelayState. Некоторые ветви создают настоящую сессию Gateway; другие приводят к падению packet engine и перезапуску устройства. Этот скрипт не делает ни того, ни другого — он отправляет одну длину, проверенную на то, что она не создаёт сессию и не затрагивает packet engine, и отвечает на один вопрос для каждой цели: Результат, отличный от , .

уязвимо ли это устройство?
VULNERABLE
сам по себе не является подтверждением безопасности

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

root@kitploit:~
# single target
./cve_2026_19490_check.py https://gateway.example.com

# a specific Gateway or AAA virtual server
./cve_2026_19490_check.py https://gateway.example.com:9443

# several targets; the scheme defaults to https://
./cve_2026_19490_check.py gw-a.example.com gw-b.example.com:9443

# scan a list, one target per line ('#' comments allowed), compact output
./cve_2026_19490_check.py -f targets.txt --brief

# machine-readable output for pipelines
./cve_2026_19490_check.py -f targets.txt --json > results.json

Python 3.8+, только стандартная библиотека — без сторонних пакетов.

Направьте инструмент на Gateway или AAA virtual server, а не на интерфейс управления. Подверженность определяется для каждого virtual server, поэтому устройство с несколькими VIP требует проверки каждого из них. Проба несёт жёсткие рамки безопасности — одна проверенная длина RelayState, без перебора — которые описаны в разделе Безопасно ли это запускать?.

Опции

ФлагОписание
TARGETОдна или несколько целей [https://]HOST[:PORT]; схема по умолчанию https://
-f, --targets-file FILEЧитать цели из файла (по одной на строку; комментарии #)
--timeout SECSТайм-аут на запрос (по умолчанию: 15)
--workers NОдновременных целей (по умолчанию: 16); вывод сохраняется в порядке ввода
-b, --briefОдна выровненная строка на цель — идеально для сканирования множества хостов
--jsonВывод структурированного JSON, включая каждый отправленный запрос на цель
--no-colorОтключить цветной вывод (также учитывает NO_COLOR и не-TTY)

Примеры

Уязвимое устройство (вывод по умолчанию в две строки). Маркер [!] и VULNERABLE отображаются красным на TTY:

root@kitploit:~
$ ./cve_2026_19490_check.py https://gateway.example.com:9443
[!] https://gateway.example.com:9443: VULNERABLE  [internal-error-43524]
      HTTP 500 / 43524: the decoded RelayState length was propagated as the internal error, so the CTX696939 fix is absent

Исправленное устройство:

root@kitploit:~
$ ./cve_2026_19490_check.py https://vpn.example.com
[+] https://vpn.example.com: PATCHED  [fixed-error-returned]
      HTTP 200 "Malformed Assertion": the fixed error was returned on the path this probe reached, so the CTX696939 fix is present (>= 13.1-63.21 / 14.1-73.32)

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

root@kitploit:~
$ ./cve_2026_19490_check.py https://sp-strict.example.com
[?] https://sp-strict.example.com: INCONCLUSIVE  [flat-response]
      the probe and the same-length control both answered HTTP 500 / 43524, so the reply does not depend on what was sent and the fix was never exercised; unknown, not patched

Сканирование парка (--brief). Две строки gateway.example.com — это SP и IdP-only virtual server на одном устройстве — оба отвечают, чего проверка предусловий конфигурации не смогла бы обеспечить:

root@kitploit:~
$ ./cve_2026_19490_check.py -f targets.txt --brief; echo "exit: $?"
VULNERABLE    https://gateway.example.com:9443         internal-error-43524
VULNERABLE    https://gateway.example.com:9444         internal-error-43524
PATCHED       https://vpn.example.com                  fixed-error-returned
INCONCLUSIVE  https://sp-strict.example.com            flat-response
UNAFFECTED    https://lb.example.com                   no-saml-endpoint
ERROR         https://www.example.com                  not-identified
exit: 1

Машиночитаемый вывод (--json). Включён каждый запрос, поэтому находку можно вывести заново из доказательств, а не доверять ей. Контроль записывается по его отношению к пробе, а не как самостоятельный вердикт, потому что контроль, читающийся как исправленная сборка, — ожидаемый результат на любой сборке:

root@kitploit:~
$ ./cve_2026_19490_check.py https://gateway.example.com:9443 --json
[
  {
    "target": "https://gateway.example.com:9443",
    "verdict": "VULNERABLE",
    "reason": "internal-error-43524",
    "detail": "HTTP 500 / 43524: the decoded RelayState length was propagated as the internal error, so the CTX696939 fix is absent",
    "netscaler_indicators": [
      "CSP contains citrixng://",
      "CSP contains com.citrix.nsgclient://",
      "CSP contains nsgcepa://",
      "CSP report-uri /nscsp_violation/report_uri",
      "/vpn/js/rdx/ present (HTTP 404)"
    ],
    "attempts": [
      {
        "kind": "probe",
        "path": "/cgi/samlauth",
        "status": 500,
        "state": "unpatched",
        "detail": "HTTP 500 / 43524: the decoded RelayState length was propagated as the internal error"
      },
      {
        "kind": "control",
        "path": "/cgi/samlauth",
        "status": 200,
        "state": "differs-from-probe",
        "detail": "same-length control: HTTP 200 \"Malformed Assertion\": the fixed error was returned"
      }
    ]
  }
]

Безопасно ли это запускать?

Да. Он предназначен для использования в продакшене и при оценке:

  • Одна фиксированная длина, никогда не перебор. RelayState пробы декодируется ровно в 20 байт, и инструмент не отправляет никакую другую длину ни под каким флагом. На неисправленном устройстве декодированная длина и есть селектор ветви, а среди ветвей есть создающие сессию и вызывающие SIGSEGV в packet engine — перезапускающие весь NetScaler и отбрасывающие трафик примерно на 45 секунд. Двадцать байт попадают на чистую ветвь внутренней ошибки, которая не создаёт сессию, и построитель полезной нагрузки отказывается конструировать любую другую длину, поэтому правка в другом месте не может незаметно расширить пробу.
  • Проверено измерением. 20-байтовая проба была запущена 10 раз подряд против неисправленной 13.1-63.18 без единого сгенерированного кора и без перезапуска packet engine. Сама проверка с тех пор запускалась против обеих ветвей обслуживания, по обе стороны от исправления, и против как service-provider, так и IdP-only virtual server, без перезапуска packet engine ни на одном из них.
  • Без аутентификации, без учётных данных, без изменения состояния. Ни assertion, ни подпись, ни метка времени, ни сессия, ни клиентский сертификат нигде в этой проверке не предъявляются. Параметр SAMLResponse должен присутствовать, чтобы была достигнута ветвь RelayState, но его содержимое несущественно, поэтому это четыре байта мусора. Ветвь не выдаёт cookie и не записывает конфигурацию.
  • Защита от ложных срабатываний. VULNERABLE никогда не сообщается по одному ответу — см. контроль.

Если вы изменяете пробу, не меняйте декодированную длину RelayState и не перебирайте длины. Двадцать байт несут нагрузку, и короче — не безопаснее. Другие длины в лучшем случае не протестированы, а в худшем — это простой устройства.

След запросов и логов

Три HTTP-запроса на цель, и четвёртый только когда устройство возвращает неисправленный сигнал:

#ЗапросНазначение
1GET /logon/LogonPoint/tmindex.htmlИдентификация NetScaler (токены Content-Security-Policy)
2GET /vpn/js/rdx/core/rdx.jsИдентификация NetScaler
3POST /cgi/samlauthпроба
4POST /cgi/samlauthконтроль, отправляется только после неисправленного сигнала

Перенаправления не отслеживаются, и никакой cookie никогда не отправляется обратно — NetScaler отдаёт просроченный NSC_DLGE, который воспроизводящий клиент перенёс бы в запрос 4, превратив POST в страницу входа.

nsppe записывает SAML POST в /var/log/ns.log на информационном уровне, без необходимости в отладочном переключателе, как сбой десериализации контекста nFactor, включая строку nFactor: ctx deserialize aaa_info, base64 decode failed. На этой длине нет строк создания сессии или входа, что и отличает сканирование от попытки обхода.

Как это работает

Исправление — это одна инструкция. При неудачной десериализации контекста уязвимая сборка переносит декодированную длину RelayState вперёд как статус запроса; исправленная сборка переносит константную ошибку 0xe0005, отображаемую как Malformed Assertion. Так что один POST разделяет их:

Ответ на пробуСборкаВердикт
500 Internal Server Error 43524неисправленнаяVULNERABLE
200 Malformed Assertion sent to NetscalerисправленнаяPATCHED

Исправленная сборка отвечает Malformed Assertion на любой длине, что и делает неисправленный ответ оракулом, а не совпадением.

Контроль — это то, что придаёт 500 значение

VULNERABLE опирается на единственный различающий ответ, поэтому инструмент проверяет, что ответ действительно зависит от того, что было отправлено. После неисправленного сигнала он повторяет запрос с контрольным RelayState той же 20-байтовой декодированной длины, отличающимся только 16 байтами после ctx=. Это содержимое отклоняется защитой перед десериализатором, поэтому каждая протестированная сборка — исправленная и неисправленная — отвечает на него 200 Malformed Assertion. Вердикт сохраняется только если два ответа различаются. Если они совпадают, что-то возвращает 500/43524 независимо от ввода, и результат — INCONCLUSIVE с тегом flat-response, а не ложный VULNERABLE. Удержание контроля на той же декодированной длине сохраняет его внутри проверенных рамок безопасности и изолирует содержимое как единственную переменную.

Защита односторонняя. Она не может подтвердить вердикт PATCHED, потому что по-настоящему исправленное устройство отвечает на пробу и контроль одинаково — это и означает быть исправленным здесь. См. Ограничения.

Он отвечает и на IdP-only virtual server

Десериализация RelayState выполняется до сопоставления политики SAML, поэтому virtual server, несущий только samlIdPPolicy, отвечает на пробу, а не только тот, у которого привязан service-provider samlAction. Это более широкое покрытие, чем может предложить проверка предусловий конфигурации.

Несовпадение — это никогда не утверждение о безопасности

Уязвимый ответ — единственный самоподтверждающийся: он несёт конкретный маркер, и контроль доказывает, что ответ зависит от того, что было отправлено. PATCHED — тоже положительное доказательство — собственная исправленная ошибка устройства на пути, которого достигла проба — но оно ограничено этим CVE и этим путём. INCONCLUSIVE и ERROR вообще не доказательства: проба так и не достигла десериализатора, поэтому состояние исправления неизвестно, и именно поэтому INCONCLUSIVE — отдельный вердикт, а не отнесён к PATCHED. Сообщать о молчании как о прохождении — значит ошибаться в опасном направлении. Там, где нужна определённость, подтвердите с помощью show ns version против сборок в Устранении.

Вердикты

Каждый вердикт несёт короткий тег reason. --brief печатает его третьей колонкой, а --json несёт его как reason.

ВердиктТег reasonЗначение
VULNERABLEinternal-error-43524Устройство передало декодированную длину RelayState как свою внутреннюю ошибку, и контроль той же длины доказал, что ответ зависит от того, что было отправлено. Исправление CTX696939 отсутствует — исправьте.
PATCHEDfixed-error-returnedУстройство вернуло исправленную ошибку на пути, которого достигла проба. Ограничено этим CVE, и см. Ограничения о промежуточных устройствах.
UNAFFECTEDno-saml-endpoint/cgi/samlauth вернул 404, поэтому потребитель SAML assertion здесь не обслуживается. На vserver, а не на устройство, и см. оговорку о старых сборках в Ограничениях.
INCONCLUSIVEflat-responseПроба и контроль той же длины ответили одинаково, поэтому ответ не зависит от того, что было отправлено. Срабатывание защиты от ложных срабатываний.
INCONCLUSIVEgeneric-internal-errorКонечная точка вернула 43549, свою общую внутреннюю ошибку, которую возвращают и исправленные, и неисправленные сборки. Не дискриминатор — и заметьте, что это есть неисправленный маркер для несвязанного CVE-2026-8452, поэтому выглядит как попадание, но им не является.
INCONCLUSIVEunrecognized-replyКонечная точка ответила чем-то вне распознанного набора.
INCONCLUSIVEno-probe-responseХост ответил на идентификацию, но не на пробу — тайм-аут, сброс или промежуточное устройство, отбрасывающее POST. Повторите.
ERRORnot-identifiedНе идентифицирован как NetScaler или недостижим.

Все четыре причины INCONCLUSIVE означают одно и то же для принятия решений — неизвестно, не исправлено. Тег называет, какое условие исправить перед повторным запуском.

Коды выхода

КодЗначение
0Ни одна цель не была VULNERABLE
1Как минимум одна цель VULNERABLE
2Ошибка использования (неверные аргументы / нечитаемый файл целей)

Выход 0 — не подтверждение безопасности. PATCHED, UNAFFECTED и все четыре причины INCONCLUSIVE сводятся к нему, и только одна из них — положительный результат. Обёртка, которой нужно отличить «исправлено» от «не удалось классифицировать», должна читать вердикт — первую колонку --brief или поле verdict из --json — а не код выхода.

Ограничения

  • WAF или балансировщик нагрузки может исказить вердикт PATCHED. Malformed Assertion — это то, что устройство возвращает всякий раз, когда проба не достигает десериализатора контекста, и исправленность — лишь одна из причин, почему это происходит. Промежуточное устройство, которое удаляет, искажает или замыкает параметр RelayState, поэтому выдаёт PATCHED на уязвимом устройстве, и никакой дополнительный запрос, который инструмент мог бы отправить, не разделил бы эти два случая. Там, где что-то может стоять перед устройством, подтвердите с помощью show ns version.
  • UNAFFECTED ограничено текущими сборками. На 14.1-43.55 / 13.1-61.27 и более ранних бюллетень утверждает, что подверженность вообще не требует SAML action — любой Gateway или AAA virtual server затронут — поэтому 404 на такой сборке не выводит устройство из области действия. Это положение взято из бюллетеня, а не измерено.
  • Это проверяет одно CVE, а не уровень исправлений устройства. PATCHED ничего не говорит о любой другой уязвимости NetScaler, включая CVE-2026-19489 из того же бюллетеня.
  • Не проверка эксплуатации и не проверка компрометации. VULNERABLE устанавливает, что исправление отсутствует на пути, которого достигла проба. Оно не измеряет, как далеко атакующий мог бы зайти с обходом на вашей конфигурации, и не скажет вам, не сделал ли это уже кто-то — ищите это в /var/log/ns.log отдельно.
  • Он не может сказать вам, достижимы ли ветви отказа в обслуживании. Инструмент отправляет одну проверенную длину и никогда не исследует другие, по замыслу.
  • Достижимость. Результат отражает то, что устройство предоставляет сетевой позиции, с которой вы его запускаете.

Устранение

Обновитесь до 13.1-63.21 или более поздней, либо 14.1-73.32 или более поздней (FIPS и NDcPP: 13.1-37.277 для 13.1-FIPS и 13.1-NDcPP, 14.1-73.32 FIPS для 14.1-FIPS), согласно CTX696939. Устройства на 12.1 или 13.0 не имеют исправления и не получат его — эти ветви сняты с поддержки и должны быть перенесены на поддерживаемую ветвь.

Три дополнительных замечания:

  • Исправьте оба узла пары HA. Неисправленный вторичный узел — это полностью подверженное устройство в момент, когда он берёт на себя управление.
  • Если вы не можете исправить сегодня, проверьте единственный глобальный переключатель, ограничивающий воздействие. Сессия, которую эта ошибка создаёт на Gateway virtual server, пропускает оценку политики сессии, поэтому она не подхватывает defaultAuthorizationAction любого vpn sessionAction, привязанного к vserver — она откатывается к глобальному set vpn parameter -defaultAuthorizationAction. Поставляемое значение по умолчанию — DENY; ALLOW распространён на практике, потому что это то, к чему администраторы прибегают вместо написания политик авторизации для каждого пользователя, и именно ALLOW позволяет неаутентифицированной сессии достичь внутренних ресурсов. Это глобально, а не на vserver. Это ограничивает воздействие; это не исправление.
  • Определяйте область инвентаризации по конфигурации SAML, а не по типу virtual server. Проверьте рабочую конфигурацию на add authentication samlAction и add authentication samlIdPProfile вместе с add authentication vserver и add vpn vserver — с учётом оговорки о старых сборках выше.

CTX696939 также исправляет CVE-2026-19489, и эта поверхность сильно пересекается с CVE-2026-8452 из предыдущего бюллетеня: на сборках с 14.1-43.56 / 13.1-61.28 и далее обе проблемы зависят от настроенного SAML action, поэтому один аудит конфигурации охватывает обе.

Лицензия

Этот код распространяется под лицензией MIT.

Правовая оговорка

Использование этого инструмента для атаки на цели без предварительного взаимного согласия незаконно. Это ответственность конечного пользователя — соблюдать все применимые местные, региональные и федеральные законы. Разработчики не несут ответственности и не отвечают за любое неправомерное использование или ущерб, вызванный этой программой.

См. также

  • Citrix CTX696939 — бюллетень безопасности NetScaler
  • NVD — CVE-2026-19490
  • NVD — CVE-2026-19489
  • NVD — CVE-2026-8452
Скачать инструмент