ByteRay CQL Hub
← All queries

Citrix NetScaler - CVE-2026-88771 Pitboss Command-Injection String in Logs

CVE-2026-88771 is a pre-auth command injection in ns_monuploadd_err.pl. The script greps logs for 'pitboss.*PPE.*(missed too many heartbeats|unexpectedly died)', extracts a core-file name with sed/awk without validation, and interpolates it into a backtick find command as root. Any attacker-controlled logged value (login field, User-Agent, parameters) can carry the payload, so every exploit attempt must leave a line matching that grep. This query applies the exact grep and scores lines that deviate from a legitimate pitboss crash record.

CQL · Falcon Next-Gen SIEMCopy query
#Vendor=citrix #event.module=adc
  | @rawstring=/pitboss.*PPE.*(missed too many heartbeats|unexpectedly died)/iF
  | case {
      @rawstring=/\$\{?IFS|b64decode|base64/iF
        | ioc.match := "IFS/base64 space-evasion payload" | ioc.score := 100 ;
      @rawstring=/NSPPE[^\s(]*[;`|&$]/iF
        | ioc.match := "shell metacharacter after NSPPE token" | ioc.score := 95 ;
      @rawstring=/(login req|authenticate user|AAAD RESP|user:\s*<|User-?Agent|Browser_type|Username)/iF
        | ioc.match := "crash string inside auth/header field" | ioc.score := 85 ;
      @rawstring!=/pitboss.*NSPPE-\d{2}\s*\(\d+\).*(missed too many heartbeats|unexpectedly died)/F
        | ioc.match := "malformed crash record (fails patched-parser regex)" | ioc.score := 70 ;
      * | ioc.match := "well-formed PPE crash record" | ioc.score := 10 ;
  }
  | regex("(?:Client[_ ]?ip|ClientIP|Source|Remote_?ip)\s*:?\s*(?<ns.client_ip>\d{1,3}(?:\.\d{1,3}){3})", field=@rawstring, flags=i, strict=false)
  | regex("(?<ns.payload>pitboss.{0,200})", field=@rawstring, flags=i, strict=false)
  | ns.host := coalesce([log.syslog.hostname, host.name, observer.hostname, host.hostname])
  | ns.client_ip := coalesce([ns.client_ip, source.ip, client.ip])
  | default(field=[ns.host, ns.client_ip], value="-", replaceEmpty=true)
  | dataset := #event.dataset
  | groupBy([ns.host, dataset, ioc.match], function=[count(as=Events), max(ioc.score, as=Score), min(@timestamp, as=FirstSeen), max(@timestamp, as=LastSeen), collect([ns.client_ip], limit=50), selectLast([ns.payload])], limit=max)
  | formatTime("%F %T %Z", field=FirstSeen, as=FirstSeen)
  | formatTime("%F %T %Z", field=LastSeen, as=LastSeen)
  | table([Score, ns.host, dataset, ioc.match, Events, FirstSeen, LastSeen, ns.client_ip, ns.payload], limit=1000, sortby=Score, order=desc)

Score >= 70 means an exploit string was logged; treat as probable compromise because the payload executes on the next ns_monuploadd_err.pl run (up to ~24h later) regardless of an observed crash. Space-free payloads (${IFS}, base64) are expected because awk splits on whitespace. Score 10 rows are well-formed PPE crash records - context for CVE-2026-88772 and the DoS CVEs, not exploitation. nsaaad lines often lack a client IP; pivot on timestamp to adjacent adc.sslvpn / adc.aaatm lines. Requires local0 and local1 syslog facilities forwarded. False positives: none expected at >= 85; 70 may catch unusual firmware log formats.

Citrix_NetScaler_CVE_2026_88771_Pitboss_Command_Injection_String_in_Logs.yml
T1190, T1059.004, T1027.010
Travis Baldwin
Hunting, Monitoring, Detection
Network
2026-09-28
2026-09-28

Get this query running in your SIEM, with someone on call.

Our Managed SIEM team operates CrowdStrike Falcon Next-Gen SIEM in production, with over 350 battle-tested use cases and 24/7 incident response behind them.

Talk to the SIEM team