Skip to content
KitploitKITPLOIT
FerramentasBlog
Enviar
FerramentasBlog
Enviar

Ferramentas de Hacking, PenTest e Cibersegurança para o seu Arsenal de Segurança!

Kitploit é um diretório de ferramentas de hacking, cibersegurança e pentesting. Descubra as últimas atualizações de projetos para encontrar vulnerabilidades, analisar sistemas, automatizar testes e fortalecer sua segurança.

··Feeds·Contato·Privacidade·© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
CVE-2026-19490 — NetScaler ADC/Gateway bypass de asserção SAML não assinada via binding HTTP-Redirect (CTX696939) - análise de causa raiz + PoC | Kitploit
Ferramentas/GitHubGitHub/tarpeg007/cve-2026-19490
Análise de VulnerabilidadesExploraçãoExploração de Aplicações WebTestes de PenetraçãoAnálise de BináriosAutenticaçãoRed Teaming
GitHubtarpeg007/cve-2026-19490

CVE-2026-19490

NetScaler ADC/Gateway bypass de asserção SAML não assinada via binding HTTP-Redirect (CTX696939) - análise de causa raiz + PoC

Ver Repositório
1há 9h 4mAinda não revisado

Mais Populares

Ver todos →

Descubra as ferramentas mais usadas pela nossa comunidade.

Explore todas as ferramentas

Navegue pela nossa coleção de ferramentas

Ver todas as ferramentas →
Compartilhar

CVE-2026-19490 — Bypass de autenticação SAML no NetScaler ADC/Gateway

Falsificação de sessão não autenticada no Citrix NetScaler ADC / NetScaler Gateway via o manipulador de binding HTTP-Redirect SAML em GET /cgi/samlauth. CVSS 4.0 9.3, CWE-288. Boletim CTX696939 (2026-08-19), sem workarounds. O crédito pelo relatório original vai para Samarth Vashisht (equipe de pen-test do JPMorgan Chase); a análise de causa-raiz e o código neste repositório são de minha autoria.

Afetados: 14.1 antes de 14.1-73.32, 13.1 antes de 13.1-63.21. Corrigido nessas duas versões.

causa raiz

Duas coisas dão errado juntas no nsppe, o motor de pacotes.

1. o binding de redirect analisa as asserções com o flag strict desativado.

Todos os pontos de chamada do parser de resposta SAML (sub_b40a50) configuram um argumento "strict" antes da chamada. O caminho do binding POST (o que os navegadores realmente usam para respostas SAML) o passa ativado. O caminho do binding HTTP-Redirect não:

root@kitploit:~
$ objdump -d -M intel --start-address=0xb7f532 --stop-address=0xb7f558 nsppe-14.1-73.30
  b7f532: 41 b8 00 00 00 00     mov    r8d,0x0          <-- strict OFF
  b7f538: 48 8d 8d d8 fe ff ff  lea    rcx,[rbp-0x128]
  b7f53f: 48 8b 95 b8 fe ff ff  mov    rdx,[rbp-0x148]
  b7f546: 8b b5 cc fe ff ff     mov    esi,[rbp-0x134]
  b7f54c: 48 8b 3d f5 9f 6f 02  mov    rdi,[rip+0x26f9ff5]
  b7f553: e8 f8 14 fc ff        call   b40a50            <-- o parser

Esse é o caminho alternativo no sentido da CWE-288. Mesma superfície de requisição, invocação de parser mais fraca, alcançável por qualquer pessoa que possa enviar um GET com um parâmetro de consulta SAMLResponse.

2. a porta de verificação de asserção não assinada trata a configuração padrão como ALLOW.

Dentro do manipulador de redirect, quando a requisição não carrega SigAlg/Signature, a palavra de configuração para rejectUnsignedAssertion é comparada e ramificada assim:

root@kitploit:~
$ objdump -d -M intel --start-address=0xb7ee3b --stop-address=0xb7ee41 nsppe-14.1-73.30
  b7ee3b: 83 78 08 02           cmp    DWORD PTR [rax+0x8],0x2
  b7ee3f: 74 5d                 je     b7ee9e            <-- pula para o caminho ACCEPT

Os valores da palavra são: 2 = rejectUnsignedAssertion ON (o padrão), 3 = STRICT. O je envia 2 para aceitar. Apenas STRICT alcança a linha de log de negação:

root@kitploit:~
$ strings -t x nsppe-14.1-73.30 | grep 'denying as per action'
  2020998 SAMLIDP: Redirect Binding: Unsigned Assertion seen, denying as per action %s

Então, em uma máquina com configuração padrão, uma asserção não assinada entregue ao binding de redirect é analisada (strict desativado), aceita pela porta de não assinatura (ON mal interpretado como permitir) e então executa as etapas pós-análise comuns: verificações de emissor/audiência/sujeito contra a configuração da ação SAML, e então a construção da sessão a partir de campos fornecidos pelo atacante. Sem digest, sem verificação RSA, em qualquer ponto dessa rota. O binding POST não é afetado da mesma forma — ele passa strict ao parser e rejeita entrada não assinada corretamente.

