Für CVE-2026-88771 hat Citrix mit dem Bulletin CTX697096 Angriffe auf ungepatchte Systeme bestätigt. CERT-EU hat inzwischen beschrieben, wie die Angriffe ablaufen und welche Spuren sie in den Logs einer Appliance hinterlassen. Dieser Beitrag fasst das zusammen und zeigt die Suche danach, getestet an meiner Testinstanz.
Welche Builds betroffen sind und wie sich jede Appliance je CVE bewerten lässt, steht im Beitrag NetScaler CVE-2026-88771 bis 88778: Betroffenheit prüfen.
Der Mechanismus
Auf der Appliance liegt das Skript /netscaler/ns_monuploadd_err.pl. Es wertet nach einem Absturz der Packet Engine die Logs aus, um die passende Core-Datei zu finden. Dazu durchsucht es /var/log/ns.log.0, /var/log/ns.log und /var/log/messages nach Zeilen mit pitboss … PPE … missed too many heartbeats oder pitboss … PPE … unexpectedly died und verarbeitet die letzte Trefferzeile in einem Shell-Befehl weiter, ohne ihren Inhalt zu prüfen.
Die Angreifer nutzen zwei Logs:
- Das Zugriffslog des Webservers. Im HTTP-Header User-Agent steht ein Base64-kodierter Befehl, eingeleitet mit
INDEX:. Er landet unverändert in/var/log/httpaccess.log. - Das Anmeldelog. Ein Anmeldeversuch mit einem präparierten Benutzernamen, der den Text
pitboss PPE missed too many heartbeatsenthält, dazu einen angehängten Befehl. Der Benutzername landet inns.log. Läuft das Skript, holt dieser Befehl den Base64-Teil aus dem Zugriffslog, dekodiert ihn und führt ihn aus.
Nach CERT-EU schalten die Angreifer anschließend in /etc/httpd.conf die PHP-Ausführung frei und legen Webshells ab.
Ein Eintrag im Log ist ein Versuch, noch kein Erfolg. Aussagekraft bekommt er erst durch zeitliche Korrelation und durch Folgeartefakte auf der Appliance.
Was die Testinstanz dazu zeigt
Auf meiner Testinstanz, NetScaler 14.1 mit einem Build vor dem Fix:
- Das Skript liegt unter
/netscaler/ns_monuploadd_err.pl, die grep-Zeile ist genau die von CERT-EU beschriebene, einschließlich der Varianteunexpectedly died. - Ein fehlgeschlagener Login an der Management-Schnittstelle (NITRO) mit dem Benutzernamen
pitboss PPE missed too many heartbeatssteht danach wörtlich inns.log:User pitboss PPE missed too many heartbeats … Status "ERROR: Invalid username or password". Der Weg ins Log braucht also kein Gateway, eine erreichbare Anmeldung genügt. - Ein User-Agent mit
INDEX:dGVzdA==steht vollständig inhttpaccess.log, auch bei einer Anfrage, die mit 401 abgewiesen wird. - Die Logs reichen nicht weit zurück.
ns.log,messagesundhttpaccess.logwerden nach Größe rotiert (je 100 KB, 25 Rotationen, laut/etc/newsyslog.conf). Auf der Testinstanz mit fast keinem Verkehr deckt das gut 24 Stunden ab. Auf einem genutzten Gateway sind es entsprechend weniger.
Wie du prüfst
- Logs sichern, bevor etwas anderes passiert. Wegen der kurzen Rotation zuerst. Ein Update mit Neustart ändert zusätzlich den Zustand der Appliance. Gibt es ein externes Syslog-Ziel, dort den Zeitraum vor dem Patch mit auswerten.
- Auf einer Kopie suchen, nicht auf der Appliance. Befehle über die NetScaler-CLI (
shell '…') schreibt die Appliance alsCMD_EXECUTEDsamt Suchmuster inns.log. Die nächste Suche findet dann den eigenen Suchbefehl. Auf der Testinstanz genau so passiert. - Nach beiden Spuren suchen und die Treffer zeitlich zuordnen. Einzelne Treffer sind ein Hinweis, zeitlich passende Paare sind der eigentliche Befund.
- Folgeartefakte suchen: die PHP-Einstellung in
/etc/httpd.conf, fremde oder veränderte Dateien in den Webverzeichnissen/var/netscaler/gui/und/var/netscaler/logon/.
Logs von der Appliance holen
Auf der NetScaler-CLI ein Archiv anlegen:
shell "cd /var/log && tar czf /var/tmp/logsicherung.tgz ns.log* httpaccess*.log* messages*"
Das Archiv per SCP abholen (/var/tmp/logsicherung.tgz) und danach auf der Appliance löschen:
shell "rm /var/tmp/logsicherung.tgz"
Suchen
Auf einem Rechner mit zgrep und base64 (Linux, Git Bash unter Windows), im entpackten Verzeichnis:
# Anmeldelog: praeparierte Benutzernamen (beide Varianten, auch in den .gz-Rotationen)
zgrep -E -i 'pitboss.*PPE.*(missed too many heartbeats|unexpectedly died)' ns.log* messages*
# Zugriffslog: Base64 hinter INDEX: im User-Agent
zgrep -h 'INDEX:' httpaccess*.log*
# Den Base64-Teil lesbar machen, ohne ihn auszufuehren
zgrep -ho 'INDEX:[A-Za-z0-9+/=]*' httpaccess*.log* | sed 's/INDEX://' | while read b; do echo "$b" | base64 -d; echo; done
Das Suchmuster enthält bewusst pitboss und PPE. Nur nach heartbeat zu suchen, liefert Falschtreffer: In messages steht bei jedem Start hvheartbeat0: <Hyper-V Heartbeat>.
Falschtreffer, die du erkennst:
- Zeilen mit
CMD_EXECUTED … User … Command "shell …"sind eigene Suchbefehle über die CLI, siehe Schritt 2. - Ein echter Absturz der Packet Engine erzeugt ebenfalls eine pitboss-Zeile. Sie steht dann nicht als Benutzername in einer Anmeldezeile, und unter
/var/coreliegt eine passende Core-Datei.
Ein Anmeldeversuch mit diesem Benutzernamen ist in jedem Fall ein Angriffsversuch.
Folgeartefakte
shell "grep -n -i 'php_flag engine' /etc/httpd.conf"
Im Normalzustand steht dort php_flag engine off für den internen VirtualHost auf Port 81. Eine Zeile mit on gehört geklärt. Der Zeitstempel von /etc/httpd.conf allein sagt wenig: Die Datei liegt im Arbeitsspeicher-Dateisystem und trägt auf der Testinstanz den Zeitpunkt des letzten Neustarts. Deshalb diese Prüfung vor dem Update mit Neustart durchführen.
Für die Webverzeichnisse taugt das Dateialter nicht. /netscaler/ns_gui ist ein Symlink auf /var/netscaler/gui, und die Appliance schreibt dort und unter /var/netscaler/logon Tausende Dateien bei jedem Start und zusätzlich zu jeder vollen Stunde neu. Eine Suche nach Dateien, die jünger sind als ein Stichtag, liefert auf der Testinstanz mehrere Hundert harmlose Treffer.
Belastbar ist der Vergleich von Prüfsummen. Die Liste erzeugen:
shell "find /var/netscaler/gui/ /var/netscaler/logon/ -type f -exec md5 -r {} + | sort -k2 > /var/tmp/webdateien.txt"
Die Liste abholen und mit einer Liste von einer sauberen Appliance mit demselben Build vergleichen (diff), danach /var/tmp/webdateien.txt löschen. Auf der Testinstanz zeigte der Vergleich eine hinzugefügte Datei und eine veränderte Anmeldeseite als genau zwei Zeilen, bei gut 4.500 Dateien. Der abschließende / hinter den Verzeichnissen ist nötig: Ohne ihn folgt find dem Symlink nicht und meldet nichts, auch wenn etwas da ist.
Findet sich ein Folgeartefakt, reicht das Update allein nicht mehr. Dann ist die Appliance als kompromittiert zu behandeln: Beweise sichern, Kennwörter und Schlüssel aus der Konfiguration tauschen, aktive Sitzungen beenden und die Appliance nach Vorgabe von Citrix neu aufsetzen.
Weitere Indikatoren aus Netz und Firewall
Veröffentlicht wurden außerdem (Help Net Security unter Berufung auf GreyNoise und Kevin Beaumont):
| Art | Indikator |
|---|---|
| HTTP | POST /nf/auth/doAuthentication.do mit pitboss PPE unexpectedly died NSPPE im Body |
| IP (Abfluss von Daten) | 138[.]199[.]200[.]90 |
| DNS | ausgehende Anfragen auf *.instances.httpworkbench[.]com |
Die beiden letzten lassen sich in Firewall- und DNS-Logs prüfen, also außerhalb der Appliance. Das hat den Vorteil, dass diese Quelle von einem möglichen Angreifer auf der Appliance nicht verändert werden kann.
Wie du es löst
Die Lösung ist das Update auf die behobenen Builds aus CTX697096: 14.1-73.37 und 13.1-64.23, bei FIPS 14.1-73.37 FIPS und 13.1-37.279. CERT-EU empfiehlt zusätzlich, für jede aus dem Internet erreichbare Appliance mit betroffenem Build eine Prüfung auf Kompromittierung durchzuführen. Die Suche in den Logs ersetzt das Update nicht, sie beantwortet eine andere Frage: ob in der Zeit davor jemand erfolgreich war.
Für die nächste Welle hilft ein externes Syslog-Ziel. Die lokalen Logs auf der Appliance reichen im Ernstfall oft nicht bis zum fraglichen Zeitpunkt zurück.
Was du dir merkst
Erst Logs,
httpd.confund Prüfsummenliste sichern, dann patchen, dann auf den Kopien suchen. Base64 hinterINDEX:im User-Agent und ein Benutzername mitpitboss … PPEgehören zusammen. Ein Versuch im Log ist noch kein Einbruch, eine fremde Datei im Webverzeichnis schon.
Quellen: CTX697096, CERT-EU: Taking ‚execute logging‘ a bit too literally, CERT-EU Security Advisory 2026-014, watchTowr Labs, Help Net Security, 29.09.2026. Eigene Messungen an einer Testinstanz mit NetScaler 14.1 vor dem Fix.
Stand dieses Beitrags: 30.09.2026. Änderungen an der Lage trage ich datiert am Kopf des betroffenen Abschnitts nach, statt den Text still zu korrigieren.
