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, 任意文件写入, 内存分配, 工控安全, 未授权访问, 漏洞验证, 目录穿越, 红队武器, 编程工具, 网络安全, 路径遍历, 远程代码执行, 隐私保护