漏洞
Citrix NetScaler:日志怎样变成了命令
NetScaler CVE-2026-88771 已遭利用,公开补丁揭示维护脚本会把日志中的外部文本带入 shell;管理员应安装对应分支的修复包,同时保全升级前的入侵线索,当前普通分支目标为 14.1-73.37 或 13.1-64.24。

文章导航
一次登录失败,通常会留下一个用户名、一条错误和一个时间。系统把它们记下来,供管理员日后排查。NetScaler 这次的问题就藏在“日后”两个字里:外部请求中的文字进入日志后,还会被维护脚本重新读取;脚本从中拼出文件名,再把这个文件名放进 shell 命令。原先只该描述一次请求的内容,由此获得了控制设备操作的机会。
9 月 27 日,Citrix 在 CTX697096 公告中确认 CVE-2026-88771 和 CVE-2026-88772 已遭利用,并发布修复。CISA 同日把两项漏洞加入 KEV;澳大利亚 ACSC 在 28 日的通告也说明,全球利用活动早于补丁可用时间。28 日,watchTowr 公布了 88771 的脚本差异,才让这条从请求到后台任务的路径变得具体。
对正在维护这类网关的人,眼前同时有两件急事:堵住后续入口,查清更新前是否已经有人进来。升级会改变现场,继续暴露又会增加风险。我们的建议是尽快限制未修设备的可达范围,安排必要的证据保全与修补并行推进;普通 14.1 分支当前采用 14.1-73.37,13.1 分支采用 13.1-64.24。后者比安全公告最初列出的版本多了一个小版本,原因涉及升级时的循环重启,后文会单独说明。
1 请求结束以后,文字还在继续流动
先把两项正在遭利用的漏洞分开。88771 允许未经认证的命令执行,厂商列出的配置前提覆盖所有受影响的 NetScaler ADC 和 Gateway 部署,默认配置也在其中。88772 是另一项内存溢出,要求启用 DTLS;VPN virtual server 默认开启 DTLS。关闭 DTLS 可以改变后者的前提,88771 的日志处理路径仍需修复。两者可以独立造成远程代码执行,不能把其中一项的配置检查当作整个公告的排除条件。
这些范围针对客户自行管理的设备,也包括 Secure Private Access Hybrid 使用的 NetScaler 实例。Citrix 管理的云服务及 Adaptive Authentication 由厂商更新。对自行维护的设备,只查有没有 VPN 登录页还不够:88771 的官方范围没有要求先启用额外功能,待处理的对象应从固件版本和实际部署清单开始找,包括备用实例。
为什么登录失败也可能留下可用的输入?认证系统为了排错,会记录失败请求里的部分字段。账号是否合法,与日志是否保留这个账号字符串,是两个不同的处理步骤。watchTowr 公开的观察中,登录字段出现在认证相关日志里;随后读取日志的程序看见的是磁盘上的一行文字。它需要重新判断这行文字哪些部分可信。
公开差异定位到设备上的 /netscaler/ns_monuploadd_err.pl。研究者比较了 14.1-73.30 与 14.1-73.37,展示了提取崩溃文件名及调用 find 的改变。本文据此解释数据如何流动;完整厂商脚本、提交历史和原始行号没有公开,SOSEC 未取得固件或独立运行漏洞。公开补丁节选是下面代码分析的依据,设备执行结果归属于研究者的实验。
这个脚本有一个正常任务:从日志中找到 Packet Engine 异常退出的信息,再定位对应的 core 文件。core 保存进程退出时的内存信息,供后续诊断。正常日志中的引擎编号和进程号可以组合成候选文件名,例如:
pitboss: NSPPE-00 (12345) unexpectedly died
↓
NSPPE-00-12345
这里的 NSPPE-00 是引擎名称,12345 是示例进程号。要完成诊断,脚本只需要这两项受约束的信息。旧实现却从符合关键词的日志行中剪取文本:先找出看起来像进程故障的行,留下最后一条,再用 sed 和 awk 去掉部分字符、拼接字段。关键词可以出现在一行日志的任意位置,这种筛选没有确认匹配内容真是由故障报告程序写出的结构化字段。
2 危险发生在第二次解释
到这一步,摘出的内容仍然只是 Perl 字符串。即使字符串里出现了 shell 使用的分隔符,第一次提取也不会因为输出了这些字符就执行它们。问题出在下一次使用:旧脚本把候选名称插进另一条反引号命令,让 shell 去运行 find。这时,数据与命令语法合到了一条字符串里。
下面用伪代码保留这个变化,省略日志路径和无关诊断工作:
candidate = fields_selected_from_log
command_text = "find " + core_directory + " -name " + candidate + "* ..."
core_path = run_through_shell(command_text)
脚本希望 candidate 只占据“要查找的文件名”这个位置。shell 处理的是整条命令文本,会解释其中的语法字符;它没有一份额外信息告诉自己,哪些字符来自程序作者,哪些来自先前记录的请求。这就是这里的命令注入:外部文本经过日志和文件名变量之后,最终进入了一个会再次解释语法的消费者。
这条路径也解释了时间上的错位。请求写入日志和维护脚本读取日志可以发生在不同时间。研究者报告过等待后台任务的情况,其实验中执行命令的进程具有 root 权限。这个观察要求排查同时关注请求时间与后续进程、文件变化;一个 HTTP 响应只能说明请求得到了处理,无法单独说明后台代码何时运行。公开材料提到的等待时长也不能当作留给管理员的安全窗口。

