
ثغرة حرجة في تنفيذ التعليمات البرمجية عن بُعد في محرك القواعد الخاص بـ OpenRemote تسمح للمستخدمين المصادق عليهم بدور `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 | CVE-2026-39842 |
| معرف GHSA | 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 |
| مستوى تنفيذ RCE | الجذر (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 لتقييم تعبيرات القواعد المقدمة من المستخدم دون أي عزل (sandboxing) أو مدير أمان أو قيود ClassFilter. وهذا يسمح للمهاجمين بالوصول إلى فئات Java مباشرة من سياق JavaScript.
**العيب 2: تعطيل عزل Groovy**
كان محرك سكربتات Groovy يحتوي على مرشح GroovyDenyAllFilter مسجل لمنع تنفيذ التعليمات البرمجية، ولكن تم تعطيل تسجيل هذا المرشح في قاعدة التعليمات البرمجية. كان هناك فقط تطبيق لقيود Groovy على مستوى واجهة API (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 (محظورة)
- لا توجد بيئة عزل (sandboxing) لجافاسكريبت، لذا يمكن استغلال الثغرة من قبل أي مستخدم مصادق عليه يمتلك صلاحية write:rules
بالإضافة إلى ذلك، يمكن تجاوز العزل متعدد المستأجرين عبر الانعكاس (reflection) على 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