防御针对 Citrix NetScaler ADC 与 Gateway 设备的主动利用
Mandiant 与 GTIG 发现 Citrix NetScaler 零日 CVE-2026-88772 正被野外利用。报告记录了完整攻击链、两种 Web 服务持久化手法、WHIPSHOT 与 SLAPSHOT 两个恶意软件的分析,以及猎捕思路、三套处置方案与 YARA 规则。
中文
复制
简介
2026 年 9 月下旬,Mandiant Consulting 与 Google Threat Intelligence Group(GTIG)发现,Citrix NetScaler ADC 和 NetScaler Gateway 设备上的一个零日漏洞(CVE-2026-88772)正在被主动利用。我们观察到证据表明,北美和欧洲政府、金融服务、科技、教育以及法律与专业服务领域的组织很可能受到了这轮利用活动的影响,该活动至少从 9 月初就已开始。据厂商披露,威胁行为者还在积极利用第二个零日漏洞(CVE-2026-88771)。 利用 CVE-2026-88772 可绕过身份验证,并触发 NetScaler Packet Processing Engine(NSPPE)的未处理终止,从而建立初始的 root 级访问权限。对攻击者后渗透工具包的分析揭示了新发现的自定义 PHP Web Shell,例如 WHIPSHOT,能够将 Base64 编码的命令与控制(C&C)载荷伪装在原生 HTTP 头中。该工具包还包含一个新颖的配套 Python 隧道工具 SLAPSHOT,能够将流量代理到内网,用于侦察和凭据窃取。在至少一起已观察到的入侵中,威胁行为者通过该代理转发流量,手动进行内网侦察和凭据窃取。 Citrix 针对新修复的漏洞发布了客户指南,并建议客户在此处进行更新。我们鼓励防御者查阅 Citrix 文档,并优先为这些漏洞打补丁。作为本篇博客的一部分,Mandiant 同时发布遏制与修复指南。
活动概览
初始访问
在初始的预认证加密握手过程中,NSPPE 会解析入站 DTLS 记录结构。虽然 Google Threat Intelligence Group 并不掌握漏洞利用代码,但对一线遥测数据的分析表明,传输特制的畸形或分片记录头会在数据包引擎内引发堆内存边界损坏,将控制流转向执行任意 shellcode,并在底层 FreeBSD 平台上获得 root 级操作系统权限。 成功的利用尝试生成了两条日志记录:
0-PPE-0 : default SSLLOG SSL_HANDSHAKE_FAILURE 0 : SPCBId - ClientIP - ClientPort - VserverServiceIP - VserverServicePort 443 - ClientVersion DTLSv1.0 - CipherSuite "TLS1-AES-256-CBC-SHA" - Session New - Reason "Handshake failure-Internal Error"
图 1:Syslog 中记录的 SSL 握手失败
qat0: Process <PID> NSPPE-<##> exit with orphan rings 5:500
pitboss[<##>]: pitboss <DATETIME> NOT restarting NSPPE-<##> (<PID>)
图 2:FreeBSD 内核和设备看门狗守护进程(pitboss)记录的 NSPPE 进程终止(/var/log/messages)
建立立足点与持久化
利用成功后,初始 Web Shell 载荷会通过修改目标 httpd.conf 文件自行安装,将系统配置为把指定的非脚本文件类型当作可执行的 PHP 脚本处理,为部署更多自定义恶意软件(包括 WHIPSHOT(一个 PHP Web Shell)和 SLAPSHOT(一个 Python 代理/隧道工具))铺平道路。
Web 服务器持久化方法 A:包处理器伪装(.deb)
在一起案例中,初始安装程序修改了 /etc/httpd.conf,使 Web 服务器将 .deb 文件当作 PHP 脚本处理。
php_flag engine on
<FilesMatch "\.deb$">
Header set Cache-Control "no-cache"
</FilesMatch>
AddHandler application/x-httpd-php .deb
图 3:通过伪装成包处理程序实现持久化
该配置变更使攻击者得以在 /netscaler/gui/vpn/scripts/linux 中投放带有欺骗性文件扩展名的 web shell。
Web 服务器持久化方法 B:图标别名与签名文件处理程序(.sig)
在另一些入侵中,威胁行为者植入了一个更为隐蔽的配置钩子,将 web shell 的执行伪装成图片请求:
php_flag engine on#
AliasMatch ^/vpn/media/(.+).ico$ /var/netscaler/gui/vpn/scripts/linux/$1.sig
AddHandler application/x-httpd-php .sig
图 4:通过图标别名与签名文件处理程序实现持久化 该配置指令执行三项操作:
- 启用 mod_php 引擎。
- 将 .sig 文件注册为可执行的 PHP 脚本。
- 将 /vpn/media/ 下任何以 .ico 结尾的传入 HTTP 请求直接映射到 /var/netscaler/gui/vpn/scripts/linux/ 中同名基名对应的 .sig 文件。
例如,客户端访问 /vpn/media/e6ee7c85.ico 时,实际由投放的 PHP web shell
e6ee7c85.sig响应。至少在一例中,web 服务器访问日志显示 GET 请求返回 HTTP 404 响应,但处理耗时偏高、响应体达到数千字节。随后几天,攻击者尝试访问不存在的 .sig 文件,在 httperror-vpn 日志中产生了文件缺失错误,说明这些文件并不存在。这可能表明攻击者正在多个已攻陷环境中管理类似的 web shell。
Root 权限持久化
尽管对 CVE-2026-88772 的初始利用以 root 权限执行,但 web 服务器(httpd)后续处理的请求运行在无特权的 web 服务上下文中。为了给 web shell 建立持久的 root 级执行能力,威胁行为者利用其轻量级安装器 web shell,为 /bin/sh 可执行文件设置 setuid(Set User ID)位:
chmod u+s /bin/sh
图 5:设置 User ID 的命令
通过修改 /bin/sh 的权限,威胁行为者得以确保 web 服务器后续处理的 web 请求以提升后的权限执行。为了在修改 SUID shell 的同时应用 /etc/httpd.conf 的改动,安装器触发了 NetScaler 设备的完整重启(/netscaler/nsshutdown -R)。
在 web shell 的其他变体中,威胁行为者直接下发命令重启 web 服务,并为 /bin/sh 可执行文件赋予 root setuid(Set User ID)权限。
system('/bin/httpd -k restart -f /etc/httpd.conf && chmod u+s /bin/sh');
图 6:重启 web 服务的命令
恶意软件分析
威胁行为者部署了多个 PHP web shell 以及一个隧道类恶意软件,将流量代理进受害组织的网络,为内部侦察、横向移动和凭据窃取提供便利。
安装器与独立 web shell
Mandiant 恢复了多个轻量级 PHP web shell,它们被放置在扩展名为 .deb 和 .sig 的文件中,可提供直接命令执行和自动化的设备持久化。在直接观察到的入侵中,web shell 的文件名因受害者而异。我们观察到多个轻量级 web shell 的示例,其文件名使用 “nginstaller” 的各种变体,后面通常跟一个数字。
- 一个示例在通过命令行界面(CLI)执行时,会修改
/etc/httpd.conf,为/bin/sh启用 setuid root 权限(chmod u+s /bin/sh),从/etc/crontab中清除对/vpn/scripts/linux的引用,并通过/netscaler/nsshutdown -R重启设备。通过 HTTP 时,它从HTTP_NSC_LDAP头中提取 Base64 编码的命令,经shell_exec()执行,并返回 Base64 编码的输出。 - 另一个已观察到的 Web Shell 变种会返回伪造的 HTTP
404 Not Found响应码。它重启 Apache 守护进程(/bin/httpd -k restart -f /etc/httpd.conf)以应用配置变更,并使用eval()执行传入的 payload。为规避检测,它使用正则表达式(#^.*/vpn/scripts/linux.*\n#m)系统性地从系统/etc/crontab中清除自身安装路径。该 Web Shell 将经由 HTTP 从HTTP_NSC_LDAP头接收的 Base64 编码 payload 直接用 PHP 通过eval()执行。 - e6ee7c85.sig:一个同样强制返回
HTTP 404 Not Found响应的 Web Shell 变种,但它从HTTP_NSC_CLIENTTYPE请求头中提取 Base64 编码的 payload,同样通过eval()执行。
WHIPSHOT
nohup <python> -c 'import base64;exec(base64.b64decode("<payload>"))' /tmp/.uxdport /tmp/.uxdlock > /dev/null 2>&1 </dev/null &
图 7:在后台执行 SLAPSHOT 的命令
- 回环 IPC:SLAPSHOT 启动后,WHIPSHOT 读取记录在
/tmp/.uxdport中的动态 TCP 端口,与127.0.0.1:建立 socket 连接,并转发客户端请求。 - 规避:WHIPSHOT 抑制标准错误输出(
error_reporting(0)),设置 HTTP404 Not Found响应头,同时将隧道传输的 TCP 响应放在 HTTP body 中返回。
SLAPSHOT
SLAPSHOT 是一款用 Python 编写的 TCP 隧道工具。它充当内网网桥,接收来自 WHIPSHOT 的命令,并将任意 TCP 流转发至内网主机。 其关键能力与行为包括:
- 动态端口绑定与锁定:启动时,SLAPSHOT 绑定到 127.0.0.1 上的临时端口,将当前端口号写入指定文件(如
/tmp/.uxdport),并通过 fcntl.flock 对锁文件(如/tmp/.uxdlock)加独占文件锁,确保同一时间只有一个实例运行。 - 自定义线路协议:与代理的通信使用自定义二进制协议,每条消息由 4 字节大端长度前缀和随后的 JSON payload 组成。支持的命令动作包括:
open:向目标主机和端口建立出站 TCP socket。push:向已打开的会话写入数据。pull:轮询并读取已打开会话 socket 中的数据。exch``:向已打开的会话 socket 发送 C&C 数据并接收其返回数据。close:终止指定的网络会话。ping:执行基本的健康检查验证。 空闲超时:守护进程会监控连接活动,在 15 分钟无活动后自动关闭各个会话 socket。如果 10 分钟内未收到任何活动会话或命令(可通过 UXD_IDLE_EXIT 变量配置),SLAPSHOT 会删除其端口文件和锁文件,并终止自身进程,以尽量减小内存占用和被发现的风险。
影响
这次行动凸显出攻击者持续瞄准边缘设备,将其作为进入受害者网络的初始入口。GTIG 在多个威胁行为体身上都追踪到了这一趋势。值得注意的是,这些漏洞约占2025 年企业相关零日漏洞的一半。这类设备——包括应用交付控制器、VPN 网关和防火墙——之所以始终是诱人的目标,是因为它们暴露在互联网上,处于端点检测与响应(EDR)工具的覆盖范围之外,而且往往存储或处理可用于向网络内部横向移动的凭据。鉴于这一手法已被证明行之有效,我们预计威胁行为体会继续利用边缘设备中的漏洞。
狩猎、遏制与修复指南
组织应首先分析现有日志和配置文件,以发现可能的失陷迹象。
狩猎策略
Citrix NetScaler ADC 设备
- 检查 Web 服务器配置: 检查所有 NetScaler ADC 设备上的
/etc/httpd.conf,排查是否存在未授权的 MIME 类型、脚本处理程序指令或 Web 路径别名。若发现任何AddHandler或AddType将非 PHP 文件扩展名(如.deb、.sig、.html、.rpm或.tgz)注册为 PHP 脚本执行,或有任何AliasMatch将公开 Web 路径(/vpn/media/、/vpn/theme/、/vpn/images/)指向设备脚本目录,即表明系统已被入侵。
grep -En -i "application/x-httpd-php|php_flag|AliasMatch" /etc/httpd.conf
图 8:Web 路径别名
- 审计 Appliance 暂存目录与客户端插件目录: 审计原生客户端插件路径(
/var/netscaler/gui/vpn/scripts/linux/、/var/netscaler/gui/vpns/scripts/vista/、/var/netscaler/gui/vpns/scripts/mac/)和 Web 资源路径(/netscaler/ns_gui/vpn/media/、/var/vpn/theme/)的内容。这些目录中合法的客户端交付物应为编译后的二进制文件或归档文件;凡被识别为 ASCII 文本或包含 PHP 脚本标记的文件,均属异常。在默认安装中,这些目录存放的是合法的已编译客户端二进制文件和静态 Web 资源。请检查其中是否存在以非脚本扩展名伪装的纯文本脚本,或包含 PHP 代码的文件:
file /var/netscaler/gui/vpn/scripts/linux/* /var/netscaler/gui/vpns/scripts/vista/* /var/netscaler/gui/vpns/scripts/mac/* /netscaler/ns_gui/vpn/media/* 2>/dev/null | grep -E "ASCII text|PHP script"
grep -rlE "<\?php|eval\(|base64_decode\(|shell_exec\(" /var/netscaler/gui/ /netscaler/ns_gui/ /var/vpn/ /netscaler/portal/ 2>/dev/null
图 9:检查客户端插件路径,查找伪装成非脚本扩展名的脚本或包含 PHP 代码的文件
- 检查 Web 服务器访问日志与错误日志: 检查
/var/log/httperror*中是否存在涉及伪装或非标准文件扩展名的语法、解析或执行错误(即使访问日志已被清理,这些错误仍会保留)。审计/var/log/httpaccess.log中是否有针对静态媒体、图标或脚本路径的请求返回伪造的 HTTP 404 状态码或异常大的响应体。在访问日志中搜索/vpn/scripts/或/vpn/media/附近突然出现的时间断层或被截断的行,这可能表明攻击者基于正则表达式的日志清除工具已被执行。
grep -E -i "\.(deb|sig|rpm|tgz|sh|so|dat|ico|png|html)" /var/log/httperror*
图 10:搜索非标准文件扩展名并执行
grep -E "/vpn/media/|/vpn/scripts/|/vpn/theme/" /var/log/httpaccess.log* | awk '$9 ~ /200|404/ && $10 > 5000'
图 11:搜索异常大的响应负载
- 检查临时 IPC 产物:检查设备上的 /tmp/ 目录,查找 SLAPSHOT 创建的锁文件和端口指针文件。若存在
/tmp/.uxdport或/tmp/.uxdlock,说明 SLAPSHOT 代理守护进程正在运行或近期运行过。响应人员应记录.uxdport中的端口,并通过sockstat -4 -l检查监听进程:
ls -la /tmp/.uxdport* /tmp/.uxdlock
图 12:搜索由 SLAPSHOT 创建的文件
- 验证 Shell 与二进制文件权限: 检查
/bin/sh,确认未建立未经授权的 SUID 权限。如果权限显示为-rwsr-xr-x且属主为 root,则说明该二进制文件已被篡改,用于通过 setuid 实现提权持久化。
ls -l /bin/sh
图 13:检查未授权的 SUID 权限
- 检查进程执行与 Shell 历史记录:检查系统中的活动进程,查看是否存在异常的 Python 解释器在后台执行引用
/tmp/.uxdport的命令,或以nohup身份运行。查看/var/log/sh.log,找出在变更窗口之外执行的管理类命令,包括强制重启(/netscaler/nsshutdown -R)和手动重启 Apache(httpd -k restart)。
ps aux | grep -E "python.*(\.uxd|uxdport|uxdlock|base64)"
图 14:检查系统进程中是否存在异常的 Python 解释器
注意: Citrix 已发布指南,说明如何使用其入侵指标(IOC)扫描工具识别组织 NetScaler 基础设施上的潜在入侵指标。更多细节请参阅以下 Citrix 文档:
- https://docs.netscaler.com/en-us/netscaler-console-service/instance-advisory/security-advisory-dashboard.html
- https://docs.netscaler.com/en-us/netscaler-console-service/instance-advisory/ioc.html
注意:组织应在更广泛的基础设施上整体运用这些狩猎技术,以识别可能源自 NetScaler 基础设施的横向移动。这些技术应覆盖整个环境,包括但不限于其他特权访问管理(PAM)平台。
遏制与修复策略
尚未应用最新安全更新的组织应立即评估自身的暴露面和风险。对 NetScaler Gateway 实施大范围互联网隔离或严格的 IP 允许列表,会给通过 Citrix Virtual Apps and Desktops(原 XenApp 和 XenDesktop)支持远程办公的组织造成严重中断。因此,Mandiant 建议采取有针对性的分阶段方法,优先打补丁,同时根据组织的风险状况实施适当的遏制措施和补偿性控制。
即时缓解措施
组织应根据自身的风险容忍度、失陷证据和运营需求评估以下选项。
选项 1 — 应用最新的 Citrix 版本(Mandiant 推荐)
部署已修复相关漏洞的最新 Citrix 版本。组织应根据当前所处的部署分支,升级到以下修复版本(或更高版本):
- NetScaler 14.1 分支:升级到 14.1-73.37 及更高版本。
- NetScaler 13.1 分支:升级到 13.1-64.23 及 13.1 的更高版本。
注意:14.1-FIPS 和 13.1-FIPS/NDcPP 部署也有对应的修复版本。
如果组织无法在 Citrix 客户下载门户中找到特定版本,应通过 Citrix 提交严重级别 1 的支持工单,以确认并获取包含所需修复的最新版本。
方案 2 — 隔离已失陷或疑似失陷的设备
对于已确认或疑似失陷的 NetScaler 设备,应将其从网络中隔离。此方案可能造成严重的业务中断,尤其是当该设备承担远程访问或其他关键服务时。 如果上述排查策略发现了失陷指标,Mandiant 建议实施以下遏制措施:
- 隔离节点。 立即将已确认或疑似失陷的设备从网络中移除。
- 停止 HA 同步。 对于以高可用(HA)对形式部署的 NetScaler,应分别评估两个节点。在两个节点均通过验证之前,禁用配置同步,以防失陷节点将恶意更改(例如被篡改的 httpd.conf 文件)复制到备用节点。
- 限制出站流量。 封禁已观测到的攻击者基础设施,并限制该设备的出站互联网连接。尤其要阻止任意的出站 TCP/UDP 流量,并在非明确需要的情况下阻止经 TCP/25 的出站 SMTP。
- 检查 hypervisor 网络隔离。 如果 NetScaler 以 VPX 设备形式运行在虚拟化环境中,应检查 vSphere vSwitch 和 Port Group 配置。确认 NetScaler VPX 已得到适当分段,且不与 hypervisor 管理接口(如 ESXi vmk0 或 vCenter)或其他高度敏感的基础设施层级共享二层网络。更多建议请参阅 Mandiant 针对 vSphere 的加固指南。
方案 3 — 实施有针对性的补偿性控制措施
如果无法立即打补丁,组织应实施有针对性的控制措施,在受影响设备完成更新之前缩小暴露的攻击面。下文中针对 DTLS 和 UDP/443 的控制措施仅适用于 CVE-2026-88772,不应依赖其缓解 CVE-2026-88771。要同时解决这两个漏洞,仍须安装修复后的 NetScaler 版本。 A 部分 — 网络限制
- 在运营允许的情况下禁用 DTLS。 如果补丁无法及时部署,请在面向互联网的 NetScaler Gateway 虚拟服务器上禁用并非必需的 DTLS。在本次攻击活动中,漏洞利用载荷通过 UDP/443 使用数据报传输层安全协议(DTLS)投递。
- 在上游限制入站 UDP/443。 除非明确需要 DTLS,否则应阻止发往受影响设备的入站 UDP/443 流量。该控制措施应在上游边界防火墙或边缘路由器上实施。仅依赖 NetScaler 本地 ACL 会让流量先到达存在漏洞的数据包处理引擎(nsppe),之后才被丢弃。
- 在可行的情况下实施上游 IP 白名单。 仅将 NetScaler 用于负载均衡的组织,或所运营的 Access Gateway 只服务于一组可预测的外部源 IP 地址的组织,应考虑在上游网络 ACL 中丢弃未授权流量,使其在到达设备之前就被拦截。
对于支撑大量远程办公人员的公网 VPN,这种做法可能并不现实,因为动态住宅 IP 地址会带来可观的行政和运维负担。
- 保留虚拟设备状态以供取证分析。 对于以虚拟设备形式部署的 NetScaler,包括运行在 VMware vSphere 或其他 hypervisor 上的 NetScaler VPX,只要运营上允许,应在重启前创建包含内存状态的完整 VM 快照。
Part B — 凭据轮换与会话终止 组织应假设被入侵设备上存储的凭据可能已经泄露。凭据轮换和会话终止需要在该设备与相连系统之间协同进行。
- 撤销活动会话。 使现有的管理、Gateway 和 VPN 会话失效,以清除可能已泄露的会话令牌。对于将该设备用作 Citrix Virtual Apps and Desktops 网关的组织,还应包括在适当情况下终止活动的 ICA/HDX 会话。更多指引参见 Citrix CTX584227。
- 轮换设备密钥。 轮换 NetScaler 管理员凭据、本地设备账户、Secure Shell(SSH)密钥、TLS 证书及相关私钥。
- 轮换集成凭据。 轮换 LDAP bind 账户和服务账户、RADIUS 共享密钥、TACACS 凭据、SNMP community string,以及 NITRO/应用程序编程接口(API)凭据。
- 审计下游 Citrix 基础设施。 检查与 NetScaler 直接通信的系统,尤其是 Citrix StoreFront 服务器、Citrix Delivery Controller(DDC)以及内部 Citrix Virtual Apps and Desktops 主机。检查 Windows 事件日志,查找异常的交互式登录、非预期的远程桌面协议(RDP)活动、凭据转储的迹象,以及其他横向移动的证据。
组织还应考虑吊销并轮换受感染设备上存储的 TLS 证书及相关私钥。 注意: 应在设备成功修补后轮换凭据。
Part C — 控制平面限制 组织应对 NetScaler 的控制平面和管理平面施加额外限制。
- 仅向面向互联网的服务开放必需的端口和协议。
- 为 NetScaler 设备实施默认拒绝的出站防火墙规则。
- 仅允许出站连接到明确批准的目标和服务,包括 DNS、NTP、必需的 OCSP/CRL 服务、已批准的后端应用,以及已批准的管理和安全基础设施。
- 除非有书面记录的业务需求,否则明确阻止经 TCP/25 的出站 SMTP。
- 防止 NSIP 和管理接口暴露于互联网。
- 将 SSH、HTTPS 管理访问和 NITRO/API 访问限制在专用管理网络、已批准的跳板主机和明确批准的源 IP 范围内。
Part D — 日志与检测工程 检测是响应策略的关键组成部分。Mandiant 建议从两个方面开展检测:确保必要的遥测数据可用,以及实施能够关联网络、设备、文件系统和身份活动的检测。 日志与可见性 下文中的若干检测依赖 NetScaler 默认不转发的日志。在实施检测逻辑之前,请确认 SIEM 能收到以下遥测数据:
- 通过 syslog action 转发的 NetScaler 审计日志(ns.log),包括与 SSL 相关的事件。
- 设备的 FreeBSD 系统日志(/var/log/messages),其中记录 NSPPE 终止/崩溃和 pitboss 消息,且不包含在标准 ns.log 转发中。
- Web 服务器日志(
/var/log/httpaccess.log和/var/log/httperror*)、NetScaler Web Logging 或 AppFlow 遥测。由于 TLS 在设备上终止,上游网络设备通常无法检查 HTTP 请求路径或标头。 - 源自 NetScaler NSIP 和 SNIP 地址的流量的防火墙或网络流日志。
- Secret Server 或其他特权访问管理(PAM)审计日志。
检测工程
协议与流量分析
- 对利用特征的 DTLS 失败告警。 关注 ClientVersion 为 DTLSv1.0、原因为 Handshake failure-Internal Error 的 SSL_HANDSHAKE_FAILURE 事件。在此活动中观察到的成功利用会产生该事件。逐一审查每次出现,并优先处理来自同一设备的聚集性事件。
- 将 DTLS 失败与引擎终止/崩溃关联。 同一设备上先出现匹配的 DTLS 握手失败、几分钟内又发生 NSPPE 终止/崩溃,是强烈的利用信号,应高优先级调查。
- 审查意外的入站 UDP/443。 重点关注已禁用 DTLS 或本不应有 DTLS 的设备。为通常与各 Gateway 建立 DTLS 连接的来源建立基线。利用行为可能只需极少的流量,因此仅靠基于流量的异常检测未必能识别该活动。
设备进程与内存稳定性
- 监控 NSPPE 终止/崩溃。 对表明 NSPPE 进程退出或被信号终止的内核消息生成高严重级别告警。同时监控 /var/core/ 下是否创建新的 NSPPE core 文件。
- pitboss 未重启 NSPPE 时告警。 监控包含 pitboss NOT restarting NSPPE 的 pitboss 消息。对这些消息和 NSPPE 内核终止/崩溃事件分别独立告警,而不是要求两个条件同时满足。
- 与可用性事件关联。 同一时间窗口内,面向互联网的 Gateway 出现意外 HA 故障切换或设备重启,应视为潜在利用的佐证。
文件系统与配置完整性
- 监控关键 VPN 脚本路径。 检测 VPN 相关目录中 .sig 文件的创建、修改或暂存,包括 nsgclient.sig 等文件,相关目录例如:
/var/netscaler/gui/vpn/scripts/linux//netscaler/ns_gui/vpn/scripts/linux//var/netscaler/gui/vpns/scripts/vista//var/netscaler/gui/vpns/scripts/mac//netscaler/ns_gui/vpn/media//var/vpn/theme/
检测未经授权的 Web 服务器配置更改。 监控 /etc/httpd.conf、/nsconfig/httpd.conf 和 /flash/nsconfig/httpd.conf 是否被未经授权修改。尤其要对以下情况告警:
- 新增或修改 AddHandler application/x-httpd-php .[ext] 指令。
- php_flag engine on 配置,或其他启用 PHP 执行的改动。攻击者的活动包括使用 .php 以外扩展名的 PHP Web Shell,具体扩展名因环境而异。将 /vpn/media/、/vpn/theme/、/vpn/images/ 等 Web 资源路径映射到脚本目录或可执行文件的 Alias、AliasMatch 或 RewriteRule 指令。
定期检查运行时状态。 重点监控:
/bin/sh 被设置 SUID 位
存在 /tmp/.uxdport 或 /tmp/.uxdlock
通过 nohup 启动、或包含 Base64 编码载荷的 Python 进程
/nsconfig/ 下持久化配置或启动文件出现异常改动
出站与交互监控
- 检测 Web Shell 与静态资源或客户端脚本路径的可疑交互。 关注行为本身,而不只是请求的路径,因为正常客户端也会频繁访问 /vpn/media/ 下的资源。可能的迹象包括:
- 对
/vpn/media/*.ico或/vpn/scripts/路径的请求返回 404,但响应体达到数 KB,或处理时间异常长。 - HTTP 错误日志中出现涉及 .sig 等非标准文件的 “File does not exist” 记录,且位于
/vpn/scripts/下。即使访问日志已被修改或清除,这类事件仍可能留存。 - httpaccess.log 中针对
/vpn/scripts/或/vpn/media/的请求附近出现缺失、格式错误或截断的行。
识别设备的异常出站流量。 监控直接从 NetScaler 设备发起的出站连接,当目标不在组织批准的白名单内时告警。优先关注涉及凭据保险库和 PAM 系统的活动、通过异常端口连接域控制器、短时间内连接大量内部系统,以及经 TCP/25 发出的 SMTP 流量。
入侵指标(IOC)
网络与传输层指标
| 类型 | 描述 | 指标 |
|---|---|---|
| 入站网络流量 | 用于投递零日漏洞利用的传输协议 | UDP :443 (DTLSv1.0) |
| HTTP 请求头 | nsginstaller.deb 使用的入站命令执行请求头 | HTTP_NSC_LDAP |
| HTTP 请求头 | nsgclient.sig 使用的入站命令执行请求头 | HTTP_NSC_CLIENTTYPE |
| HTTP 请求头 | WHIPSHOT 使用的分块 Base64 传输请求头 | HTTP_X_UX / HTTP_X_UX_[0-9]+ |
| URI 路径 | 经 AliasMatch 路由到 .sig Web Shell 的伪装图标请求 URI | /vpn/media/nsgclient.ico / /vpn/media/*.ico |
| URI 路径 | NetScaler Gateway 上恶意 PHP Web Shell 的暂存路径 | /vpn/scripts/linux/nsginstaller*.deb/vpn/scripts/linux/nsgclient*.deb/vpn/scripts/linux/*.php |
| IPv4 地址 | 扫描与暂存基础设施 | 143.198.7.94 |
| IPv4 地址 | NetScaler 漏洞利用及基础 Web Shell 后门安装 | 157.254.167.12 |
为帮助更广泛的社区追踪和识别本篇博文中描述的活动,我们已在 GTI Collection 中为注册用户提供了入侵指标(IOC)。
文件指标
| 文件路径 | /tmp/.uxdport | SLAPSHOT 活动端口痕迹 |
|---|---|---|
| 文件路径 | /tmp/.uxdlock | SLAPSHOT 进程锁痕迹 |
检测
YARA 规则
rule G_APT_Backdoorwebshell_WHIPSHOT_1
{
meta:
description = "Detects WHIPSHOT PHP webshell tunneling frontend deployed on Citrix NetScaler ADC appliances"
author = "GTIG"
family = "WHIPSHOT"
strings:
// Chunked transport headers
$sh1 = "HTTP_X_UX" ascii
$sh2 = "HTTP_X_UX_" ascii
// IPC lock and port pointers to local proxy daemon
$si1 = "/.uxdport" ascii
$si2 = "/.uxdlock" ascii
$si3 = "/tmp/.uxdport /tmp/.uxdlock" ascii
// Socket forwarding logic
$sf1 = "fsockopen" ascii
$sf2 = "127.0.0.1" ascii
condition:
filesize < 50KB and (
($sh1 or $sh2) and ($si1 or $si2 or $si3) and ($sf1 or $sf2)
)
}
rule G_APT_Tunneler_SLAPSHOT_1
{
meta:
description = "Detects SLAPSHOT Python proxy daemon and tunneling tool deployed alongside WHIPSHOT on compromised NetScaler appliances"
author = "GTIG"
family = "SLAPSHOT"
strings:
// Lock and port files
$ss1 = "/tmp/.uxdport" ascii fullword
$ss2 = "/tmp/.uxdlock" ascii fullword
$ss3 = "UXD_IDLE_EXIT" ascii fullword
$ss4 = "127.0.0.1" ascii
// Wire protocol command verbs
$sc1 = "\"open\"" ascii fullword
$sc2 = "\"conn\"" ascii fullword
$sc3 = "\"push\"" ascii fullword
$sc4 = "\"pull\"" ascii fullword
$sc5 = "\"exch\"" ascii fullword
$sc6 = "\"close\"" ascii fullword
$sc7 = "\"ping\"" ascii fullword
// Protocol parameter names
$sp1 = "\"sid\"" ascii fullword
$sp2 = "\"host\"" ascii fullword
$sp3 = "\"port\"" ascii fullword
$sp4 = "\"data\"" ascii fullword
condition:
filesize < 30KB and (
($ss1 and $ss2 and $ss3) or
($ss4 and ($ss1 or $ss2) and 3 of ($sc*) and 2 of ($sp*)) or
($ss3 and 3 of ($sc*) and 2 of ($sp*))
)
}
rule G_Hunting_Config_NetScaler_PHP_1
{
meta:
description = "Detects unauthorized Apache configuration directives registering non-standard extensions as PHP scripts, or aliasing web paths to appliance script directories on Citrix NetScaler ADC"
author = "GTIG"
strings:
// NetScaler appliance configuration context markers
$ns1 = "/netscaler" ascii nocase
$ns2 = "/var/netscaler" ascii nocase
$ns3 = "/vpn/" ascii nocase
$ns4 = "ns_gui" ascii nocase
$ns5 = "<VirtualHost *:81>" ascii nocase
$ns6 = "Listen 81" ascii nocase
// Generic type or handler registration mapping non-standard file extensions to PHP
// Diversion of web asset paths (media, theme, help, logon, images) to script staging directories
$a1 = "AliasMatch" ascii nocase
$a2 = /\^?\/vpn(s)?\/(media|theme|themes|images|help|logon|support)\// ascii nocase
$a3 = /\/var\/netscaler\/gui\/vpn(s)?\/scripts\// ascii nocase
$a4 = /\/vpn(s)?\/scripts\// ascii nocase
// PHP execution flags
$p1 = "php_flag engine on" ascii nocase
// Exclusions for web pages, markup, and source code
$not_html1 = "<html" ascii nocase
$not_html2 = "<!DOCTYPE" ascii nocase
$not_html3 = "<?xml" ascii nocase
$not_code1 = "package " ascii
$not_code2 = "#include " ascii
condition:
filesize < 100KB and not (
$not_html1 or $not_html2 or $not_html3 or $not_code1 or $not_code2
) and (1 of ($ns*)) and (
// Any directive registering a non-PHP extension as PHP
$t1 or
// Any AliasMatch diverting web paths to script directories
($a1 and ($a2 or $a3 or $a4)) or
// Generic combination of php_flag engine on with script directory aliasing
($p1 and $a1 and ($a3 or $a4))
)
}
rule G_Hunting_Backdoorwebshell_NetScaler_C2Headers_1
{
meta:
description = "Detects standalone PHP webshells deployed on NetScaler appliances extracting commands from custom or native SetEnvIf HTTP headers"
author = "GTIG"
strings:
// NetScaler C2 header patterns (both HTTP_NSC_* and raw NSC_*, covering all native SetEnvIf variables)
$h1 = /(HTTP_)?NSC_[a-zA-Z0-9_]+/ ascii
$h2 = /(HTTP_)?NSC_(USER|NONCE|LDAP|CLIENTTYPE|FT_HIDE)/ ascii nocase
// Specific named NetScaler SetEnvIf headers
$hs1 = "HTTP_NSC_LDAP" ascii fullword nocase
$hs2 = "HTTP_NSC_CLIENTTYPE" ascii fullword nocase
$hs3 = "HTTP_NSC_USER" ascii fullword nocase
$hs4 = "HTTP_NSC_NONCE" ascii fullword nocase
$hs5 = "HTTP_NSC_FT_HIDE" ascii fullword nocase
$hs6 = "NSC_USER" ascii fullword nocase
$hs7 = "NSC_NONCE" ascii fullword nocase
$hs8 = "NSC_LDAP" ascii fullword nocase
$hs9 = "NSC_CLIENTTYPE" ascii fullword nocase
$hs10 = "NSC_FT_HIDE" ascii fullword nocase
// Dynamic execution sinks
$e1 = "eval(base64_decode(" ascii
$e2 = "shell_exec(base64_decode(" ascii
$e3 = "system(base64_decode(" ascii
$e4 = "passthru(base64_decode(" ascii
$e5 = "eval(" ascii
$e6 = "base64_decode(" ascii
$e7 = "shell_exec(" ascii
$e8 = "passthru(" ascii
$e9 = "system(" ascii
$e10 = "exec(" ascii
$e11 = "popen(" ascii
$e12 = "proc_open(" ascii
$e13 = "assert(" ascii
// Concealment and response markers
$c1 = "http_response_code(404)" ascii
$c2 = "REQUEST_METHOD" ascii
$c3 = "<FATO>" ascii
$c4 = "</FATO>" ascii
condition:
filesize < 50KB and (
// Any NSC header accessed alongside dynamic execution
((1 of ($h*) or 1 of ($hs*)) and ($e1 or $e2 or $e3 or $e4 or ($e6 and ($e5 or $e7 or $e8 or $e9 or $e10 or $e11 or $e12 or $e13)))) or
// Any NSC header paired with concealment markers
((1 of ($h*) or 1 of ($hs*)) and ($c3 or $c4 or ($c1 and $c2))) or
// Standalone FATO marker webshell
(($c3 and $c4) and ($e1 or $e2 or ($e5 and $e6) or ($e6 and $e7)))
)
}
rule G_Hunting_Script_NetScaler_Persistence_1
{
meta:
description = "Detects appliance staging, installer, and anti-forensic maintenance scripts deployed during NetScaler compromise"
author = "GTIG"
strings:
// Appliance restart / shutdown commands
$cmd1 = "/netscaler/nsshutdown" ascii
$cmd2 = "nsshutdown -R" ascii
// SUID root backdoor creation
$cmd3 = "chmod u+s /bin/sh" ascii
// Web server reload / restart
$cmd4 = "/bin/httpd -k restart" ascii
$cmd5 = "httpd -k restart -f /etc/httpd.conf" ascii
// Forensic access log scrubbing regex pattern (across any staging path)
$scrub1 = /#\^\.\*\/vpn(s)?\/(scripts|media|theme|themes|help|logon)/ ascii
// Apache configuration modification strings
$cfg1 = "AddHandler application/x-httpd-php" ascii
$cfg2 = "AddType application/x-httpd-php" ascii
$cfg3 = "php_flag engine on" ascii
$cfg4 = "AliasMatch" ascii
$cfg5 = "SetEnvIf" ascii
condition:
filesize < 50KB and (
// Log scrubber + privilege escalation or web server restart
($scrub1 and ($cmd3 or $cmd4 or $cmd5)) or
// SUID root backdoor creation + appliance command or config modification
($cmd3 and ($cmd1 or $cmd2 or $cmd4 or $cmd5 or $cfg1 or $cfg2 or $cfg3 or $cfg4 or $cfg5)) or
// Configuration tampering + appliance command
(($cfg1 or $cfg2 or $cfg4) and ($cmd1 or $cmd2 or $cmd4 or $cmd5)) or
// Generic 2 of the specific appliance maintenance commands
(2 of ($cmd*))
)
}
Google Security Operations
Google Security Operations 用户可使用以下规则。这些规则位于 Mandiant Frontline Threats 规则包中:
- SUID or SGID Bit Set on System Shell Binary
- HTTPD Custom Configuration Restart Chained with Permission Modification
- NetScaler Web Directory Suspicious Filewrite
- Python Base64 In-Memory Execution with Hidden Temp File
- Citrix NetScaler Crontab Installation Path Scrubbing
- Citrix NetScaler
ns_monuploadd_err.plLog Poisoning Command Injection - Citrix NetScaler DTLSv1.0 Handshake Failure Internal Error or NSPPE Crash
- Citrix NetScaler Masqueraded Webshell HTTP Request or PHP Error Telemetry
致谢
感谢 Bella Valdescruz、Bhavesh Dhake、Chris Linklater、Christopher Romano、Geoff Carstairs、Greg Blaum、Josh Thackston、Kimberly Goody、Lianis Oliva、Matthew Quick、Michael Edie、Omar ElAhdan、Peter Ukhanov、Sagun Chetry、Stuart Carrera、Tyler McLellan 的协助,本次分析才得以完成。