On September 27, eight new vulnerabilities affecting Citrix NetScaler ADC and Citrix NetScaler Gateway products were disclosed. We identified two distinct kinds of NetScaler scanning that defenders should be aware of.
- Generic fingerprinting. Most requests scanning for exposed Citrix devices use a generic NetScaler path that is also used by benign scanners.
- Scanning through (residential) proxies. A specific set of requests were routed through proxies using headless Chrome browsers.
Port 443 around disclosure
Disclosure day was the busiest day for port 443, but only modestly above the next-busiest day. This is consistent with other CVE disclosures, where malicious scanning can blend into existing internet noise.
The NetScaler-specific requests on port 443 followed this traffic bump. Whoever reacted to the disclosure did not do so with a clearly visible wave of scanning.
Scanning for NetScaler instances
Who. We observed scanners from many source IPs over the past 30 days, including AS14061 (DigitalOcean) and AS63949 (Akamai/Linode). This group includes institutional and other benign scanners. Next to this we observe a set of scans that appear to be more targeted and malicious, routed through (residential) proxies.
Port rotation. NetScaler fingerprinting appeared on ports 80, 443, 8080, and 8443. We did not observe device fingerprinting outside this range.
We identified some of the 16 attacker IPs published by eSentire and Google. Two also reached our sensors on other ports during September: 143.198.7.94 swept about 25 unrelated ports on 10 September, while 185.156.46.162 sent BitTorrent traffic. Because these IPs are in datacenters, we do not believe they necessarily remain under the original operators' control.
Generic fingerprinting of NetScaler
Most fingerprint requests are the same hand-built, two-header request with a borrowed browser User-Agent. It is also used by institutional scanners. The destination IP is anonymised below.
GET /vpn/js/rdx/core/lang/rdx_en.json.gz HTTP/1.1 Host: <REDACTED>:443 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36
| Field | Observation | What it tells us |
|---|---|---|
| Header set | Exactly Host and User-Agent; no Accept, Accept-Encoding, Connection, or client hints | Not a browser or common HTTP-library default |
| Host | Raw destination IP :port is appended on 443, 8080, and 8443, and omitted on 80 | The scan works from an IP:port list, not hostnames |
| Source port | 32,774-60,998 | Linux default ephemeral range (32768-60999), indicating hosts using the kernel TCP stack |
| Size | 209-216 bytes; only the host length varies | Trivial to match exactly |
Target validation through proxies
Generic scanning connects directly from cloud IPs and addresses targets by IP. The targeted probing uses real hostnames and hides behind proxy networks. We saw an uptick in highly targeted scanning after disclosure: scans were generic before disclosure, then used Chromium to appear more authentic.
Probe 1: generic scans before disclosure
GET /vpn/index.html HTTP/1.1 Host: gateway.example.com User-Agent: Mozilla/5.0 Connection: close
This minimal scripted client sends three headers and a truncated User-Agent, with one request per connection. /vpn/index.html is the classic NetScaler Gateway login page, so its response confirms the product.
Probe 2: scans after disclosure
GET /logon/LogonPoint/receiver/images/common/icon_vpn.ico HTTP/1.1 Host: citrix.example.com Connection: keep-alive Pragma: no-cache Cache-Control: no-cache sec-ch-ua: "Chromium";v="153", "Not_A Brand";v="8" sec-ch-ua-mobile: ?0 sec-ch-ua-platform: "Linux" Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/153.0.0.0 Safari/537.36
The available export ends after the User-Agent, so later headers such as Accept and Sec-Fetch-* are not shown.
A real browser engine. Header names and ordering match a Chromium top-level navigation, rather than a library merely faking a browser User-Agent.
Unbranded Chromium. The sec-ch-ua header lists Chromium rather than Google Chrome, consistent with a plain Chromium build used by headless automation frameworks.
Cache disabled. Pragma: no-cache and Cache-Control: no-cache appear during a hard reload or when automation disables caching.
Why this file. icon_vpn.ico is a static asset from the Gateway logon page. Fetching it confirms a Gateway without touching the login flow. It is not a webshell check: implants from this campaign use made-up names under /vpn/media/*.ico.
Blocking cloud scanner IPs stops noisy scans. It does not stop the targeted step, which can arrive through any open proxy selected that day.
Detection notes
The scanning is straightforward to match in most telemetry systems.
What to match
- Generic scanning:
GET /vpn/js/rdx/core/lang/rdx_en.json.gzwith onlyHostandUser-Agent, plus the macOSChrome/92.0.4515.159User-Agent for this specific campaign. - Target validation: a request for
/vpn/index.htmlor a/logon/LogonPoint/path reaching a Gateway as a single request without a surrounding page load.
False positives removed
| Rule | Actual cause | Resolution |
|---|---|---|
| Generic request smuggling (TE + CL) | One bot sent a 4-byte chunked POST /upload to CDN-fronted sites | Dropped as it was not attributable to CVE-2026-88773 |
IOC IP 185.156.46.162 | BitTorrent from a rotating pool of 21 IPs in one /24 | Kept the IP, but discarded the match after review |
Sources
- Citrix security bulletin CTX697096
- CERT-EU: Taking 'execute logging' a bit too literally
- Google Cloud / Mandiant: Defending Against Active Exploitation of Citrix NetScaler ADC and Gateway Appliances
- eSentire: Ongoing Exploitation of Citrix NetScaler
- CitrixScan, which uses
rdx_en.json.gzfor NetScaler version fingerprinting
Know who's knocking
Look up any source IP from your NetScaler logs for a verdict, ASN, and per-port history in the IP Lookup tool.
