Skip to content
KitploitKITPLOIT
도구익스플로잇블로그
Log in
제출
도구익스플로잇블로그
제출

해킹, 침투 테스트 및 사이버 보안 도구를 당신의 보안 무기고에!

Kitploit은 해킹, 사이버 보안 및 침투 테스트 도구 디렉토리입니다. 최신 프로젝트 업데이트를 발견하여 취약점을 찾고, 시스템을 분석하고, 테스트를 자동화하고, 보안을 강화하세요.

피드문의개인정보© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
CVE-2026-19490-check — Citrix NetScaler SAML 인증 우회 CVE-2026-19490을 안전하게 탐지 | Kitploit
도구/GitHubGitHub/bishopfox/cve-2026-19490-check
Defensive ToolsVulnerability ScannersWeb Vulnerability ScannersVulnerability AnalysisInformation GatheringWeb SecurityNetwork SecurityPenetration TestingAuthentication
GitHubbishopfox/cve-2026-19490-check

CVE-2026-19490-check

22620일 전아직 검토되지 않음

인기

모두 보기 →

커뮤니티에서 가장 많이 사용되는 도구를 찾아보세요.

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

Citrix NetScaler SAML 인증 우회 CVE-2026-19490을 안전하게 탐지

저장소 보기

Citrix NetScaler SAML nFactor 컨텍스트 인증 우회 — 취약점 탐지 스크립트

Citrix NetScaler ADC / NetScaler Gateway SAML 서비스 제공자 경로의 사전 인증 인증 우회인 CVE-2026-19490에 대한 안전한 비인증 취약점 점검 도구입니다 (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). JPMorgan Chase 침투 테스트 팀의 Samarth Vashisht가 보고했습니다.

어플라이언스는 SAML 응답의 RelayState 파라미터를 base64 디코딩하고, 평문이 ctx=로 시작하면 나머지를 nFactor 컨텍스트 역직렬화기로 넘깁니다. 패치되지 않은 빌드에서는 역직렬화 실패 시 오류 대신 디코딩된 RelayState 길이가 요청의 내부 처리 코드로 전파되므로, 비인증 공격자는 단순히 RelayState의 길이를 선택하는 것만으로 어플라이언스가 다음에 어떤 내부 분기를 택할지 정할 수 있습니다. 일부 분기는 실제 Gateway 세션을 생성하고, 다른 분기는 패킷 엔진을 충돌시켜 어플라이언스를 재시작합니다. 이 스크립트는 둘 다 하지 않습니다 — 세션을 생성하지 않고 패킷 엔진에 영향을 주지 않는 것으로 검증된 단 하나의 길이를 전송하며, 대상마다 단 하나의 질문에 답합니다: 이 어플라이언스는 취약한가? VULNERABLE이 아닌 결과는 그 자체로 안전하다는 보증이 아닙니다.

사용법

# 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 가상 서버에 지정하세요, 관리 인터페이스가 아닙니다. 노출은 가상 서버별로 이루어지므로, 여러 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에서 빨간색으로 표시됩니다:

$ ./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

패치된 어플라이언스:

$ ./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)

오탐 방지 가드가 작동하는 경우. 프로브 와 동일 길이 대조군이 모두 미패치 신호를 반환했으므로, 응답이 전송된 내용에 의존하지 않으며 결정적으로 보이는 답변이 철회됩니다:

$ ./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 전용 가상 서버입니다 — 둘 다 응답하며, 이는 구성 사전 조건 점검으로는 처리할 수 없습니다:

$ ./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). 모든 요청이 포함되므로, 발견 사항을 신뢰하기보다 증거로부터 재도출할 수 있습니다. 대조군은 자체 판정이 아니라 프로브와의 관계로 기록됩니다. 패치된 빌드처럼 읽히는 대조군이 모든 빌드에서 예상되는 결과이기 때문입니다:

$ ./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를 일으키는 것이 포함됩니다 — 이는 전체 NetScaler를 재시작하고 약 45초 동안 트래픽을 끊습니다. 20바이트는 세션을 생성하지 않는 깨끗한 내부 오류 분기에 도달하며, 페이로드 빌더는 다른 길이를 구성하는 것을 거부하므로 다른 곳의 편집이 프로브를 조용히 확장할 수 없습니다.
  • 측정으로 검증됨. 20바이트 프로브는 패치되지 않은 13.1-63.18에 대해 연속 10회 실행되었으며 코어 생성이 전혀 없고 패킷 엔진 재시작도 없었습니다. 점검 자체는 이후 두 유지보수 브랜치에 대해, 수정 전후 양쪽에서, 그리고 서비스 제공자 및 IdP 전용 가상 서버 모두에 대해 실행되었으며, 어느 경우에도 패킷 엔진 재시작이 없었습니다.
  • 인증 없음, 자격 증명 자료 없음, 상태 변경 없음. 이 점검에서는 어떤 어설션, 서명, 타임스탬프, 세션, 클라이언트 인증서도 제시되지 않습니다. RelayState 분기에 도달하려면 SAMLResponse 파라미터가 존재해야 하지만 그 내용은 무관하므로, 4바이트의 쓰레기 데이터입니다. 이 분기는 쿠키를 발급하지 않고 구성을 기록하지 않습니다.
  • 오탐 방지 가드. VULNERABLE은 단일 응답으로 절대 보고되지 않습니다 — 대조군을 참조하세요.

프로브를 수정하는 경우, 디코딩된 RelayState 길이를 변경하지 말고 길이를 훑지 마세요. 20바이트는 핵심이며, 더 짧다고 더 안전하지 않습니다. 다른 길이는 최선의 경우 미검증이고 최악의 경우 어플라이언스 중단입니다.

요청 및 로그 흔적

대상당 세 개의 HTTP 요청, 그리고 어플라이언스가 미패치 신호를 반환할 때만 네 번째 요청:

#요청목적
1GET /logon/LogonPoint/tmindex.htmlNetScaler 식별 (Content-Security-Policy 토큰)
2GET /vpn/js/rdx/core/rdx.jsNetScaler 식별
3POST /cgi/samlauth프로브
4POST /cgi/samlauth대조군, 미패치 신호 이후에만 전송

리다이렉트는 따라가지 않으며 쿠키는 절대 되돌려 보내지 않습니다 — 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은 단일 구별 응답에 의존하므로, 도구는 응답이 실제로 전송된 내용에 의존하는지 검증합니다. 미패치 신호 이후 **동일한 20바이트 디코딩 길이의 대조군 RelayState**로 요청을 반복하며, ctx= 뒤의 16바이트만 다릅니다. 그 내용은 역직렬화기 앞의 가드에 의해 거부되므로, 테스트된 모든 빌드 — 패치됨과 미패치 — 가 200 Malformed Assertion으로 응답합니다. 두 응답이 다를 때만 판정이 유지됩니다. 일치하면 무언가가 입력과 무관하게 500/43524를 반환하는 것이며, 결과는 거짓 VULNERABLE이 아니라 flat-response 태그가 붙은 INCONCLUSIVE입니다. 대조군을 동일한 디코딩 길이로 유지하면 검증된 안전 범위 내에 머물고 내용을 유일한 변수로 격리합니다.

가드는 단방향입니다. PATCHED 판정을 검증할 수 없습니다. 진정으로 패치된 어플라이언스는 프로브와 대조군에 동일하게 응답하기 때문입니다 — 여기서 패치되었다는 것의 의미가 바로 그것입니다. 제한 사항을 참조하세요.

IdP 전용 가상 서버에서도 응답합니다

도구 다운로드