%GoCortexIO Snippets

Cortex XSIAM

Citrix NetScaler CVE-2026-88771 (pitboss) RCE Threat Hunt

| 30 minutes to implement | ~4 min read
markdown
> Make sure you're comfortable with the results in your own environment before using this more widely.

# Snippet | Citrix NetScaler CVE-2026-88771 RCE Threat Hunt

---

## Scenario: Production-ready Cortex XQL queries for Palo Alto Networks XSIAM to detect unauthenticated log injection and remote code execution (CVE-2026-88771) targeting Citrix NetScaler ADC and Gateway appliances, as detailed by CERT-EU.

---

### Threat Details

* **Vulnerability:** CVE-2026-88771 (CVSS 9.5 - Critical Unauthenticated RCE)
* **Target System:** Citrix NetScaler ADC and NetScaler Gateway (Customer-managed deployments)
* **Exploitation Technique:** Log Injection via `pitboss` authentication logs coupled with Base64 payload delivery in HTTP User-Agent / URI headers, executed by background diagnostic log parsers (`ns_monupload_err`).

---

### Capability Summary

This threat hunting package provides Cortex XQL queries engineered for XSIAM datasets (`citrix_netscaler_raw`, `panw_ngfw_url_raw`, and `xdr_data`). It targets the full attack lifecycle: from initial log injection into NetScaler authentication channels and Base64 staging in HTTP User-Agents, to the automated trigger execution via `ns_monupload_err` and post-exploitation web shell persistence.

---

**Reference:** [CERT-EU: Taking 'execute logging' a bit too literally — CVE-2026-88771](https://cert.europa.eu/blog/taking-execute-logging-a-bit-too-literally-cve-2026-88771)

---

## Threat Hunting Guide: NetScaler CVE-2026-88771 in Cortex XSIAM

### Exploitation Mechanics Breakdown

CVE-2026-88771 is an unauthenticated command injection vulnerability in Citrix NetScaler ADC and Gateway appliances. As documented by CERT-EU, exploitation occurs across a multi-stage race condition:

1. **Payload Staging:** The attacker sends high-frequency HTTP requests to the NetScaler gateway (e.g., `/logon/LogonPoint/tmindex.html`) carrying a Base64-encoded Bash command prefixed with `INDEX:` in the `User-Agent` header.

2. **Log Injection:** Simultaneously, the attacker sends crafted authentication requests to inject shell commands into the NetScaler syslog (`/var/log/ns.log` or `/var/log/messages`). The injected username contains commands such as `grep INDEX: /var/log/htt* | sed ... | b64decode -r | sh` appended after the log string `PPE missed too many heartbeats`.

3. **Trigger Execution:** When the NetScaler system process `ns_monupload_err` runs, it searches the log files for lines matching `PPE missed too many heartbeats`, extracts the last line (`tail -1`), and evaluates the string directly inside a shell (`sh`).
4. **Post-Exploitation Persistence:** The executed Bash script decodes the Base64 payload from the HTTP logs, modifies `/etc/httpd.conf` to enable the PHP engine (`php_engine`), and writes a persistent PHP web shell to an internet-accessible path.
markdown
> Make sure you're comfortable with the results in your own environment before using this more widely.

### XQL Hunting Queries for Cortex XSIAM

#### Query 1: Detect NetScaler Log Injection in Authentication & Syslog Data

This query searches NetScaler syslog logs for command injection syntax and the critical error signature (`PPE missed too many heartbeats`) referenced in CERT-EU's analysis.
xql
// Make sure you're comfortable with the results in your own environment before using this more widely.
dataset = citrix_netscaler_raw
| filter _raw_log contains "PPE missed too many heartbeats"
    or _raw_log contains "process_kernel_socket"
    or (
        _raw_log contains "INDEX:" 
        and (_raw_log contains "b64decode" or _raw_log contains "base64" or _raw_log contains "b64")
    )
| filter _raw_log contains "grep" 
    or _raw_log contains "sed" 
    or _raw_log contains "${IFS}" 
    or _raw_log contains "|sh" 
    or _raw_log contains "|bash"
| fields _time, reporter_ip, host, _raw_log
markdown
> Make sure you're comfortable with the results in your own environment before using this more widely.

#### Query 2: Hunt for Base64 Payload Staging in HTTP User-Agent / URI

This query inspects web server and gateway access logs for the INDEX: prefix inside the User-Agent string or URI path, which threat actors use to stage Base64 payloads prior to triggering code execution.
xql
// Make sure you're comfortable with the results in your own environment before using this more widely.
dataset = xdr_data
| filter (
        action_external_hostname contains "tmindex.html" 
        or action_process_image_command_line contains "tmindex.html"
        or action_file_path contains "tmindex.html"
        or action_process_image_command_line contins "INDEX:"
    )
    | fields _time, agent_hostname, action_local_ip, action_remote_ip, action_external_hostname, action_file_path, action_process_image_command_line
markdown
> Make sure you're comfortable with the results in your own environment before using this more widely.

#### Query 3: Correlated Hunt (Syslog Exploitation + Web Payload Staging)

This query correlates NetScaler syslog entries containing the INDEX: decoding pipeline with incoming web requests carrying INDEX: in the User-Agent within a short time window.
xql
// Make sure you're comfortable with the results in your own environment before using this more widely.
config time_range = 24h;
dataset = citrix_netscaler_raw
| filter _raw_log contains "INDEX:" and _raw_log contains "b64decode"
| fields _time as log_time, reporter_ip as netscaler_ip, _raw_log as injected_payload
| join type = inner (
    dataset = xdr_data
    | filter cs_user_agent contains "INDEX:" or cs_uri_path contains "INDEX:"
    | fields _time as web_time, src_ip as attacker_ip, dst_ip as netscaler_ip, cs_user_agent, cs_uri_path
) as web_events (netscaler_ip = web_events.netscaler_ip)
| fields log_time, web_time, attacker_ip, netscaler_ip, injected_payload, cs_user_agent, cs_uri_path

Earlier in this module

See all 21 snippets