Hann1bl3L3ct3r/FUXAPWN

GitHub: Hann1bl3L3ct3r/FUXAPWN

针对 FUXA SCADA/HMI 平台未授权路径遍历漏洞(CVE-2026-25895)的多模式 PoC 利用工具,实现从侦察到远程代码执行的完整攻击链。

Stars: 0 | Forks: 0

# CVE-2026-25895 — FUXA <= 1.2.9 未授权路径遍历致远程代码执行 针对 FUXA(一个基于 Node.js 的 SCADA/HMI 平台)的未授权、预认证任意文件写入漏洞。该漏洞可通过多种不同的写入后利用方式链式触发远程代码执行。即使 `secureEnabled = true`(开启了身份验证),该漏洞依然可以利用,因为易受攻击的端点没有附加任何中间件。 | 字段 | 值 | | -------------- | ----------------------------------------------- | | CVE ID | CVE-2026-25895 | | 受影响版本 | FUXA `<= 1.2.9` | | 已修复 | FUXA `1.2.10` | | 供应商 | frangoteam / FUXA | | 攻击向量 | 网络 (HTTP/HTTPS) | | 身份验证 | 不需要 | | 影响 | 任意文件写入,远程代码执行 | | CVSS v3.1 | 9.8 (严重) — AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H | | 研究员 | Anthony Cihan (`Hann1bl3L3ct3r`) | ## 概述 FUXA 的 `POST /api/upload` 端点(`server/api/projects/index.js:193`)在注册时未附加中间件,从而绕过了应用于其他所有项目管理端点的 `secureFnc` JWT / API 密钥检查及管理员权限校验。在处理程序中,JSON body 中的 `destination` 字段仅被添加了下划线前缀就直接拼接到文件系统路径中,期间没有进行任何规范化或限制检查: ``` let destinationDir = path.resolve(runtime.settings.appDir, `_${destination}`); filePath = path.join(destinationDir, fullPath || fileName); fs.writeFileSync(filePath, basedata, encoding); ``` 如果 `destination` 的值形如 `a/../../../../../etc`(其中 `a` 用于消耗掉前缀的下划线),Node 的 `path.resolve` 就会跳出 `appDir` 并指向 FUXA 进程拥有写入权限的任何位置。由于在 `fs.writeFileSync` 之前有条件地执行了 `fs.mkdirSync(dir, { recursive: true })`,攻击者还可以根据需要创建父目录。 最终的结果是,在默认的 HTTP 端口(`1881`)上实现了一个未经身份验证的任意文件写入原语,无论 FUXA 管理员是否启用了登录功能,都可以在预认证阶段被利用。 ## 影响 未经身份验证的远程攻击者可以: - 写入或覆盖 FUXA 服务账户所能访问的任何文件 - 替换 `settings.js` 以在下一次 FUXA 重启时实现代码执行 - 投递 cron 任务(`/etc/cron.d/`),当 FUXA 以 `root` 身份运行时(供应商 Docker 镜像中的默认设置),可在 60 秒内实现代码执行 - 安装绑定在 FUXA Node 进程内的 HTTP webshell 监听器 - 投递 SSH 公钥到 `/root/.ssh/authorized_keys` 或任何用户的 `~/.ssh/authorized_keys` 中 - 通过文件系统级别的侧信道,枚举运行 FUXA 的本地用户账户及主机上的其他账户 这是一个针对用于操作工业过程的 ICS/SCADA 平台的预认证严重级别发现。 ## 受影响版本 | 版本 | 状态 | | ---------- | -------------- | | `<= 1.2.9` | 易受攻击 | | `1.2.10+` | 已修复 | 已确认在 Ubuntu Server 上全新安装的 FUXA 1.2.9 版本中可成功利用。 ## 概念验证 单文件 Python 3 脚本,包含一个第三方依赖(`requests`)。 ``` pip install requests python3 fuxapwn.py --help ``` ### 快速未授权侦察 无需写入任何异常内容,即可识别正在运行的 OS 用户、Node-RED 暴露情况以及主机上的任何其他账户: ``` python3 fuxapwn.py -u http://target:1881 --mode recon \ --probe-root --probe-home ``` ### 验证写入原语 写入一个中性的 `/tmp/healthcheck` 标记文件(文件名或内容中没有针对该 CVE 的特定 IOC 特征): ``` python3 fuxapwn.py -u http://target:1881 --mode canary ``` ### 一次性 RCE 如果 FUXA 以 `root` 身份运行,投递一个将在 60 秒内触发的 cron 文件,且无需重启 FUXA: ``` python3 fuxapwn.py -u http://target:1881 --mode cron \ --cron-cmd 'id > /tmp/fx.txt 2>&1' ``` ### 通过替换 `settings.js` 实现持久化 webshell 在 FUXA Node 进程内安装一个 HTTP webshell 监听器(由于 `require()` 会缓存模块,因此会在下次冷启动时激活),然后在 FUXA 重启后进入一个交互式 REPL: ``` # 放置 payload — 替换 settings.js 但保留目标的 # 真实配置 (uiPort, allowedOrigins, secureEnabled 等) 以便让 # 应用程序继续正常运行。 python3 fuxapwn.py -u http://target:1881 --mode webshell \ --appdata /opt/FUXA/server/_appdata --ws-port 31337 # 一旦 FUXA 重启,连接到已安装的 webshell。 python3 fuxapwn.py -u http://target:1881 --mode webshell-exec \ --ws-host target --ws-port 31337 \ --ws-path /_abc123 --ws-token --interact ``` ## 操作模式 | 模式 | 用途 | | --------------- | ------------------------------------------------------------- | | `recon` | 通过 `GET /api/settings` 进行未授权信息泄露;从绝对路径推断运行中的 OS 用户;报告 Node-RED 状态;支持可选的 `--probe-root` 和 `--probe-home` 主动探测 | | `canary` | 使用中性的默认路径验证文件写入原语 | | `settings-rce` | 用一个在下次 FUXA 冷启动时运行可配置命令的 payload 替换 `settings.js` | | `ssh-key` | 将公钥写入目标用户的 `authorized_keys` | | `drop` | 将任意文件投递到任何绝对路径 | | `cron` | 投递 `/etc/cron.d/`,无需等待 FUXA 重启即可在 60 秒内实现 RCE(需要 FUXA 以 `root` 身份运行) | | `webshell` | 通过替换 `settings.js` 在 FUXA Node 进程内安装 HTTP webshell 监听器(在下次冷启动时激活) | | `webshell-exec` | 已安装 webshell 的客户端;支持单条命令或 `--interact` REPL | 各模式的完整标志参考:`python3 fuxapwn.py --help`。 ## 技术说明 ### 未授权配置泄露 `GET /api/settings`(`server/api/index.js:103`)在注册时没有附加中间件,并返回实时的运行时配置(仅进行了轻度删节,服务器在发送前删除了 `secretCode` 和 `smtp.password`)。其余字段泄露了绝对路径(`appDir`、`workDir`、`userSettingsFile`、`logsDir`、`uploadFileDir`),这些路径通常会暴露服务用户,以及 `nodeRedEnabled` 状态,这是第二条未授权 RCE 攻击路径的直接特征(见下文)。 ### 在非 root、非 Docker 安装环境下的运行用户枚举 当 FUXA 由本地用户账户通过 `npm start` 启动,且安装路径不包含用户名(例如安装在 `/opt`、`/tmp` 或通用的 `/app` 下),且 `/root/` 不可写时,POC 会退而求其次,通过对 `/home//` 执行零字节写入进行迭代探测。 FUXA 的上传处理程序会在 `fs.writeFileSync` 之前有条件地调用 `fs.mkdirSync(parent, { recursive: true })`,这会产生一个 EACCES 歧义:一个不存在的 `/home//` 会在 `mkdir` 尝试时失败并返回 `EACCES`(进程无法在 root 拥有的 `/home/` 下创建目录),而一个存在且模式为 `0700` 的 `/home//` 则会在写入本身时失败并返回 `EACCES`。相同的 errno,不同的含义。POC 通过解析由服务器转发的 `err.message`(libuv 格式 `": , ''"`)中的 syscall token 来消除这种歧义,并且仅将 `EACCES`-on-open(或任何非 `mkdir` 的 syscall)报告为“其他用户存在”。这消除了仅进行简单 errno 探测可能产生的误报横向移动列表。 ### Node-RED 辅助 RCE 路径 如果泄露的设置中 `nodeRedEnabled = true`,FUXA 嵌入的 Node-RED 管理 API 端点(`/nodered/flows/deploy` 等)将可以在未经身份验证的情况下访问,这是由于一个 Referer 头白名单检查(`node-red/index.js:134-136`)会接受任何 `Referer` 包含 `/editor`、`/viewer` 或 `/lab` 的请求。这实现了无需重启即可达成的即时未授权 RCE(通过 function 节点)。`recon` 模式会标记出此情况;操作员在可用时应优先使用此路径。 ### `settings.js` payload 会保留目标配置 在生成 `settings.js` 替换文件(模式 `settings-rce` 和 `webshell`)时,POC 首先通过 `/api/settings` 获取实时配置,并将其 JSON 序列化为 `module.exports` 的主体(JSON 是合法的 JavaScript 对象字面子集)。这保留了目标的 `uiPort`、`allowedOrigins`、`secureEnabled` 和其他运行时设置,以便应用程序在替换后能继续正常提供服务。当目标开启了 `secureEnabled = true` 或包含 `smtp` 块时,POC 会发出明确的警告,因为服务器端的删节会移除 `secretCode`(JWT 回退机制将会启动)和 `smtp.password`(电子邮件将失效,直到手动恢复)。 ## 检测 / 指标 - HTTP 访问日志条目:来自未经身份验证来源的 `POST /api/upload`,特别是响应中的 `destination` 值包含 `..` 或绝对文件系统路径 - 来自未经身份验证来源的 `GET /api/settings`(通常仅供已通过身份验证的 UI 使用) - 与 `/tmp/healthcheck*`、`/tmp/.fuxa-probe-*` 或 `/home/*/.fuxa-probe-*` 匹配的文件(默认的 Canary 和探测标记文件名——POC 允许覆盖这些名称以避免暴露明显的 IOC,因此这些文件的缺失不能排除被利用的可能性) - `settings.js`、`/etc/cron.d/*` 或 `~/.ssh/authorized_keys` 上不对应管理员操作的修改时间戳 - FUXA 主机上绑定到意外端口的新监听器(webshell 模式会在 Node 进程内绑定一个可配置的端口) ## 缓解措施 - **升级到 FUXA 1.2.10 或更高版本。** 在已修复的版本中,`/api/upload` 端点受到了标准中间件链的保护。 - 对 FUXA 管理接口进行网络分段。ICS/SCADA HMI 不应能从不受信任的网络被访问到。 - 如果无法立即升级,请在 FUXA 前部署反向代理,以拦截对 `/api/upload` 和 `/api/settings` 的未授权请求。 - 使用专用的低权限服务账户运行 FUXA。这不能防止被利用,但可以显著降低爆炸半径(无法写入 `/root/`,无法写入 `/etc/cron.d/`,无法通过 cron 实现全主机持久化)。 - 如果不主动使用 Node-RED,请将其禁用(`nodeRedEnabled = false`)。 ## 参考 - NVD: - 供应商: - 补丁: FUXA 发布版本 `1.2.10` - 易受攻击源码: FUXA `1.2.9` 中的 `server/api/projects/index.js:193` ## 贡献者 研究、PoC 和文章由 **Anthony Cihan**(`Hann1bl3L3ct3r`), Offensive Security 负责人完成。 ## 授权与法律 本仓库包含针对 ICS/SCADA 产品中严重漏洞的功能性漏洞利用代码。出于负责人的披露原则,在供应商发布补丁后予以发布,旨在造福防御者(检测规则作者、应急响应人员)和获得授权的安全测试人员。 **请仅针对您拥有或已获得明确书面测试授权的系统使用。** 在大多数司法管辖区,未经授权针对第三方系统使用本代码是非法的,作者将对此类行为严肃对待。作者对滥用行为不承担任何责任。 如果您是 FUXA 操作员,并希望在受控条件下获取有关针对此 PoC 验证补丁级别的帮助,请联系作者。 ## 许可证 发布用于授权的安全测试和防御性研究目的。有关完整条款,请参见 `LICENSE`。
标签:0day, CISA项目, CVE-2026-25895, CVSS 9.8, Express中间件, FUXA, GNU通用公共许可证, HMI系统, IT/OT融合, Maven, Node.js, PKINIT, POC, RCE, SCADA安全, writeFileSync, 任意文件写入, 内存分配, 工控安全, 未授权访问, 漏洞验证, 目录穿越, 红队武器, 编程工具, 网络安全, 路径遍历, 远程代码执行, 隐私保护