Pré-condições conforme o boletim, confirmadas contra o binário: builds a partir de 14.1-43.56 / 13.1-61.28 precisam de uma ação SAML vinculada a um vserver Gateway ou AAA (a configuração normal de SSO SAML, então a maioria das implantações SAML se qualifica). Builds anteriores registram a rota apenas com o vserver.

formato do exploit

Um único GET. Construa uma Resposta SAML sem nenhum <ds:Signature> em qualquer lugar, aplique DEFLATE + base64 e envie:

root@kitploit:~
GET /cgi/samlauth?SAMLResponse=<b64(raw-deflate(xml))>&RelayState=<ctx> HTTP/1.1
Host: <gateway>

Os valores que devem corresponder à configuração da ação SAML do alvo: Issuer da asserção = o entity ID do IdP, Audience = o entity ID do SP, Recipient/Destination = a URL do ACS, e em configurações transacionais um InResponseTo de uma AuthnRequest ativa. --mint percorre o redirect de login pré-autenticação do próprio gateway para capturar esses valores (o SAMLRequest no cabeçalho Location carrega todos eles). Um 302 para /vpn/ mais um cookie NSC_AAAC / NSC_TASS real (não os marcadores de exclusão xyz) é uma sessão forjada como qualquer NameID que você colocar.

uso

root@kitploit:~
pip install requests

# o endpoint existe e o binding GET processa SAMLResponse de alguma forma
python3 poc.py https://vpn.target.com --check-only

# sonda de configuração não intrusiva: asserção não assinada com um issuer deliberadamente ERRADO.
#   'Malformed Assertion' (0xe0005)  -> STRICT, não vulnerável a este vetor
#   erro de issuer/policy (0xe0012)  -> configuração padrão, vulnerável; nenhuma sessão emitida
python3 poc.py https://vpn.target.com --safe-oracle

# cadeia completa (apenas alvos autorizados): emite a cadeia do SP, forja, valida uma vez
python3 poc.py https://vpn.target.com --mint --name-id [email protected]

--safe-oracle existe porque as duas configurações retornam páginas de erro diferentes antes que qualquer coisa com formato de sessão aconteça, o que também é como os defensores podem fazer autoverificação sem tocar em um IdP real. Execute-o contra seu próprio equipamento.

demonstração

demo/demo.gif (também demo.mp4, e demo/demo.cast se quiser reproduzi-lo com asciinema play): build afetado a partir da imagem docker, a configuração padrão de palavra-2, os dois branches binários desmontados do nsppe enviado, e a verificação de endpoint do PoC. A última milha, emissão de sessão, precisa de um VPX licenciado — o CPX Express recusa sessões AAA na camada de licença — que é o que lab/record-demo.sh captura quando você tem um.

laboratório

lab/setup-cpx.sh sobe exatamente o build afetado no docker:

root@kitploit:~
docker run -dt --privileged --name cpx19490 -e EULA=YES \
    quay.io/netscaler/netscaler-cpx:14.1-73.30
bash lab/setup-cpx.sh

e configura uma ação SAML com rejectUnsignedAssertion ON, uma policy e um vserver Gateway. Duas ressalvas aprendidas da maneira difícil:

  • O CPX Express não carrega licença de usuário SSLVPN/AAA. O vserver serve /cgi/samlauth mas toda requisição cai em 480 Login exceeds maximum allowed users. Bom o suficiente para reproduzir configuração + endpoint + estado binário, não o cookie de sessão final.
  • Para a execução completa de emissão de sessão você quer um VPX com a licença gratuita Developer Edition (My Citrix → downloads → NetScaler VPX, depois CTX587663 para o fluxo de licença). Mesma CLI do script de configuração, então lab/record-demo.sh grava toda a sequência asciinema: versão, configuração, safe-oracle, sessão forjada, controle negativo STRICT.

Os offsets do binário enviado acima vêm direto dessa imagem:

root@kitploit:~
docker cp cpx19490:/var/netscaler/bins/nsppe ./nsppe-14.1-73.30
objdump -d -M intel --start-address=0xb7ee3b --stop-address=0xb7ee41 ./nsppe-14.1-73.30

detecção / mitigação

  • Atualize para 14.1-73.32+ / 13.1-63.21+. Não há workaround suportado.
  • set samlAction <name> -samlRejectUnsignedAssertion STRICT bloqueia o vetor de redirect no caminho vulnerável (torna a palavra == 3). Esteja ciente de que STRICT também muda o que a máquina espera do seu IdP (requisitos de assinatura de Response + Assertion), o que presumivelmente é o motivo pelo qual a Citrix envia ON como padrão e por que "apenas defina STRICT" não é um workaround limpo para todos.
  • Detecte: requisições a /cgi/samlauth carregando SAMLResponse em GET (respostas de binding de redirect são raras na natureza — navegadores fazem POST), payloads não assinados e o diferencial de página de erro acima.

legal

Apenas para testes de segurança autorizados: seu próprio laboratório, ou alvos explicitamente no escopo de um programa no qual você está autorizado. O autor não é afiliado à Citrix nem à equipe de relato original.

linha do tempo

  • 2026-08-19 — Boletim CTX696939 da Citrix, correções enviadas
  • 2026-09 — este writeup de causa-raiz e PoC

Licença MIT, veja LICENSE.

Baixar ferramenta