因此,我们不建议把临时防守押在某一个登录 URL 或一段公开样例字符串上。真正需要保护的是可写入相关日志的外部入口,以及随后消费这些日志的旧脚本。研究者展示了具体入口,厂商给出的受影响配置范围更广;目前公开材料不足以替每一种部署写出一条覆盖完整的拦截规则。无法及时修补时,把受影响服务隔离或下线,代价是相应的远程访问或应用交付会中断。只做来源限制可以减少暴露,允许范围内的请求仍可能到达设备。
3 补丁让文件名保持为数据
补丁没有放弃从日志里寻找 core 文件。它先收窄需要提取的内容:用 Perl 直接读文件,匹配引擎名称与括号内的数字进程号,再从捕获结果重建名称。公开正则中的两个捕获组是 (NSPPE-\d{2}) 和 (\d+)。旁边出现的其他日志文字不会跟着进入新名称。合法的诊断任务仍能取得所需编号,不再依靠任意截出的前两个字段。
接下来,调用 find 的方法也改变了。补丁使用 Perl 管道 open 的列表形式,把程序名和参数逐项传入。Perl 文档明确区分了这种形式与命令字符串:列表中的值作为参数传给子进程,shell 不负责重新拆解它们。即使某个参数带有 shell 的语法字符,它也只是一项参数的内容。
使用 open 时,仍要分清命令字符串和分离参数这两种形式。前者也能让 shell 解释一整条命令,补丁使用的列表形式让参数保持分开。下面是独立的接口示意,不是设备脚本原文:
open(my $results, '-|', 'find', $core_directory,
'-type', 'f', '-name', $validated_name)
or die "cannot start file search";
公开差异还把原来的文件名前缀匹配,收窄为候选名称本身或对应的 .gz 文件,并检查返回路径的全部字符。路径需要满足 \A[A-Za-z0-9\/\-.]+\z:开头和结尾锚点约束整个值。研究者指出,后面仍有旧的反引号调用会使用这个路径,因此返回值检查也有实际作用。这里能核对的是公开展示的这些修改;完整脚本的其他分支没有进入本次审查范围。
从这个修复可以提出一个明确的代码审查问题:某段文字每次被拿去作新用途时,程序究竟传递了一个值,还是重新拼出一段语言?日志、队列、数据库里的内容都可能保留原始请求者的控制。存放位置变成了内部文件,并没有改变文字最初由谁提供。把字段格式限制与分离参数一起看,才能理解补丁为何同时动了两处。
4 这次升级还要留意业务变化
修复最终要落实到运行固件。下表把公告中的首次安全修复与 9 月 29 日厂商下载页实际提供的目标放在一起;同一行的目标只适用于相应产品分支,FIPS 与普通固件不能互换。旧的已停止维护分支不因缺席此表而获得安全结论,应迁入厂商支持的修复分支。
| 分支 | 首次修复 | 本次部署目标 |
|---|---|---|
| ADC / Gateway 14.1 | 14.1-73.37 | 14.1-73.37 |
| ADC / Gateway 13.1 | 13.1-64.23 | 13.1-64.24 |
| ADC 14.1 FIPS | 14.1-73.37 FIPS | 14.1-73.37 FIPS |
| ADC 13.1 FIPS / NDcPP | 13.1-37.279 | 13.1-37.279 |
厂商补充说明解释了 13.1 的差别:64.23 在配置了变量的设备上,升级时可能进入循环重启;64.24 用于避开这个已知运行问题。可以用只读命令 show ns variable 确认是否存在变量配置。返回为空,只能排除这一个重启前提,不能据此判断设备没有安全漏洞。既然当前下载已经提供 64.24,新安排的普通 13.1 升级采用它更直接。
已经装上 64.23 的管理员还可能遇到另一个困惑:Console 仍显示漏洞。厂商说明,Security Advisory 的扫描逻辑一度会把这个修复版本误标为受影响,需要等待该逻辑更新;它与配置变量导致的重启是两个问题。应核对实际固件、变量配置和检测逻辑更新时间,分别处理,不能只凭一次红色提示就退回旧固件。
使用 SAML 的环境还要检查身份提供方。厂商说明,新版本要求签署并校验 assertion,原有 samlRejectUnsignedAssertion OFF 会在升级时转换到安全默认行为。依赖未签名 assertion 的连接可能因此无法继续登录。上线前应验证 IdP 确实签署 assertion,并用真实业务的正常登录路径检查兼容性。这个变化可能解释一次升级后的认证失败,却不构成继续开放未修网关的理由。
同一公告中的 88778 还有额外配置动作:相关 TCP 部署需要启用 Enhanced ISN Generation。官方命令文档说明它作用于 NetScaler 作为服务器建立的 TCP 连接;公告要求核对并修改该设置。只安装固件不能替代这项检查。其余漏洞按公告里的 HTTP、Gateway/AAA、Oracle 负载均衡和非 HTTP L7 等条件核对即可,无需为了检查它们而启用原本不用的服务。
升级失败时,维持隔离并恢复受支持的已修复方案。回到 14.1-73.37、普通 13.1-64.23 或对应 FIPS 首修版本以下,会重新越过本次安全修复边界;普通 13.1 的业务回退还要避开上述变量重启问题。备用节点、快照和恢复镜像也要一起核对,防止故障切换把旧代码重新送回入口。
用数据库辅助盘点时,还会遇到一处版本差异。截至 2026-09-29 01:16 UTC,NVD 的 CPE 匹配项把 14.1-73.37 FIPS 列作包含式上界,和厂商公告、CNA 记录的修复边界不一致。本表采用厂商当前包表与下载入口;这个自动匹配项仍需纠正,不能用它断言修复包仍受该漏洞影响。同一记录里,CNA 的 9.5 使用 CVSS 4.0,NVD 在 9 月 28 日新增的 NIST 9.8 使用 CVSS 3.1;两者的提供者和评分版本也应保留在资产记录中。
5 保存能回答“之前发生过什么”的材料
补丁处理新的执行路径,入侵排查处理更新以前发生的事。CISA 的本次警报提醒,在条件允许时先检查入侵迹象;疑似受侵设备应在更新前保留取证材料,因为升级可能让部分线索消失。这也决定了操作顺序:先控制暴露,再让证据保全与恢复服务各有明确负责人,避免一边升级、一边才决定要留下什么。
对 VPX,Citrix 的受侵处置指南建议保留实例快照,并记录系统时间、时区和 NTP 配置;本地日志之外,还要保留远程 syslog 与 Console 记录。硬件设备需要按事件响应流程保存内存及磁盘。尤其注意,厂商的 Packet Engine core 采集会触发 warm restart,并断开 SSH。它不是一条毫无业务影响的“导出日志”命令,应和现场负责人一起决定执行时点。
NetScaler Console 可以辅助检查。IoC 功能文档区分潜在受侵、未检测到、跳过、执行失败和进行中。只有确实完成了对应逻辑的扫描,才谈得上解释结果。厂商本次说明列出的条件包括 Console 14.1-73.36 起、服务版或启用 Cloud Connect 的本地版、开启遥测、接受相关条款,并由用户手动启动;还要记录所用逻辑的更新时间。不用 Console 的客户可向 Citrix Support 索取适用的通用 IoC。
“未检测到”描述的是这一次检查。厂商明确说明,IoC 不能覆盖全部手法,也可能漏掉实际入侵。我们建议把检测结果与日志保存范围、异常进程或文件、设备对认证系统的访问放在一起看。普通 pitboss 故障文本本身可能合法;单独出现一个关键词不能直接给设备定性。相反,日志缺失或任务执行失败也不能被记成一次干净检查。
若已怀疑设备受侵,恢复工作会比更新固件更大。Citrix 指南要求隔离设备,调查它连接过的系统,处理存储在其上的服务账号、密钥及相关用户凭据,并撤销受影响的证书和私钥。VPX 建议替换重建,使用早于入侵且核对过的配置备份恢复;恢复后还要轮换本地密码、KEK 和带回来的证书材料。一个备份能启动服务,不代表其中保存的秘密仍然可信。
恢复入口前,可以用四类实际结果核对工作是否完成:
- 每个会接收业务的实例运行了对应分支的修复构建,备用节点和故障切换后的节点同样如此。
- 正常登录、SAML assertion 签名、实际应用流量和 HA 切换经过验证;与同批漏洞相关的配置动作已经执行。
- 更新前的日志与必要现场已经保存,IoC 检查的版本、结果及未检查范围有记录;异常有具体调查结论。
- 疑似受侵设备的重建、关联系统调查和凭据更换已经落实,恢复使用的配置经过检查。
这些是按本次机制与官方处置说明提出的验收建议,SOSEC 没有在生产 NetScaler 上执行这组操作。若其中一项仍无答案,继续保留相应隔离和调查措施;不要让“固件更新成功”替其他工作作结论。
6 日志保留了输入,也保留了输入者的影响
这起漏洞最值得带回日常开发的地方,是那个离请求很远的维护动作。网关可以拒绝一次登录,同时把请求者的文字留给另一个高权限程序。后者读取内部文件时,仍须按文字的来源和接下来的用途处理它。排查自动报表、故障收集和后台脚本时,沿着一个外部字段跟到最后一次使用,往往比只盯着登录是否成功更能发现问题。这次补丁把其中一段重新变成了受约束的文件名;运营者接下来的工作,是让所有入口都真正运行这段修复,并查清旧路径曾经做过什么。
7 参考资料
- Citrix CTX697096:八项漏洞、前提与修复范围
- Citrix 补充说明:13.1 运行问题、SAML 与 IoC
- NetScaler 当前固件下载
- watchTowr:14.1-73.30 与 14.1-73.37 的公开脚本比较
- Perl:管道 open 的命令与列表形式
- CISA:2026 年 9 月 27 日 NetScaler 警报
- ASD ACSC:9 月 28 日利用活动与修复建议
- Citrix:疑似设备受侵后的保存、重建与凭据处理
- NetScaler Console:IoC 检查状态与局限
- NetScaler:Enhanced ISN Generation
- CVE-2026-88771 CNA 记录;NVD 分析及变更历史;CISA KEV
研究依据
研究依据核对厂商公告、实际下载版本、CNA、NVD 及变更历史、KEV 和官方处置文档;依据研究者公开的 14.1-73.30 与 14.1-73.37 脚本差异解释机制。未取得完整固件、未独立复现设备漏洞,未向外部设备发送测试请求。官方状态核对截至 2026-09-29 01:16 UTC。
来源Citrix、CISA、ASD ACSC、Perl 文档与 watchTowr 公开补丁分析
证据置信度 高