导语:Fortinet FortiSIEM 的 gRPC 查询服务被曝出路径遍历漏洞,未认证攻击者可以把文件写到任意目录,精确控制文件名后覆盖系统定时执行的脚本,60 秒内拿到 root。10 月 13 日官方发布公告,10 月 20 日 Horizon3.ai 公开完整技术分析与 PoC,10 月 25 日安全研究员 Nicolas Krassas 在 X 上再次把这把”钥匙”递到了大家面前。
漏洞速览
结论先摆桌上。Fortinet 在 10 月 13 日发布的公告 FG-IR-26-180 里,给这个漏洞的评级是 Critical,CVSS v3 得分 9.4,类型 CWE-22 路径穿越,攻击类型标注为 Unauthenticated。
受影响范围很窄:FortiSIEM 7.5.0 受影响,升级到 7.5.1 及以上即可修复;7.6 版本不受影响,FortiSIEM Cloud 也不受影响。官方给的临时缓解方案只有一条——限制对 tcp/27918 端口的访问。
漏洞链路是一套三连:路径没校验导致任意目录写入 + NUL 字节截断控制文件名 + 覆盖 cron 脚本升级为 RCE。
根因拆解:两个小问题叠成一条大动脉
出问题的服务叫 phQueryMaster,由 grpcNotificationServer::run() 起起来。配置项 command_port 默认 7918,经 phSecureUtils::getGrpcPort() 映射后实际监听 tcp/27918,绑定 [::]:27918(所有网卡)。更要命的是创建 SSL 凭据时 sslOps.client_certificate_request 保持为 0,不强制客户端证书——任何能连上该端口的人,不用账号密码就能和服务端对话。
暴露出来的 RPC 方法叫 SendQueryResult,流式接收 QueryResultReq{ bytes file_content = 1; }。服务端从元数据里取出 query-id、src-ip、period-start、period-end 拼成路径,再把流里推送的字节当文件内容写下去。
第一个 Bug 在目录拼接上:fileDir = "/query/result/" + queryId。queryId 完全没校验,一个 ../../../../../tmp/x 就能跳出查询根目录,攻击者由此拿到任意目录写入能力。
第二个 Bug 更隐蔽也更致命。服务端会自动追加 result----.dat 做文件名,id 是服务端自己的计数器,改不了——只看这点,攻击者只能写”文件名半可控”的文件。转折在于,服务端按客户端声明的长度逐字节拷贝元数据值,于是可以在 query-id 中间塞进 。路径交给操作系统的 C 接口打开时会在 NUL 处截断,服务端追加的后缀被整个丢掉,写入精确落在 NUL 之前的那条路径上。要新建指定名字的文件则需两次请求:先用目录穿越建临时目录,再把文件名塞进 period-end。
由于 curl 和常规 gRPC 库都不允许在 HTTP 头里塞 NUL 字节,公开 PoC 选择手工拼装 HTTP/2 帧与 HPACK 编码——字面量头部、不索引、不用 Huffman——再裹上 gRPC 信封和 protobuf 消息。
PoC 跑起来是什么样
下面是 Horizon3.ai 研究员 Zach Hanley 的实机截图,整个请求最终只有 333 字节:

几个关键数字:HEADERS 帧负载 230 字节,DATA 帧 52 字节,NUL 出现在 query-id 第 59 个字节偏移处,服务端拼出的完整路径表达式长度 73,最终归一化的写入目标就是 /opt/charting/redishb.sh。截图下半部分还接上了反向 shell,回连后拿到的身份是 uid=0(root)。
执行是”盲”的——脚本何时被 cron 拉起、命令有没有跑成功,攻击者拿不到回显,最多等约 60 秒。PoC 命令行形如 python3 CVE-2026-106173.py -t -c 'id',脚本会自动把命令包成 #!/bin/bashnn 覆盖进 redishb.sh。
公开 PoC 与下载
PoC 仓库已在 GitHub 公开:https://github.com/horizon3ai/CVE-2026-106173。

仓库只有两个文件:README.md 与 CVE-2026-106173.py(Python,约 11 KB)。仓库 10 月 20 日创建,未附开源许可证文件,仅有研究与防御用途声明;目前已积累 20 多个 star、9 次 fork,并被安全研究员 Nicolas Krassas 在 X 上转发(10 月 25 日,110 赞)。
脚本主要参数:-t 指定目标,-p 指定 gRPC 端口(默认 27918),-c 指定要执行的命令,--overwrite/--create 指定覆写或新建目标文件,--plaintext 走明文 HTTP/2,--dry-run 只构造请求不发送,预演时很实用。
再次提醒:这套东西是给有授权的靶场用的,README 里也写明仅供研究用途。拿它去碰生产环境的 SIEM 设备,请先拿授权书。
蓝队视角:怎么发现、怎么防
Horizon3 的研究团队明确表示,没有找到能直接暴露利用行为的应用日志。换句话说,被打了可能悄无声息。
排查线索主要是文件时间戳:重点检查 /opt/charting/redishb.sh 与 /opt/phoenix/bin/phLicenseTool 的写入/修改时间是否与周边文件明显不符;也可关注 /query/result/ 目录下是否出现本不该存在的目录结构。
加固优先级很清楚:先升级到 7.5.1 及以上;补丁窗口之前,用防火墙或安全组把 tcp/27918 限制在管理网段,确认不再对业务网段暴露;再查一下这台 SIEM 的 27918 端口是否对公网可达。
有个细节值得留意:官方公告只把 7.5.0 列为受影响版本,而研究者的演示环境是 7.3.4。盘点时若只按公告版本号过滤,可能漏掉处在风险中的老设备。
紫队视角:这条链真正教给我们什么
这条链上每一环都不算天才级漏洞,却拼成了一条从”未认证网络可达”到”root 权限”的完整通路。它给蓝队留了三个问题:
第一,管理类协议暴露给了谁。SIEM 的 gRPC 服务绑定所有网卡、不要求客户端证书,这组合本身就值得审一遍。
第二,输入校验不是一层的事。目录穿越之外,”按声明长度拷贝 + C 字符串语义”等于在应用层校验后又被开了扇门。
第三,执行链路才是最后的裁判。设备上只要存在高权限、周期执行、以 root 运行的本地脚本,就随时可能变成终点——资产画像里除了版本号,还该有一份”产品会执行哪些本地文件”的清单。
红队每一步都踩在蓝队某个默认假设的边界上,把这些假设翻出来,正是紫队的活。
版权声明:本文由华盟网原创发布,保留所有权利。文中漏洞信息引自 Fortinet 官方公告 FG-IR-26-180 与 Horizon3.ai 公开研究报告,配图由华盟网授权使用。














暂无评论内容