Citrix NetScaler ADC and Gateway Three Zero-Days Exploited With WHIPSHOT and SLAPSHOT Malware Across Government and Financial Sectors
Three zero-day vulnerabilities in Citrix NetScaler ADC and NetScaler Gateway have been exploited in the wild since at least early September 2026. Two critical remote code execution flaws, CVE-2026-88771 and CVE-2026-88772 (both CVSS v4.0 9.5), were disclosed and patched on September 27 [1][8]. A third flaw, CVE-2026-88779 (CVSS 8.7), a SAML-related denial-of-service vulnerability, was disclosed October 3 and patched October 4 [9][12]. All three are listed in CISA's Known Exploited Vulnerabilities catalog. Mandiant Consulting and Google Threat Intelligence Group (GTIG) have documented intrusions affecting dozens of organizations in government, financial services, technology, education, and legal/professional services across North America and Europe [4][5]. The attackers deployed two previously undocumented malware families: WHIPSHOT, a PHP webshell, and SLAPSHOT, a Python-based TCP tunneler [3][4]. No public attribution to a named threat group has been made [5][6].
Patching closes the vulnerability but does not remove implants, modified Apache configurations, or stolen credentials left during the pre-disclosure exploitation window. Researchers warn that updates "will not remove access for attackers that have already established persistence" [1][21]. Palo Alto Cortex Xpanse identified 50,277 internet-exposed NetScaler instances as of September 27 [1], and Shadowserver Foundation telemetry shows more than 23,000 appliances still directly exposed to the public internet [15].
Background
NetScaler ADC and NetScaler Gateway are perimeter appliances handling VPN termination, remote access, load balancing, and authentication. Compromise gives attackers a staging point for credential theft, lateral movement, and persistent internal access. These products have been repeatedly targeted: the 2023 zero-day campaign exploiting CVE-2023-4966 ("Citrix Bleed") demonstrated the pattern of silent exploitation followed by persistent implants that survive patching.
Before Citrix's September 27 public bulletin, national cybersecurity agencies, CERTs, IT suppliers, and security teams were privately warning NetScaler customers to shut down or isolate affected appliances [8]. watchTowr confirmed it had credible information that multiple NetScaler RCE zero-days were being exploited before any public advisory existed. The Dutch National Cyber Security Center (NCSC-NL) reportedly warned organizations about two critical NetScaler zero-days without CVE IDs, noting that threat actors were placing shellcode directly into memory [8]. Citrix's Sunday disclosure blog post included a noindex meta tag instructing search engines not to index the page [8].
Mandiant CTO Charles Carmakal warned of "broad and opportunistic exploitation of CVE-2026-88772 and CVE-2026-88771 by a variety of threat actors in the near term" [5]. Security researcher Kevin Beaumont suggested the attacks may be espionage-motivated, though no formal attribution was given by CERT-EU, Google, or Mandiant [2].
CVE-2026-88771 (CVSS v4.0: 9.5)
Improper input validation (CWE-20) allowing an unauthenticated attacker to execute arbitrary commands. No precondition: default configurations are vulnerable. Attack complexity is low, meaning reliable RCE is likely against all vulnerable appliances regardless of configuration [20]. Exploitation was confirmed to have begun September 5, 2026, twenty-two days before public disclosure [22]. No published workaround exists; IP restriction or disconnecting from the internet were the only interim mitigations pending upgrade [21].
CVE-2026-88772 (CVSS v4.0: 9.5)
Memory overflow (CWE-119) in DTLS protocol handling within the NetScaler Packet Processing Engine (NSPPE). Requires DTLS to be enabled, which is the default on VPN virtual servers[20]. Attack complexity is rated high [20]. Malformed or fragmented DTLS record headers sent during the pre-authentication handshake corrupt heap memory in the NSPPE, diverting execution to attacker-controlled shellcode running with root privileges on the appliance's FreeBSD operating system [7][4]. Google reported that exploitation of CVE-2026-88772 bypasses authentication and achieves root-level access on the appliance [4].
CVE-2026-88779 (CVSS v4.0: 8.7)
Memory overflow vulnerability in SAML processing affecting NetScaler deployments configured as a SAML Service Provider or SAML Identity Provider [11][14]. Citrix disclosed this October 3 after administrators noticed recently patched appliances unexpectedly rebooting [11]. watchTowr Labs reproduced the vulnerability after investigating honeypot activity [11]. A single specially crafted request is enough to knock an appliance offline; repeated triggering renders the service unavailable [9][11]. Researchers are investigating whether the flaw can also enable remote code execution [11]. CISA added CVE-2026-88779 to KEV on October 4 with a federal remediation deadline of October 7.
Rapid7 reported that threat actors are chaining CVE-2026-88779 with CVE-2026-88771, combining a pre-authentication log-poisoning injection with a SAML-parsing crash. This means appliances patched for the first two CVEs but not for CVE-2026-88779 are still targetable.
Additional CVEs in CTX697096
Six more vulnerabilities were disclosed in the same bulletin. None are confirmed exploited, but several carry high CVSS scores [12][24]:
| CVE | Description | Precondition | CVSS v4.0 |
|---|---|---|---|
| CVE-2026-88773 | HTTP request smuggling (CWE-444) | HTTP configuration enabled | 9.3 |
| CVE-2026-88774 | Feature policy bypass via HTTP URL expression (CWE-16) | HTTP configuration enabled | 7.0 |
| CVE-2026-88775 | Memory overflow, DoS (CWE-119) | Gateway or AAA virtual server | 8.8 |
| CVE-2026-88776 | Memory overflow, DoS (CWE-119) | LB virtual server of type Oracle | 8.8 |
| CVE-2026-88777 | Memory overflow, DoS (CWE-119) | LB/CS or CGNAT-LSN/NAT64 with non-HTTP L7 | 8.8 |
| CVE-2026-88778 | TCP ISN prediction (CWE-342) | TCP configuration enabled | 8.8 |
Fixed Versions
For CVE-2026-88771 and CVE-2026-88772: NetScaler ADC and Gateway 14.1-73.37 and later, 13.1-64.23 and later, 14.1-73.37 FIPS, and 13.1-37.279 FIPS/NDcPP [6][21].
For CVE-2026-88779: NetScaler ADC and Gateway 14.1-73.41 and later, 13.1-64.28 and later, 14.1-73.41 FIPS, and 13.1-37.282 FIPS/NDcPP [11][14]. Organizations that already patched for CTX697096 must upgrade again to address CVE-2026-88779 [13][26].
Initial Access and Root Compromise
Exploitation of CVE-2026-88772 causes heap memory corruption in the NSPPE process during the pre-authentication DTLS handshake. The attacker's shellcode executes with root privileges on the underlying FreeBSD OS [4][7]. GreyNoise observed exploitation from 149.104.78.141 on September 24, three days before public disclosure [3]. Unit 42 telemetry shows pre-disclosure attacker requests continuing around the clock, with the last arriving at 01:54 UTC on September 27, hours before Citrix published CTX697096 [1].
Persistence via Apache Configuration Modification
Attackers modified /etc/httpd.conf to register .deb and .sig file extensions as PHP handlers, allowing webshells to execute from NetScaler client software directories [3]. URL aliases mapped seemingly benign icon requests (e.g., /vpn/media/<name>.ico) to malicious .sig payloads stored in VPN script directories [3][7]. This technique blends webshells into paths and extensions associated with legitimate NetScaler components.
GreyNoise observed an attack chain setting SUID and SGID on /bin/sh before installing a password-protected hidden webshell [7].
WHIPSHOT Webshell
WHIPSHOT is a PHP webshell stored without a .php extension at /var/netscaler/logon/LogonPoint/custom/.ctxs.receiver [22][20]. An Apache Alias directive maps receiver.min.css requests to this file, making it indistinguishable from a legitimate CSS stylesheet in server logs [22]. WHIPSHOT hides Base64-encoded commands inside HTTP headers (specifically HTTP_X_UX*, HTTP_NSC_CLIENTTYPE, and HTTP_NSC_LDAP headers) and can return spoofed HTTP 404 responses to disguise activity [3][16][19]. It reads a dynamic TCP port recorded in /tmp/.uxdport and connects to 127.0.0.1:<port> to relay client requests to SLAPSHOT [4].
SLAPSHOT Tunneler
SLAPSHOT is a Python-based TCP tunneling tool that bridges the compromised appliance and internal network devices for reconnaissance and credential theft [3][4]. In at least one observed intrusion, the threat actor routed traffic through this proxy to manually conduct internal reconnaissance and credential theft [4][6]. SLAPSHOT listens locally and coordinates with WHIPSHOT through /tmp/.uxdport and /tmp/.uxdlock files [3][4].
Log-Poisoning Injection
Sygnia identified exploit attempts appearing as fabricated PPE failure messages containing attacker-controlled shell commands, including the patterns unexpectedly died and missed too many heartbeats [27]. Sygnia also discovered a new variant using the unexpectedly died command pattern for configuration exposure, remote payload execution, and command-execution validation [27].
Indicators of Compromise
The following IOCs are drawn verbatim from the cited source material. This is not an exhaustive list; community tools aggregate additional indicators from over a dozen vendor reports [18][19].
| Type | Value | Context | Source |
|---|---|---|---|
| IP | 149.104.78.141 |
Pre-disclosure exploitation source | [3][7] |
| IP | 77.83.199.39 |
Early fingerprinting host | [1] |
| IP | 104.248.244.66 |
Early fingerprinting host | [1] |
| IP | 139.180.152.138 |
Dropped PHP webshell | [1] |
| IP | 45.61.136.143 |
Citrix bulletin network indicator | [1] |
| IP | 66.227.183.84 |
Citrix bulletin network indicator | [1] |
| IP | 216.245.184.164 |
Citrix bulletin network indicator | [1] |
| IP | 45.141.21.130 |
C2 reverse shell destination | [22] |
| IP | 213.209.159.55 |
Payload download in SAML exploit | [11] |
| IP | 78.128.113.10 |
Attacker IP | [19] |
| IP | 149.104.78.208 |
Failed login attempt source | [20] |
| Domain | echvista.com |
Attacker infrastructure | [19] |
| Domain | gsocket.io |
Attacker infrastructure | [19] |
| Domain | pylrk.cc |
Attacker domain | [19] |
| Filename | /var/netscaler/logon/LogonPoint/custom/.ctxs.receiver |
WHIPSHOT webshell disk path | [20][22] |
| Filename | /tmp/.uxdport |
SLAPSHOT port coordination file | [3][4] |
| Filename | /tmp/.uxdlock |
SLAPSHOT lock file | [3] |
| Filename | slapshot.py |
SLAPSHOT tunneler component | [19] |
| Filename | receiver.min.css |
Apache alias for WHIPSHOT webshell | [22] |
| Filename | /etc/httpd.conf |
Modified by attacker for PHP handler registration | [3] |
| Filename | insight-new.js |
Payload file for writing stolen data | [19] |
| Malware | WHIPSHOT | PHP webshell, HTTP header C2 | [3][4] |
| Malware | SLAPSHOT | Python TCP tunneler | [3][4] |
MITRE ATT&CK Mapping
| Technique ID | Technique Name | Observed Activity |
|---|---|---|
| T1190 | Exploit Public-Facing Application | Exploitation of CVE-2026-88771 and CVE-2026-88772 against internet-facing NetScaler appliances [4][16] |
| T1133 | External Remote Services | NetScaler Gateway provides remote access services exploited for initial access [16] |
| T1505.003 | Server Software Component: Web Shell | WHIPSHOT PHP webshell deployed for persistent access [3][4] |
| T1059.004 | Command and Scripting Interpreter: Unix Shell | Shell commands executed via log-poisoning injection and webshell [27] |
| T1059.006 | Command and Scripting Interpreter: Python | SLAPSHOT written in Python for TCP tunneling [3][4] |
| T1071.001 | Application Layer Protocol: Web Protocols | C2 payloads hidden in HTTP headers by WHIPSHOT [4][16] |
| T1090 | Proxy | SLAPSHOT proxies traffic into internal networks [4][6] |
| T1027 | Obfuscated Files or Information | Base64-encoded payloads in HTTP headers [4] |
| T1036.005 | Masquerading: Match Legitimate Name or Location | Webshells disguised as CSS files and Debian packages via Apache Alias directives [22][3] |
| T1105 | Ingress Tool Transfer | Remote payload download and webshell staging [7] |
| T1548.001 | Abuse Elevation Control Mechanism: Setuid and Setgid | SUID/SGID set on /bin/sh before webshell installation [7] |
| T1070.004 | Indicator Removal: File Deletion | Attackers ran cleanup commands to delete traces; cron jobs scheduled to erase forensic evidence [22][25] |
Log-Based Detection
Search NetScaler ns.log and nsvpn.log for fabricated PPE failure messages containing the strings unexpectedly died and missed too many heartbeats, which are used as injection vectors [27]. Look for SSL_HANDSHAKE_FAILURE/DTLSv1.0 entries that correlate with NSPPE termination events [18].
Filesystem Indicators
On the appliance, check for:
- Hidden files in
/var/netscaler/logon/LogonPoint/custom/, especially.ctxs.receiver[20][22] .debor.sigfiles containing PHP code under/var/netscaler/gui/vpn/scripts/linux/[2][3]- Presence of
/tmp/.uxdportand/tmp/.uxdlock[3][4] - Unauthorized
AddHandler,AddType,Alias, orAliasMatchdirectives in/etc/httpd.confmapping non-PHP extensions to the PHP engine [3] - Unexpected files in
/nsconfig/.slap/includingboot.shpersistence scripts [19]
Network Detection
Monitor for HTTP requests to receiver.min.css paths that return response sizes or headers inconsistent with actual CSS content. Alert on HTTP responses returning 404 status codes with non-zero or abnormally large response bodies from NetScaler LogonPoint paths, which may indicate WHIPSHOT's spoofed 404 behavior [3][16].
Community Hunt Tools
Two open-source tools compile indicators from multiple vendor reports and can be run against live appliances or offline evidence:
netscaler_threat_hunt_helperby orjanj: bash-based IoC scanner covering CTX697096 and CTX697174 indicators [18]netscaler-ctx697096-checkerby Thomas Poppelgaard: read-only precondition and exposure checker aggregating indicators from over a dozen sources, including roughly 32 confirmed attacker IPs and the domainechvista.com[19]
Sigma Rule
CISA updated its alert to provide a Sigma detection rule resource for identifying suspicious activity on NetScaler appliances. Organizations should obtain this rule from CISA's alert page and deploy it alongside the community tools referenced above.
YARA Detection
Google published a YARA rule (G_APT_Backdoor_Webshell_WHIPSHOT_1) to detect the WHIPSHOT PHP webshell on NetScaler ADC appliances [4]. Deploy this rule against filesystem snapshots of NetScaler appliances during compromise assessment.
Analysis
The timeline is operationally significant. Citrix confirmed exploitation of CVE-2026-88771 began September 5 [22]. Public disclosure came September 27 [1][8]. That twenty-two-day window gave attackers uncontested access to every unmitigated internet-facing NetScaler appliance worldwide. The appearance of CVE-2026-88779 just six days after the initial patch forced organizations through a second emergency upgrade cycle, with Rapid7 confirming that the two campaigns are being chained together.
The attacker tooling is purpose-built for perimeter appliance persistence. WHIPSHOT's use of non-PHP file extensions, Apache alias manipulation, and HTTP header-based C2 channels shows a clear understanding of NetScaler's internal architecture. SLAPSHOT's tunneling capability transforms a compromised edge appliance into a proxy for internal network access, which is the primary risk associated with VPN appliance compromise.
Mandiant had not attributed the activity to a named threat group as of its September 29 report [6]. Kevin Beaumont suggested espionage motivation [2]. The targeting profile (government, financial services, education, legal sectors across North America and Europe) and the custom tooling are consistent with state-aligned activity, though multiple actors are likely now exploiting these vulnerabilities given the public disclosure [5].
SC World reported that the rapid emergence of three exploited NetScaler vulnerabilities in roughly a week indicates attackers are focused on this product line and moving as fast as Citrix can ship fixes [10].
Red Sheep Assessment
Confidence: Moderate
The pre-disclosure exploitation window, custom malware families, and targeting of government and financial-services organizations collectively suggest at least one state-aligned actor was likely responsible for the initial campaign. The lack of public attribution from Mandiant, GTIG, or CERT-EU is notable: these organizations typically attribute when they can, and their silence suggests either insufficient evidence for confident attribution or active intelligence equities. The rapid appearance of CVE-2026-88779 within days of the initial patch, combined with Rapid7's confirmation of chaining behavior, points to an actor (or actors) with deep familiarity with the NetScaler codebase and the ability to develop new exploits under time pressure.
The most concerning aspect is not the vulnerabilities themselves but the persistence gap. Every NetScaler appliance compromised between September 5 and September 27 likely still contains attacker implants, even after patching. Organizations that patched promptly on September 27 and declared victory probably still have WHIPSHOT webshells active in their environments. Reporting indicates that credentials stolen before patching remain valid, compounding the risk: patching stops new exploitation but does nothing about lateral movement, credential reuse, or internal access already established [4][21].
A contrarian read: the DoS-only classification of CVE-2026-88779 may be overly conservative. Researchers are actively investigating whether it can enable RCE [11], and SC World reported that the DoS bug may be used to force reboots and accelerate exploitation of CVE-2026-88771 [10]. The chaining behavior reported by Rapid7 supports this interpretation. Defenders should treat CVE-2026-88779 as potentially enabling code execution until proven otherwise.
Defender's Checklist
- ▢[ ] Upgrade all NetScaler ADC and Gateway appliances to 14.1-73.41 or 13.1-64.28 (or the corresponding FIPS/NDcPP builds) to address all three exploited CVEs. The September 27 patch alone does not cover CVE-2026-88779 [11][13].
- ▢[ ] Conduct a full compromise assessment on every appliance that was internet-facing before patching. Search for WHIPSHOT artifacts at
/var/netscaler/logon/LogonPoint/custom/.ctxs.receiver, check/etc/httpd.conffor unauthorized PHP handlers and aliases, and scan for/tmp/.uxdportand/tmp/.uxdlockfiles. Use the community IoC scanners [18][19] and Google's YARA ruleG_APT_Backdoor_Webshell_WHIPSHOT_1[4].
- ▢[ ] Rotate all credentials that transited the NetScaler appliance, including LDAP bind accounts, RADIUS shared secrets, SSL/TLS private keys, and any user passwords authenticated through the appliance during the exposure window. Researchers report stolen credentials remain valid after patching [4][21].
- ▢[ ] Hunt in DNS, proxy, and firewall logs for connections to known attacker infrastructure, specifically
149.104.78.141,45.141.21.130,echvista.com,gsocket.io, andpylrk.cc[3][19][22]. Query SIEM for the full IP list published in community trackers [19].
- ▢[ ] Preserve forensic evidence (memory dumps,
/var/nslog/,/var/log/,/etc/httpd.conf,/nsconfig/) before applying updates. Updates may overwrite artifacts needed for incident investigation[21].
References
[1] https://unit42.paloaltonetworks.com/netscaler-zero-days-exploited/
[2] https://www.esentire.com/security-advisories/update-ongoing-exploitation-of-citrix-netscaler-adc-and-netscaler-gateway-vulnerabilities-cve-2026-88771-cve-2026-88772
[3] https://www.bleepingcomputer.com/news/security/hackers-exploit-citrix-netscaler-zero-day-to-deploy-web-shells/
[4] https://cloud.google.com/blog/topics/threat-intelligence/defending-against-active-exploitation-of-citrix-netscaler-adc-and-gateway-appliances
[5] https://www.infosectoday.io/attackers-exploit-netscaler-flaw-for-root-access-deploy-whipshot-and-slapshot
[6] https://aicybr.com/blog/citrix-netscaler-whipshot-slapshot-active-exploitation
[7] https://cyberpress.org/hackers-exploit-citrix-netscaler-zero-days/
[8] https://www.bleepingcomputer.com/news/security/cisa-orders-feds-to-patch-exploited-citrix-flaws-by-wednesday/
[9] https://cyberscoop.com/citrix-netscaler-third-exploited-zero-day-vulnerability/
[10] https://www.scworld.com/news/new-citrix-netscaler-zero-day-exploited-just-days-after-recent-attacks
[11] https://www.bleepingcomputer.com/news/security/citrix-patches-netscaler-saml-zero-day-exploited-in-attacks/
[12] https://www.tenable.com/blog/frequently-asked-questions-about-reported-citrix-netscaler-zero-day-vulnerabilities
[13] https://www.hipaajournal.com/citrix-patches-third-actively-exploited-netscaler-zero-day/
[14] https://thehackernews.com/2026/10/new-netscaler-zero-day-exploited-in.html
[15] https://www.unboxfuture.com/2026/10/citrix-netscaler-zero-day-emergency.html
[16] https://www.hendryadrian.com/defending-against-active-exploitation-of-citrix-netscaler-adc-and-gateway-appliances/
[17] https://aviatrix.ai/threat-research-center/citrix-netscaler-cve-2026-88772-zero-day-web-shells/
[18] https://github.com/orjanj/netscaler_threat_hunt_helper
[19] https://github.com/ThomasPoppelgaard/netscaler-ctx697096-checker
[20] https://www.rapid7.com/blog/post/etr-zero-day-exploitation-of-citrix-netscaler-adc-and-gateway-cve-2026-88771-and-cve-2026-88772/
[21] https://hard2bit.com/en/blog/netscaler-cve-2026-88771-88772-patch-does-not-remove-web-shell/
[22] https://www.decryptiondigest.com/blog/netscaler-backdoor-persists-after-patching-whipshot
[23] https://github.com/ThomasPoppelgaard/netscaler-ctx697096-checker/releases/tag/1.9
[24] https://pentestit.com/analysis-cve-2026-88771-and-cve-2026-88772/
[25] https://www.prophetsecurity.ai/blog/citrix-netscaler-zero-day
[26] https://www.poppelgaard.com/cve-2026-88771-through-cve-2026-88778-what-you-should-know-and-how-to-fix-your-netscaler-adc-netscaler-gateway
[27] https://www.sygnia.co/threat-reports-and-advisories/actively-exploited-netscaler-vulnerabilities/
Event Timeline
Timeline
Entity Relationships
Entity Graph (27 entities, 42 relationships)
Diamond Model
Diamond Model
Hunt Guide: Citrix NetScaler ADC and Gateway Zero-Day Exploitation With WHIPSHOT and SLAPSHOT Malware
Attribution: Rules adapted, ported, or quoted from a public source retain that source's author (e.g. SigmaHQ / Florian Roth, Elastic, Emerging Threats, Abuse.ch, or the cited vendor/researcher) and carry an attribution credit. Rules without a credit were authored in-house by RedSheepSec. If you reuse a rule, preserve its stated attribution.
Hypothesis: If threat actors exploiting CVE-2026-88771, CVE-2026-88772, or CVE-2026-88779 have targeted our NetScaler appliances or pivoted into our environment, we expect to observe network connections to known attacker IPs and domains (149.104.78.141, 45.141.21.130, echvista.com, gsocket.io, pylrk.cc), DNS queries for attacker infrastructure, HTTP requests to receiver.min.css or LogonPoint/custom paths returning anomalous response codes, and internal lateral movement from NetScaler appliance subnets in firewall, DNS, proxy, and Zeek logs.
Intelligence Summary: Three zero-day vulnerabilities in Citrix NetScaler ADC and Gateway (CVE-2026-88771, CVE-2026-88772, CVE-2026-88779) were exploited in the wild beginning September 5, 2026, twenty-two days before public disclosure on September 27. Unattributed threat actors deployed two custom malware families, WHIPSHOT (PHP webshell) and SLAPSHOT (Python TCP tunneler), to establish persistent access on compromised appliances and proxy traffic into victim internal networks across government, financial services, education, and legal sectors in North America and Europe. Patching closes the vulnerability but does not remove implants, modified Apache configurations, or stolen credentials; organizations that patched without conducting a compromise assessment likely still have active attacker access.
Confidence: Moderate | Priority: Critical
Scope
- Networks: All network segments containing Citrix NetScaler ADC and NetScaler Gateway appliances, including DMZ, perimeter, and internal VPN termination points. Include internal segments reachable from NetScaler appliance management and data-plane interfaces.
- Timeframe: September 1, 2026 through present. Primary exploitation window is September 5 through September 27, 2026 (pre-disclosure). Second-wave exploitation of CVE-2026-88779 began around October 3, 2026. Extend window to present to capture chained exploitation and post-compromise lateral movement.
- Priority Systems: Internet-facing Citrix NetScaler ADC and Gateway appliances (all versions prior to 14.1-73.41 and 13.1-64.28). Secondary priority: internal systems reachable from NetScaler appliance subnets, particularly Active Directory domain controllers, LDAP/RADIUS servers, and file servers.
MITRE ATT&CK Techniques
T1190: Exploit Public-Facing Application (Initial Access) [P1]
Attackers exploited CVE-2026-88771 (unauthenticated command injection) and CVE-2026-88772 (DTLS heap overflow in NSPPE) against internet-facing NetScaler ADC and Gateway appliances to achieve root-level code execution before authentication. CVE-2026-88779 (SAML parsing overflow) was chained with CVE-2026-88771 against appliances patched for the first two CVEs but not the third.
Splunk SPL:
index=firewall-pan sourcetype="pan:traffic:aggregated" dest_port IN (443, 4443) src_ip IN ("149.104.78.141", "77.83.199.39", "104.248.244.66", "139.180.152.138", "45.61.136.143", "66.227.183.84", "216.245.184.164", "45.141.21.130", "213.209.159.55", "78.128.113.10", "149.104.78.208", "143.198.7.94", "157.254.167.12", "138.199.60.5", "159.203.33.46", "87.224.84.82", "66.135.19.18", "167.99.111.203", "142.93.85.227", "137.184.91.207", "104.28.247.137", "138.199.60.22", "138.199.60.36", "146.70.199.170", "146.70.211.157", "23.162.8.173", "38.60.206.53", "38.60.212.144", "149.102.254.17", "130.94.19.84", "51.158.203.95", "185.244.213.112", "158.94.211.205", "78.128.113.101", "138.199.200.90") | stats count earliest(_time) as first_seen latest(_time) as last_seen by src_ip dest_ip dest_port action | sort - count
Elastic KQL:
destination.port:(443 OR 4443) AND source.ip:("149.104.78.141" OR "77.83.199.39" OR "104.248.244.66" OR "139.180.152.138" OR "45.61.136.143" OR "66.227.183.84" OR "216.245.184.164" OR "45.141.21.130" OR "213.209.159.55" OR "78.128.113.10" OR "149.104.78.208" OR "143.198.7.94" OR "157.254.167.12" OR "138.199.60.5" OR "159.203.33.46")
Sigma Rule:
title: Connection from Known NetScaler Exploitation IP to VPN Ports
id: a1f2c3d4-e5f6-7890-abcd-ef1234567890
status: experimental
level: critical
author: RedSheepSec
date: 2026/10/10
description: Detects inbound connections from known attacker IPs associated with CVE-2026-88771, CVE-2026-88772, and CVE-2026-88779 exploitation targeting Citrix NetScaler.
references:
- https://unit42.paloaltonetworks.com/netscaler-zero-days-exploited/
- https://github.com/ThomasPoppelgaard/netscaler-ctx697096-checker
logsource:
category: firewall
detection:
selection:
src_ip:
- '149.104.78.141'
- '77.83.199.39'
- '104.248.244.66'
- '139.180.152.138'
- '45.61.136.143'
- '66.227.183.84'
- '216.245.184.164'
- '45.141.21.130'
- '213.209.159.55'
- '78.128.113.10'
- '149.104.78.208'
- '143.198.7.94'
- '157.254.167.12'
- '138.199.60.5'
- '159.203.33.46'
dst_port:
- 443
- 4443
condition: selection
falsepositives:
- Legitimate traffic from these IPs is unlikely; verify against asset inventory.
tags:
- attack.initial_access
- attack.t1190
These IPs are drawn from multiple vendor reports. Some may rotate or be reused by other actors. Correlate hits with destination assets known to be NetScaler appliances. High-confidence match if destination is a known NetScaler VIP.
T1133: External Remote Services (Initial Access) [P2]
NetScaler Gateway provides VPN and remote access services. Attackers exploited these internet-facing services as the entry vector. Hunt for anomalous authentication patterns or connections from attacker infrastructure to NetScaler Gateway login endpoints.
Splunk SPL:
index=corelight sourcetype=corelight_http uri IN ("/vpn/index.html", "/cgi/login", "/saml/login", "/logon/LogonPoint/*") | stats count dc(id.orig_h) as unique_sources values(id.orig_h) as source_ips by uri status_code | where count > 50 OR unique_sources > 10 | sort - count
Elastic KQL:
url.path:("/vpn/index.html" OR "/cgi/login" OR "/saml/login" OR "/logon/LogonPoint/*") AND event.dataset:"corelight.http"
Baseline normal login volume to NetScaler endpoints. Spikes or new source IPs hitting /saml/login may indicate CVE-2026-88779 exploitation attempts.
T1505.003: Server Software Component: Web Shell (Persistence) [P1]
WHIPSHOT is a PHP webshell stored at /var/netscaler/logon/LogonPoint/custom/.ctxs.receiver without a .php extension. Apache Alias directives map receiver.min.css requests to this file. Attackers also placed .deb and .sig files containing PHP code under /var/netscaler/gui/vpn/scripts/linux/. Hunt for HTTP requests to these paths and anomalous response characteristics.
Splunk SPL:
index=corelight sourcetype=corelight_http (uri="*receiver.min.css*" OR uri="*LogonPoint/custom/*" OR uri="*.deb" OR uri="*.sig") | eval suspicious=if(status_code=404 AND response_body_len>500, "spoofed_404", "normal") | stats count values(status_code) as status_codes values(response_body_len) as resp_sizes by id.orig_h uri suspicious | sort - count
Elastic KQL:
(url.path:"*receiver.min.css*" OR url.path:"*LogonPoint/custom/*" OR url.path:"*.deb" OR url.path:"*.sig") AND event.dataset:"corelight.http"
Sigma Rule:
title: HTTP Request to WHIPSHOT Webshell Path on NetScaler
id: b2e3d4f5-a6b7-8901-cdef-234567890abc
status: experimental
level: high
author: RedSheepSec
date: 2026/10/10
description: Detects HTTP requests targeting known WHIPSHOT webshell paths on Citrix NetScaler appliances, including receiver.min.css alias and LogonPoint custom directory.
references:
- https://cloud.google.com/blog/topics/threat-intelligence/defending-against-active-exploitation-of-citrix-netscaler-adc-and-gateway-appliances
- https://www.bleepingcomputer.com/news/security/hackers-exploit-citrix-netscaler-zero-day-to-deploy-web-shells/
logsource:
category: webserver
detection:
selection_receiver:
cs-uri-query|contains: 'receiver.min.css'
selection_logonpoint:
cs-uri-query|contains: 'LogonPoint/custom/.ctxs'
selection_deb_sig:
cs-uri-query|endswith:
- '.deb'
- '.sig'
cs-uri-query|contains: '/vpn/scripts/linux/'
condition: selection_receiver or selection_logonpoint or selection_deb_sig
falsepositives:
- Legitimate requests to receiver.min.css for Citrix Receiver UI; correlate with response size and content type.
tags:
- attack.persistence
- attack.t1505.003
WHIPSHOT returns spoofed HTTP 404 responses with non-zero or abnormally large response bodies. A 404 with a response body exceeding 500 bytes from a LogonPoint path is a strong indicator. Legitimate receiver.min.css responses will have consistent sizes; deviations warrant investigation.
T1059.004: Command and Scripting Interpreter: Unix Shell (Execution) [P2]
Attackers executed shell commands via log-poisoning injection using fabricated PPE failure messages containing patterns such as 'unexpectedly died' and 'missed too many heartbeats' in NetScaler logs. SUID/SGID was set on /bin/sh before webshell installation.
Splunk SPL:
index=linux-server (sourcetype=syslog OR sourcetype=linux_messages_syslog OR sourcetype=nix:syslog) ("unexpectedly died" OR "missed too many heartbeats" OR "SSL_HANDSHAKE_FAILURE" OR "DTLSv1.0") | stats count by host _time source | sort - _time
Elastic KQL:
message:("unexpectedly died" OR "missed too many heartbeats" OR "SSL_HANDSHAKE_FAILURE" OR "DTLSv1.0")
These strings are injection markers observed by Sygnia. If NetScaler logs are forwarded to Splunk, search for these patterns. The strings may appear in ns.log or nsvpn.log entries. False positives from legitimate NSPPE crashes are possible but should be investigated regardless.
T1059.006: Command and Scripting Interpreter: Python (Execution) [P2]
SLAPSHOT is a Python-based TCP tunneling tool that listens locally on the compromised NetScaler appliance and coordinates with WHIPSHOT via /tmp/.uxdport and /tmp/.uxdlock files. Hunt for Python process execution on appliance subnets or unusual Python-related network artifacts.
Splunk SPL:
index=linux-server (sourcetype=linux:audit OR sourcetype=auditd OR sourcetype=audit) ("slapshot.py" OR "whipd.py" OR "main.py" OR ".uxdport" OR ".uxdlock" OR "/nsconfig/.slap/") | stats count by host comm _time | sort - _time
Elastic KQL:
process.name:"python*" AND (process.args:("slapshot.py" OR "whipd.py" OR "main.py") OR file.path:("/tmp/.uxdport" OR "/tmp/.uxdlock" OR "/nsconfig/.slap/*"))
NetScaler appliances are FreeBSD-based and do not normally run Python processes in production. Any Python execution on these hosts is highly suspicious.
T1071.001: Application Layer Protocol: Web Protocols (Command and Control) [P2]
WHIPSHOT hides Base64-encoded commands inside HTTP headers (HTTP_X_UX*, HTTP_NSC_CLIENTTYPE, HTTP_NSC_LDAP) and returns spoofed HTTP 404 responses. Hunt for unusual HTTP header patterns in proxy and web logs.
Splunk SPL:
index=corelight sourcetype=corelight_http ("X-UX" OR "NSC_CLIENTTYPE" OR "NSC_LDAP") | stats count by id.orig_h id.resp_h uri | sort - count
Elastic KQL:
http.request.headers:("X-UX*" OR "NSC_CLIENTTYPE" OR "NSC_LDAP") AND event.dataset:"corelight.http"
Corelight HTTP logs may capture custom headers depending on configuration. If custom header logging is not enabled, this detection will have limited coverage. Consider enabling full header capture for NetScaler-facing sensors.
T1090: Proxy (Command and Control) [P2]
SLAPSHOT proxies attacker traffic from the compromised NetScaler appliance into internal networks for reconnaissance and credential theft. Hunt for unusual internal connections originating from NetScaler management or data-plane IPs.
Splunk SPL:
index=corelight sourcetype=corelight_conn id.resp_p IN (445, 389, 636, 88, 3389, 22, 135, 5985, 5986) | lookup netscaler_ips ip AS id.orig_h OUTPUT is_netscaler | where is_netscaler="true" | stats count dc(id.resp_h) as unique_targets values(id.resp_p) as ports by id.orig_h | where unique_targets > 5 | sort - unique_targets
Note: Create a lookup table 'netscaler_ips' containing all NetScaler appliance IPs for this query to function.
**Elastic KQL:**
source.ip:("<NETSCALER_IP_1>" OR "<NETSCALER_IP_2>") AND destination.port:(445 OR 389 OR 636 OR 88 OR 3389 OR 22 OR 135 OR 5985 OR 5986) AND event.dataset:"corelight.conn"
*Replace <NETSCALER_IP> placeholders with actual NetScaler appliance management and data-plane IPs. Normal NetScaler traffic patterns should be baselined first. Connections from a NetScaler appliance to internal hosts on SMB, LDAP, Kerberos, or RDP ports are anomalous and warrant immediate investigation.*
#### T1036.005: Masquerading: Match Legitimate Name or Location (Defense Evasion) [P2]
Attackers modified /etc/httpd.conf to register .deb and .sig extensions as PHP handlers, mapped .ico requests via Apache Alias directives to malicious .sig payloads, and stored the WHIPSHOT webshell as .ctxs.receiver (no .php extension) aliased to receiver.min.css.
**Splunk SPL:**
index=corelight sourcetype=corelight_http uri="/vpn/media/.ico*" | stats count by id.orig_h id.resp_h uri status_code response_body_len | where response_body_len > 1000 | sort - response_body_len
**Elastic KQL:**
url.path:"/vpn/media/.ico*" AND http.response.body.bytes:>1000 AND event.dataset:"corelight.http"
*Legitimate .ico files served from NetScaler VPN media paths are typically small (under 5KB). Response bodies exceeding expected sizes may indicate aliased webshell content.*
#### T1027: Obfuscated Files or Information (Defense Evasion) [P2]
WHIPSHOT uses Base64-encoded payloads in HTTP headers for command and control. Encoded commands are passed via HTTP_X_UX*, HTTP_NSC_CLIENTTYPE, and HTTP_NSC_LDAP headers.
**Splunk SPL:**
index=corelight sourcetype=corelight_http id.resp_h IN ("<NETSCALER_IPs>") status_code=404 response_body_len > 500 | stats count by id.orig_h uri status_code response_body_len | sort - response_body_len
**Elastic KQL:**
http.response.status_code:404 AND http.response.body.bytes:>500 AND destination.ip:("<NETSCALER_IPs>")
*Spoofed 404 responses with large bodies are a WHIPSHOT signature. Replace <NETSCALER_IPs> with environment-specific values. A genuine 404 typically has a small error page body.*
#### T1105: Ingress Tool Transfer (Command and Control) [P1]
Attackers downloaded remote payloads and staged webshells on compromised appliances. IP 213.209.159.55 was observed downloading payloads during SAML exploitation. Multiple VPS IPs requested malicious .deb files.
**Splunk SPL:**
index=corelight sourcetype=corelight_http (id.resp_h="213.209.159.55" OR id.orig_h="213.209.159.55" OR id.resp_h="139.180.152.138" OR id.orig_h="139.180.152.138") | stats count by id.orig_h id.resp_h uri | sort - count
**Elastic KQL:**
(source.ip:("213.209.159.55" OR "139.180.152.138") OR destination.ip:("213.209.159.55" OR "139.180.152.138")) AND event.dataset:"corelight.http"
*These IPs are confirmed payload download and webshell staging sources from the source report.*
#### T1548.001: Abuse Elevation Control Mechanism: Setuid and Setgid (Privilege Escalation) [P2]
GreyNoise observed attackers setting SUID and SGID on /bin/sh before installing a password-protected hidden webshell on compromised NetScaler appliances.
**Splunk SPL:**
index=linux-server (sourcetype=linux:audit OR sourcetype=auditd OR sourcetype=audit) ("chmod" AND ("+s" OR "4755" OR "6755" OR "2755") AND "/bin/sh") | stats count by host _time | sort - _time
**Elastic KQL:**
process.name:"chmod" AND process.args:("+s" OR "4755" OR "6755" OR "2755") AND process.args:"/bin/sh"
*Setting SUID/SGID on /bin/sh is extremely unusual in any production environment and almost always indicates compromise.*
#### T1070.004: Indicator Removal: File Deletion (Defense Evasion) [P2]
Attackers ran cleanup commands to delete traces and scheduled cron jobs to erase forensic evidence on compromised NetScaler appliances.
**Splunk SPL:**
index=linux-server (sourcetype=linux:audit OR sourcetype=auditd OR sourcetype=audit OR sourcetype=syslog) ("crontab" OR "rm -rf" OR "shred" OR "unlink") ("nslog" OR "httpd.conf" OR ".ctxs" OR "uxdport" OR "uxdlock" OR "nsconfig") | stats count by host _time | sort - _time
**Elastic KQL:**
(process.name:("rm" OR "shred" OR "unlink" OR "crontab") AND process.args:("nslog" OR "httpd.conf" OR ".ctxs" OR "uxdport" OR "uxdlock" OR "nsconfig"))
*Look for bulk deletion commands targeting NetScaler log or configuration directories. Cron jobs added by non-standard accounts are suspicious.*
### Indicators of Compromise
| Type | Value | Context |
|------|-------|---------|
| ip | `149.104.78.141` | Pre-disclosure exploitation source, observed by GreyNoise on September 24, 2026 \| AbuseIPDB confidence 1% (1 reports, JP) |
| ip | `77.83.199.39` | Early fingerprinting host identified by Unit 42 \| AbuseIPDB confidence 13% (3 reports, US) |
| ip | `104.248.244.66` | Early fingerprinting host identified by Unit 42 \| AbuseIPDB confidence 0% (0 reports, DE) |
| ip | `139.180.152.138` | Dropped PHP webshell via this IP per Unit 42 \| AbuseIPDB confidence 1% (1 reports, SG) |
| ip | `45.61.136.143` | Citrix security bulletin network indicator \| AbuseIPDB confidence 0% (0 reports, US) |
| ip | `66.227.183.84` | Citrix security bulletin network indicator \| AbuseIPDB confidence 0% (0 reports, US) |
| ip | `216.245.184.164` | Citrix security bulletin network indicator \| AbuseIPDB confidence 0% (0 reports, US) |
| ip | `45.141.21.130` | C2 reverse shell destination IP \| AbuseIPDB confidence 0% (0 reports, FR) |
| ip | `213.209.159.55` | Payload download IP observed during SAML exploit chain (CVE-2026-88779) \| AbuseIPDB confidence 18% (4 reports, DE) |
| ip | `78.128.113.10` | Attacker IP tracked by community mitigation tool \| AbuseIPDB confidence 30% (14 reports, BG) |
| ip | `149.104.78.208` | Source IP in failed login attempt against NetScaler, Rapid7 report \| AbuseIPDB confidence 0% (0 reports, JP) |
| ip | `143.198.7.94` | Scanning and staging activity indicator per SOCRadar \| AbuseIPDB confidence 19% (4 reports, US) |
| ip | `157.254.167.12` | Exploitation and webshell deployment indicator per SOCRadar \| AbuseIPDB confidence 0% (0 reports, US) |
| ip | `66.135.19.18` | VPS requesting malicious .deb files per Unit 42 \| AbuseIPDB confidence 0% (0 reports, US) |
| ip | `167.99.111.203` | VPS requesting malicious .deb files per Unit 42 \| AbuseIPDB confidence 0% (0 reports, US) |
| ip | `142.93.85.227` | VPS requesting malicious .deb files per Unit 42 \| AbuseIPDB confidence 0% (0 reports, US) |
| ip | `137.184.91.207` | Requested same malicious files per Unit 42 \| AbuseIPDB confidence 29% (13 reports, US) |
| ip | `104.28.247.137` | Additional IP sending requests Sept 10-27 per Unit 42 \| AbuseIPDB confidence 17% (10 reports, US) |
| ip | `138.199.60.5` | Attacker IP added to community tracking list \| AbuseIPDB confidence 40% (46 reports, SG) |
| ip | `138.199.60.22` | Decoy IP sending injection checks per community tracker \| AbuseIPDB confidence 13% (5 reports, SG) |
| ip | `138.199.60.36` | Decoy IP sending injection checks per community tracker \| AbuseIPDB confidence 27% (6 reports, SG) |
| ip | `146.70.199.170` | Decoy IP sending injection checks per community tracker \| AbuseIPDB confidence 0% (2 reports, SG) |
| ip | `146.70.211.157` | Decoy IP sending injection checks per community tracker \| AbuseIPDB confidence 47% (14 reports, US) |
| ip | `23.162.8.173` | Decoy IP sending injection checks per community tracker \| AbuseIPDB confidence 0% (0 reports, US) |
| ip | `38.60.206.53` | Pre-disclosure GET /saml/login source per community tracker \| AbuseIPDB confidence 0% (4 reports, US) |
| ip | `38.60.212.144` | Pre-disclosure GET /saml/login source per community tracker \| AbuseIPDB confidence 1% (1 reports, JP) |
| ip | `149.102.254.17` | Pre-disclosure GET /saml/login source per community tracker \| AbuseIPDB confidence 36% (28 reports, US) |
| ip | `130.94.19.84` | Pre-disclosure GET /saml/login source per community tracker \| AbuseIPDB confidence 0% (0 reports, US) |
| ip | `51.158.203.95` | Second-wave attacker IP per community tracker \| AbuseIPDB confidence 43% (11 reports, NL) |
| ip | `185.244.213.112` | Second-wave attacker IP per community tracker \| AbuseIPDB confidence 12% (2 reports, FR) |
| ip | `158.94.211.205` | Second-wave attacker IP per community tracker \| AbuseIPDB confidence 11% (2 reports, NL) |
| ip | `87.224.84.82` | Attacker IP moved from scanner group per community tracker \| AbuseIPDB confidence 0% (0 reports, GB) |
| ip | `138.199.200.90` | Exfiltration destination in NetScaler CVE IOC list \| AbuseIPDB confidence 0% (0 reports, DE) |
| domain | `echvista.com` | Attacker infrastructure domain confirmed by community tracker \| VirusTotal 0/92 malicious |
| domain | `gsocket.io` | Attacker infrastructure domain used in NetScaler exploitation \| VirusTotal 3/92 malicious |
| domain | `pylrk.cc` | Attacker domain per source report and community tracker \| VirusTotal 5/92 malicious |
| domain | `entretiensol.com` | Attacker-controlled domain in NetScaler exploitation IOC list per community tracker \| VirusTotal 15/92 malicious |
| domain | `pyrlnk.cc` | Attacker domain listed among NetScaler exploitation IOCs per community tracker \| VirusTotal 2/92 malicious |
| hash_sha256 | `72cff13fcba75504485e94fa6bfc5e9363e860f49efdba68feb583148eec38f2` | SAML-attack kit sample shared by community, CVE-2026-88771, VT 12/75 malicious \| VirusTotal 12/75 malicious (trojan.perl/tofsee) |
| hash_sha256 | `ed082f744f035035900f67edf438f2f7d0528ac501234f63d476d65273cdb9a1` | Webshell hash at .ctxs.receiver path per Rapid7 report, VT 1/75 malicious \| VirusTotal 1/75 malicious (trojan.webshell) |
| hash_sha256 | `5ea5ea61e9062822bee3f66ef5ff47c217178d9e31936ad6daf10c5dfae44d12` | Artifact observed in NetScaler web-accessible directory per Sygnia, VT 30/75 malicious \| VirusTotal 30/75 malicious (trojan.webshell/vigorf) |
| filename | `/var/netscaler/logon/LogonPoint/custom/.ctxs.receiver` | WHIPSHOT webshell disk path on compromised NetScaler appliances |
| filename | `/tmp/.uxdport` | SLAPSHOT port coordination file on compromised NetScaler appliances |
| filename | `/tmp/.uxdlock` | SLAPSHOT lock file on compromised NetScaler appliances |
| filename | `slapshot.py` | SLAPSHOT tunneler Python component |
| filename | `receiver.min.css` | Apache alias target used to disguise WHIPSHOT webshell requests |
| filename | `insight-new.js` | Payload file used to write stolen data on compromised NetScaler appliances |
| filename | `boot.sh` | Persistence script stored in /nsconfig/.slap/ on compromised appliances |
**IOC Sweep Queries (Splunk):**
index=corelight (sourcetype=corelight_conn OR sourcetype=corelight_http OR sourcetype=corelight_dns) ("149.104.78.141") | stats count earliest(_time) as first_seen latest(_time) as last_seen by sourcetype | append [search index=firewall-pan sourcetype="pan:traffic:aggregated" (src_ip="149.104.78.141" OR dest_ip="149.104.78.141") | stats count earliest(_time) as first_seen latest(_time) as last_seen by sourcetype]
index=corelight (sourcetype=corelight_conn OR sourcetype=corelight_http) "77.83.199.39" | stats count earliest(_time) as first_seen latest(_time) as last_seen by id.orig_h id.resp_h id.resp_p | append [search index=firewall-pan sourcetype="pan:traffic:aggregated" (src_ip="77.83.199.39" OR dest_ip="77.83.199.39") | stats count earliest(_time) as first_seen latest(_time) as last_seen by src_ip dest_ip]
index=corelight (sourcetype=corelight_conn OR sourcetype=corelight_http) "104.248.244.66" | stats count earliest(_time) as first_seen latest(_time) as last_seen by id.orig_h id.resp_h id.resp_p | append [search index=firewall-pan sourcetype="pan:traffic:aggregated" (src_ip="104.248.244.66" OR dest_ip="104.248.244.66") | stats count earliest(_time) as first_seen latest(_time) as last_seen by src_ip dest_ip]
index=corelight (sourcetype=corelight_conn OR sourcetype=corelight_http) "139.180.152.138" | stats count earliest(_time) as first_seen latest(_time) as last_seen by id.orig_h id.resp_h id.resp_p | append [search index=firewall-pan sourcetype="pan:traffic:aggregated" (src_ip="139.180.152.138" OR dest_ip="139.180.152.138") | stats count earliest(_time) as first_seen latest(_time) as last_seen by src_ip dest_ip]
index=corelight (sourcetype=corelight_conn OR sourcetype=corelight_http) "45.61.136.143" | stats count earliest(_time) as first_seen latest(_time) as last_seen by id.orig_h id.resp_h id.resp_p | append [search index=firewall-pan sourcetype="pan:traffic:aggregated" (src_ip="45.61.136.143" OR dest_ip="45.61.136.143") | stats count earliest(_time) as first_seen latest(_time) as last_seen by src_ip dest_ip]
index=corelight (sourcetype=corelight_conn OR sourcetype=corelight_http) "66.227.183.84" | stats count earliest(_time) as first_seen latest(_time) as last_seen by id.orig_h id.resp_h id.resp_p | append [search index=firewall-pan sourcetype="pan:traffic:aggregated" (src_ip="66.227.183.84" OR dest_ip="66.227.183.84") | stats count earliest(_time) as first_seen latest(_time) as last_seen by src_ip dest_ip]
index=corelight (sourcetype=corelight_conn OR sourcetype=corelight_http) "216.245.184.164" | stats count earliest(_time) as first_seen latest(_time) as last_seen by id.orig_h id.resp_h id.resp_p | append [search index=firewall-pan sourcetype="pan:traffic:aggregated" (src_ip="216.245.184.164" OR dest_ip="216.245.184.164") | stats count earliest(_time) as first_seen latest(_time) as last_seen by src_ip dest_ip]
index=corelight (sourcetype=corelight_conn OR sourcetype=corelight_http) "45.141.21.130" | stats count earliest(_time) as first_seen latest(_time) as last_seen by id.orig_h id.resp_h id.resp_p | append [search index=firewall-pan sourcetype="pan:traffic:aggregated" (src_ip="45.141.21.130" OR dest_ip="45.141.21.130") | stats count earliest(_time) as first_seen latest(_time) as last_seen by src_ip dest_ip]
index=corelight (sourcetype=corelight_conn OR sourcetype=corelight_http) "213.209.159.55" | stats count earliest(_time) as first_seen latest(_time) as last_seen by id.orig_h id.resp_h id.resp_p | append [search index=firewall-pan sourcetype="pan:traffic:aggregated" (src_ip="213.209.159.55" OR dest_ip="213.209.159.55") | stats count earliest(_time) as first_seen latest(_time) as last_seen by src_ip dest_ip]
index=corelight (sourcetype=corelight_conn OR sourcetype=corelight_http) "78.128.113.10" | stats count earliest(_time) as first_seen latest(_time) as last_seen by id.orig_h id.resp_h id.resp_p | append [search index=firewall-pan sourcetype="pan:traffic:aggregated" (src_ip="78.128.113.10" OR dest_ip="78.128.113.10") | stats count earliest(_time) as first_seen latest(_time) as last_seen by src_ip dest_ip]
index=corelight (sourcetype=corelight_conn OR sourcetype=corelight_http) "149.104.78.208" | stats count earliest(_time) as first_seen latest(_time) as last_seen by id.orig_h id.resp_h id.resp_p | append [search index=firewall-pan sourcetype="pan:traffic:aggregated" (src_ip="149.104.78.208" OR dest_ip="149.104.78.208") | stats count earliest(_time) as first_seen latest(_time) as last_seen by src_ip dest_ip]
index=corelight (sourcetype=corelight_conn OR sourcetype=corelight_http) "143.198.7.94" | stats count earliest(_time) as first_seen latest(_time) as last_seen by id.orig_h id.resp_h id.resp_p | append [search index=firewall-pan sourcetype="pan:traffic:aggregated" (src_ip="143.198.7.94" OR dest_ip="143.198.7.94") | stats count earliest(_time) as first_seen latest(_time) as last_seen by src_ip dest_ip]
index=corelight (sourcetype=corelight_conn OR sourcetype=corelight_http) "157.254.167.12" | stats count earliest(_time) as first_seen latest(_time) as last_seen by id.orig_h id.resp_h id.resp_p | append [search index=firewall-pan sourcetype="pan:traffic:aggregated" (src_ip="157.254.167.12" OR dest_ip="157.254.167.12") | stats count earliest(_time) as first_seen latest(_time) as last_seen by src_ip dest_ip]
index=corelight (sourcetype=corelight_conn OR sourcetype=corelight_http) "66.135.19.18" | stats count earliest(_time) as first_seen latest(_time) as last_seen by id.orig_h id.resp_h id.resp_p
index=corelight (sourcetype=corelight_conn OR sourcetype=corelight_http) "167.99.111.203" | stats count earliest(_time) as first_seen latest(_time) as last_seen by id.orig_h id.resp_h id.resp_p
index=corelight (sourcetype=corelight_conn OR sourcetype=corelight_http) "142.93.85.227" | stats count earliest(_time) as first_seen latest(_time) as last_seen by id.orig_h id.resp_h id.resp_p
index=corelight (sourcetype=corelight_conn OR sourcetype=corelight_http) "137.184.91.207" | stats count earliest(_time) as first_seen latest(_time) as last_seen by id.orig_h id.resp_h id.resp_p
index=corelight (sourcetype=corelight_conn OR sourcetype=corelight_http) "104.28.247.137" | stats count earliest(_time) as first_seen latest(_time) as last_seen by id.orig_h id.resp_h id.resp_p
index=corelight (sourcetype=corelight_conn OR sourcetype=corelight_http) "138.199.60.5" | stats count earliest(_time) as first_seen latest(_time) as last_seen by id.orig_h id.resp_h id.resp_p
index=corelight (sourcetype=corelight_conn OR sourcetype=corelight_http) "138.199.60.22" | stats count earliest(_time) as first_seen latest(_time) as last_seen by id.orig_h id.resp_h id.resp_p
index=corelight (sourcetype=corelight_conn OR sourcetype=corelight_http) "138.199.60.36" | stats count earliest(_time) as first_seen latest(_time) as last_seen by id.orig_h id.resp_h id.resp_p
index=corelight (sourcetype=corelight_conn OR sourcetype=corelight_http) "146.70.199.170" | stats count earliest(_time) as first_seen latest(_time) as last_seen by id.orig_h id.resp_h id.resp_p
index=corelight (sourcetype=corelight_conn OR sourcetype=corelight_http) "146.70.211.157" | stats count earliest(_time) as first_seen latest(_time) as last_seen by id.orig_h id.resp_h id.resp_p
index=corelight (sourcetype=corelight_conn OR sourcetype=corelight_http) "23.162.8.173" | stats count earliest(_time) as first_seen latest(_time) as last_seen by id.orig_h id.resp_h id.resp_p
index=corelight (sourcetype=corelight_conn OR sourcetype=corelight_http) "38.60.206.53" | stats count earliest(_time) as first_seen latest(_time) as last_seen by id.orig_h id.resp_h id.resp_p
index=corelight (sourcetype=corelight_conn OR sourcetype=corelight_http) "38.60.212.144" | stats count earliest(_time) as first_seen latest(_time) as last_seen by id.orig_h id.resp_h id.resp_p
index=corelight (sourcetype=corelight_conn OR sourcetype=corelight_http) "149.102.254.17" | stats count earliest(_time) as first_seen latest(_time) as last_seen by id.orig_h id.resp_h id.resp_p
index=corelight (sourcetype=corelight_conn OR sourcetype=corelight_http) "130.94.19.84" | stats count earliest(_time) as first_seen latest(_time) as last_seen by id.orig_h id.resp_h id.resp_p
index=corelight (sourcetype=corelight_conn OR sourcetype=corelight_http) "51.158.203.95" | stats count earliest(_time) as first_seen latest(_time) as last_seen by id.orig_h id.resp_h id.resp_p
index=corelight (sourcetype=corelight_conn OR sourcetype=corelight_http) "185.244.213.112" | stats count earliest(_time) as first_seen latest(_time) as last_seen by id.orig_h id.resp_h id.resp_p
index=corelight (sourcetype=corelight_conn OR sourcetype=corelight_http) "158.94.211.205" | stats count earliest(_time) as first_seen latest(_time) as last_seen by id.orig_h id.resp_h id.resp_p
index=corelight (sourcetype=corelight_conn OR sourcetype=corelight_http) "87.224.84.82" | stats count earliest(_time) as first_seen latest(_time) as last_seen by id.orig_h id.resp_h id.resp_p
index=corelight (sourcetype=corelight_conn OR sourcetype=corelight_http) "138.199.200.90" | stats count earliest(_time) as first_seen latest(_time) as last_seen by id.orig_h id.resp_h id.resp_p
index=corelight sourcetype=corelight_dns query="*echvista.com" | stats count earliest(_time) as first_seen latest(_time) as last_seen values(id.orig_h) as querying_hosts by query | append [search index=dns ("echvista.com") | stats count earliest(_time) as first_seen latest(_time) as last_seen by src_ip query]
index=corelight sourcetype=corelight_dns query="*gsocket.io" | stats count earliest(_time) as first_seen latest(_time) as last_seen values(id.orig_h) as querying_hosts by query | append [search index=dns ("gsocket.io") | stats count earliest(_time) as first_seen latest(_time) as last_seen by src_ip query]
index=corelight sourcetype=corelight_dns query="*pylrk.cc" | stats count earliest(_time) as first_seen latest(_time) as last_seen values(id.orig_h) as querying_hosts by query | append [search index=dns ("pylrk.cc") | stats count earliest(_time) as first_seen latest(_time) as last_seen by src_ip query]
index=corelight sourcetype=corelight_dns query="*entretiensol.com" | stats count earliest(_time) as first_seen latest(_time) as last_seen values(id.orig_h) as querying_hosts by query
index=corelight sourcetype=corelight_dns query="*pyrlnk.cc" | stats count earliest(_time) as first_seen latest(_time) as last_seen values(id.orig_h) as querying_hosts by query
index=crowdstrike sourcetype="crowdstrike:events:sensor" SHA256HashData="72cff13fcba75504485e94fa6bfc5e9363e860f49efdba68feb583148eec38f2" | stats count earliest(_time) as first_seen latest(_time) as last_seen by ComputerName
index=crowdstrike sourcetype="crowdstrike:events:sensor" SHA256HashData="ed082f744f035035900f67edf438f2f7d0528ac501234f63d476d65273cdb9a1" | stats count earliest(_time) as first_seen latest(_time) as last_seen by ComputerName
index=crowdstrike sourcetype="crowdstrike:events:sensor" SHA256HashData="5ea5ea61e9062822bee3f66ef5ff47c217178d9e31936ad6daf10c5dfae44d12" | stats count earliest(_time) as first_seen latest(_time) as last_seen by ComputerName
index=linux-server (sourcetype=linux:audit OR sourcetype=auditd OR sourcetype=audit) ".ctxs.receiver" | stats count by host _time
index=linux-server (sourcetype=linux:audit OR sourcetype=auditd OR sourcetype=audit) ".uxdport" | stats count by host _time
index=linux-server (sourcetype=linux:audit OR sourcetype=auditd OR sourcetype=audit) ".uxdlock" | stats count by host _time
index=linux-server (sourcetype=linux:audit OR sourcetype=auditd OR sourcetype=audit) "slapshot.py" | stats count by host _time
index=corelight sourcetype=corelight_http uri="receiver.min.css" | stats count by id.orig_h id.resp_h status_code response_body_len
index=corelight sourcetype=corelight_http uri="insight-new.js" | stats count by id.orig_h id.resp_h | append [search index=linux-server "insight-new.js" | stats count by host _time]
index=linux-server (sourcetype=linux:audit OR sourcetype=auditd OR sourcetype=audit) ("boot.sh" AND "nsconfig") | stats count by host _time
### YARA Rules
**WHIPSHOT_PHP_Webshell_Indicators**: Detects WHIPSHOT PHP webshell artifacts based on file path patterns, HTTP header C2 markers, and coordination file references observed in NetScaler compromises
rule WHIPSHOT_PHP_Webshell_Indicators {
meta:
author = "RedSheepSec"
description = "Detects WHIPSHOT PHP webshell deployed on Citrix NetScaler appliances via Apache Alias manipulation"
reference = "https://cloud.google.com/blog/topics/threat-intelligence/defending-against-active-exploitation-of-citrix-netscaler-adc-and-gateway-appliances"
date = "2026-10-10"
threat_name = "WHIPSHOT"
strings:
$path1 = ".ctxs.receiver" ascii
$path2 = "LogonPoint/custom" ascii
$header1 = "HTTP_X_UX" ascii
$header2 = "HTTP_NSC_CLIENTTYPE" ascii
$header3 = "HTTP_NSC_LDAP" ascii
$coord1 = "/tmp/.uxdport" ascii
$coord2 = "/tmp/.uxdlock" ascii
$coord3 = "127.0.0.1" ascii
$php_tag = "<?php" ascii nocase
$b64_decode = "base64_decode" ascii nocase
condition:
$php_tag and ($b64_decode or any of ($header)) and (any of ($path) or any of ($coord*))
}
**WHIPSHOT_Webshell_SHA256**: Detects known WHIPSHOT webshell samples by SHA-256 hash
import "hash"
rule WHIPSHOT_Webshell_SHA256 {
meta:
author = "RedSheepSec"
description = "Detects known WHIPSHOT webshell file hashes from vendor reports"
reference = "https://www.rapid7.com/blog/post/etr-zero-day-exploitation-of-citrix-netscaler-adc-and-gateway-cve-2026-88771-and-cve-2026-88772/"
date = "2026-10-10"
condition:
hash.sha256(0, filesize) == "6f5a2a452a7901323abd21879c6cecccb47c06aeeaccb1b467212f3b11e4b1e7" or
hash.sha256(0, filesize) == "ed082f744f035035900f67edf438f2f7d0528ac501234f63d476d65273cdb9a1" or
hash.sha256(0, filesize) == "ae22ef2517b5c0fb47f78745b9cb5260acee0e751b89bcd354640ff8bc8d29ec" or
hash.sha256(0, filesize) == "5ea5ea61e9062822bee3f66ef5ff47c217178d9e31936ad6daf10c5dfae44d12" or
hash.sha256(0, filesize) == "72cff13fcba75504485e94fa6bfc5e9363e860f49efdba68feb583148eec38f2"
}
**SLAPSHOT_Python_Tunneler**: Detects SLAPSHOT Python-based TCP tunneler component used for internal network proxying from compromised NetScaler appliances
rule SLAPSHOT_Python_Tunneler {
meta:
author = "RedSheepSec"
description = "Detects SLAPSHOT Python TCP tunneler deployed on Citrix NetScaler appliances"
reference = "https://www.bleepingcomputer.com/news/security/hackers-exploit-citrix-netscaler-zero-day-to-deploy-web-shells/"
date = "2026-10-10"
threat_name = "SLAPSHOT"
strings:
$name = "slapshot" ascii nocase
$coord1 = ".uxdport" ascii
$coord2 = ".uxdlock" ascii
$sock = "socket.socket" ascii
$tunnel = "127.0.0.1" ascii
$import1 = "import socket" ascii
$import2 = "import threading" ascii
$slap_dir = "/nsconfig/.slap/" ascii
condition:
(2 of ($coord, $slap_dir)) or ($name and $sock and $tunnel) or ($import1 and $import2 and any of ($coord))
}
### Suricata Rules
**SID 2026001**: Detects DNS query to echvista.com, attacker infrastructure domain associated with NetScaler zero-day exploitation
alert dns $HOME_NET any -> any any (msg:"ET TROJAN NetScaler WHIPSHOT/SLAPSHOT - DNS Query to echvista.com"; dns.query; content:"echvista.com"; nocase; reference:url,github.com/ThomasPoppelgaard/netscaler-ctx697096-checker; classtype:trojan-activity; sid:2026001; rev:1;)
**SID 2026002**: Detects DNS query to gsocket.io, attacker infrastructure domain associated with NetScaler zero-day exploitation
alert dns $HOME_NET any -> any any (msg:"ET TROJAN NetScaler WHIPSHOT/SLAPSHOT - DNS Query to gsocket.io"; dns.query; content:"gsocket.io"; nocase; reference:url,github.com/ThomasPoppelgaard/netscaler-ctx697096-checker; classtype:trojan-activity; sid:2026002; rev:1;)
**SID 2026003**: Detects DNS query to pylrk.cc, attacker domain associated with NetScaler zero-day exploitation
alert dns $HOME_NET any -> any any (msg:"ET TROJAN NetScaler WHIPSHOT/SLAPSHOT - DNS Query to pylrk.cc"; dns.query; content:"pylrk.cc"; nocase; reference:url,github.com/ThomasPoppelgaard/netscaler-ctx697096-checker; classtype:trojan-activity; sid:2026003; rev:1;)
**SID 2026004**: Detects outbound connection to 149.104.78.141, pre-disclosure exploitation source for CVE-2026-88772
alert ip $HOME_NET any -> 149.104.78.141 any (msg:"ET TROJAN NetScaler Exploitation - Outbound to 149.104.78.141"; reference:url,cyberpress.org/hackers-exploit-citrix-netscaler-zero-days/; classtype:trojan-activity; sid:2026004; rev:1;)
**SID 2026005**: Detects outbound connection to 45.141.21.130, C2 reverse shell destination in NetScaler exploitation campaign
alert ip $HOME_NET any -> 45.141.21.130 any (msg:"ET TROJAN NetScaler WHIPSHOT C2 - Outbound to 45.141.21.130"; reference:url,www.decryptiondigest.com/blog/netscaler-backdoor-persists-after-patching-whipshot; classtype:trojan-activity; sid:2026005; rev:1;)
**SID 2026006**: Detects HTTP request to receiver.min.css on NetScaler with potential webshell indicators
alert http $EXTERNAL_NET any -> $HOME_NET any (msg:"ET TROJAN NetScaler WHIPSHOT Webshell - receiver.min.css Request with Suspicious Headers"; flow:established,to_server; http.uri; content:"receiver.min.css"; nocase; http.header; content:"X-UX"; nocase; reference:url,cloud.google.com/blog/topics/threat-intelligence/defending-against-active-exploitation-of-citrix-netscaler-adc-and-gateway-appliances; classtype:trojan-activity; sid:2026006; rev:1;)
**SID 2026007**: Detects DNS query to entretiensol.com, attacker-controlled domain in NetScaler exploitation
alert dns $HOME_NET any -> any any (msg:"ET TROJAN NetScaler Campaign - DNS Query to entretiensol.com"; dns.query; content:"entretiensol.com"; nocase; reference:url,github.com/ThomasPoppelgaard/netscaler-ctx697096-checker; classtype:trojan-activity; sid:2026007; rev:1;)
**SID 2026008**: Detects DNS query to pyrlnk.cc, attacker domain in NetScaler exploitation
alert dns $HOME_NET any -> any any (msg:"ET TROJAN NetScaler Campaign - DNS Query to pyrlnk.cc"; dns.query; content:"pyrlnk.cc"; nocase; reference:url,github.com/ThomasPoppelgaard/netscaler-ctx697096-checker; classtype:trojan-activity; sid:2026008; rev:1;)