
إعادة إنتاج شاملة وكشف متعدد الطبقات لـ CVE-2026-53576، ثغرة تنفيذ الأوامر عن بُعد (RCE) دون مصادقة في Kestra — تم تجاوز إثبات المفهوم الأساسي لإظهار كيف يحوّل خطأ شائع في إعداد Docker socket صلاحيات جذر الحاوية إلى اختراق كامل للمضيف.
أطلقت Kestra، وهي منصة مفتوحة المصدر لتنسيق سير العمل، مرشّح مصادقة يقرر ما إذا كان الطلب يحتاج إلى بيانات اعتماد من خلال التحقق مما إذا كان عنوان URL ينتهي بـ /configs - وهو فحص يهدف إلى إتاحة نقطة نهاية عامة واحدة غير ضارة.
ولأن الفحص كان ينظر فقط إلى نهاية السلسلة النصية، فإن أي طلب يصادف أن ينتهي عنوان URL الخاص به بهذه الطريقة كان يتخطى المصادقة بالكامل، بما في ذلك نقاط النهاية التي تُنشئ وتُشغّل تعليمات برمجية عشوائية. النتيجة: أي شخص يستطيع الوصول إلى نسخة Kestra المصابة عبر الشبكة يمكنه تشغيل أوامر بصلاحيات الجذر دون أي بيانات اعتماد، ودون تصيّد احتيالي، ودون تخمين كلمات المرور، ودون الحاجة إلى خطوة تصعيد صلاحيات.
في هذا التمرين، تم تنفيذ هذه الثغرة الواحدة من البداية إلى النهاية ضد نسخة مختبرية مستضافة ذاتيًا:
تم التقاط كل مرحلة مقابل بيانات القياس الدفاعية (نظام كشف التسلل الشبكي، وأمن وقت تشغيل المضيف، وتدقيق Linux، وسجلات النظام).
الأثر على الأعمال في حال عدم الترقيع: اختراق كامل للمضيف الذي يعمل عليه Kestra، وليس التطبيق فقط - وبالتالي أي شيء آخر يمكن الوصول إليه من ذلك المضيف.
الإصلاح: الترقية إلى Kestra 1.0.45 / 1.3.21 أو أحدث (الترقيع وحده يُغلق الثغرة الأساسية؛ أما مرحلتا التصعيد والاستمرارية فتتطلبان إصلاحًا منفصلًا ومستقلًا - لا تقم بتركيب مقبس Docker داخل حاويات التطبيقات، انظر القسم 8).
يوثّق هذا التقرير CVE-2026-53576، وهي ثغرة تنفيذ تعليمات برمجية عن بُعد دون مصادقة بتقييم CVSS 10.0 في Kestra ≤1.3.20، ناتجة عن تجاوز مصادقة بلاحقة المسار (AuthenticationFilter.java، endsWith("/configs")).
يمكن للمهاجم الذي يسمّي مساحة الأسماء (namespace) ومعرّف سير العمل configs أن يُنشئ ويُنفّذ أوامر shell عشوائية دون أي بيانات اعتماد، وبصلاحيات الجذر، داخل حاوية Kestra. تم إصلاحها في 1.0.45 و1.3.21. كما تم الإبلاغ عن الخلل نفسه بشكل مستقل تحت CVE-2026-49869، وهو الرقم المُدرج في كتالوج CISA KEV والمرتبط باستغلال فعلي في البرية. ينبغي الاستشهاد بالرقمين معًا، لأن المصادر العامة وأدوات الفحص قد تشير إلى أيٍّ منهما.
| المتأثرة | Kestra ≤ 1.3.20 (وما قبل 1.0.45 على خط 1.0.x) |
| المُصلَّحة | 1.0.45 / 1.3.21+ |
| CVE | CVE-2026-53576 |
| الإشعار التوأم | CVE-2026-49869 - الخلل نفسه، مُدرج في CISA KEV (في البرية) |
| التاريخ | الحدث |
|---|---|
| 2026-06-02 | إصدار Kestra 1.3.21؛ ويشير سجل التغييرات إلى "تجاوز مصادقة محتمل في مرشّح المصادقة" |
| 2026-06-03 | إصدار Kestra 1.0.45 على خط 1.0.x |
| 2026-09-02 | إضافة CVE-2026-49869 (الإشعار التوأم) إلى كتالوج CISA KEV |
| 2026-09-22 إلى 09-24 | إعادة إنتاج هذا المختبر، وبناء الكشف، والتحقق عبر الطبقات |
مختبر منزلي مستضاف ذاتيًا:
- مضيف Debian (اسم المضيف docker، النواة 6.12.107+deb13-amd64)،
- Docker Engine 29.8.1.
- Kestra منشور كصورة رسمية kestra/kestra:v1.3.20، يمكن الوصول إليه عبر وكيل عكسي Caddy على kestra.int.atlasvec.com.
- حزمة القياس تحت الاختبار: Falco (وقت التشغيل/eBPF، على مستوى المضيف)،
- Suricata 8.0.3 IDS (مرآة SPAN سلبية)، تُمرّر نحو Splunk.
قبل المساس بأي شيء، تأكدت من أن الهدف مصاب فعليًا وأن حزمة القياس تعمل. كما أخذت لقطة للحالة قبل الهجوم حتى أتمكن من التراجع عند الانتهاء.
Kestra يعمل بالإصدار المصاب:

الحاوية نفسها، تعمل ويمكن الوصول إليها:

وحدات Falco محمّلة على المضيف:

Falco يُصدر أحداثًا بنشاط (وضع eBPF الحديث):

خدمة Suricata نشطة:

وeve.json الخاص بها يكتب أحداثًا حية:

هذان خطآن يتصادفان معًا، وليس خطأً واحدًا.
أولًا، يقرر مرشّح المصادقة ما إذا كان الطلب يمكنه تخطي المصادقة من خلال مطابقة نهاية مسار الطلب:```java // AuthenticationFilter.java — the vulnerable check, confirmed against the self-hosted v1.3.20 source if (path.endsWith("/configs")) { // treated as a public, unauthenticated path }
هذا الفحص موجود لكشف نقطة نهاية واحدة غير ضارة، وهي إعدادات المثيل العام. ولأن `endsWith` يقرأ فقط نهاية السلسلة، فإنه لا يستطيع التمييز بين مسار آمن واحد وأي مسار آخر ينتهي بالطريقة نفسها.
ثانيًا، لا يزال موجّه Kestra يوجّه تلك المسارات المتشابهة إلى معالجاتها الحقيقية الحساسة. يصل `/api/v1/main/flows/configs` إلى معالج إنشاء التدفق. ويصل `/api/v1/main/executions/configs/configs` إلى معالج التنفيذ. يمرّر الفلتر كليهما كمسارات عامة، وينفّذهما الموجّه رغم ذلك. سمِّ مساحة الأسماء ومعرّف التدفق `configs`، وسينتهي مسار ينفّذ الكود بـ `/configs`، فيرث بذلك التمرير المجاني الخاص بالمسار العام.
يُظهر زوج الطلبات الملتقطة ذلك بوضوح. `GET /api/v1/main/flows/search` بدون بيانات اعتماد يعيد `401`. أما `POST /api/v1/main/flows/configs` مع ترويسة المصادقة الفارغة نفسها فيعيد `200` ويخزّن التدفق (انظر §5.1).
## 5. محاكاة الهجوم
> كل خطوة أدناه موثّقة بلقطة شاشة خاصة بها. كل ذلك يعمل داخل مختبر منزلي معزول خاص بي ضد نسخة Kestra مستضافة ذاتيًا خلف الوكيل العكسي.
### 5.1 المرحلة 1 - تجاوز المصادقة -> صلاحيات root داخل حاوية Kestra
**التحكم:** `GET /api/v1/main/flows/search` بدون بيانات اعتماد → `401 Unauthorized`.
يؤكد أن المصادقة مفروضة على مسار عادي.

_____
**الزرع:** إرسال `POST /api/v1/main/flows/configs` بدون ترويسة مصادقة. الجسم عبارة عن YAML لتدفق تكون فيه `namespace` و`flow id` كلاهما `configs`، ويحتوي على مهمة Commands تستخدم مشغّل المهام Process. يعيد الخادم `200 OK` ويخزّن التدفق. لاحقة `/configs` على مسار محمي في الأصل هي ما يفعّل التجاوز **(انظر القسم 4).**

**الاستماع والانتظار**: بدء مستمع بسيط باستخدام nc لأغراض الاختبار، حتى نلتقط الـ reverse shell.

**التحفيز / التنفيذ** `POST /api/v1/main/executions/configs/configs`، بدون ترويسة مصادقة → `200 OK`، وتم إنشاء تنفيذ جديد.

**BaaaaM:** لقد حصلنا على الـ shell، لكن تذكّر - نحن "معزولون"، `root` **لكن** داخل حاوية Kestra docker، لذا "لا يُفترض" أن نتمكن من الهروب من هنا. "**حسنًا، هذا ما ظننته**"

يُنفَّذ أمر المهمة كعملية فرعية مباشرة لعملية Kestra JVM، وهو ما تم تأكيده عبر شجرة العمليات على جانب المضيف، ويكتمل بنجاح وفقًا لسجل التنفيذ الخاص بـ Kestra.
**لوحة سجلات Kestra**

**شجرة عمليات Kestra**

**النتيجة:** تنفيذ كود عن بُعد دون مصادقة بصلاحيات root، داخل حاوية Kestra. هذا هو الدليل الكامل والمكتفي بذاته على **CVE-2026-53576**.
### 5.2 المرحلة 2 - التصعيد عبر مقبس Docker المكشوف (خاص بالمختبر المنزلي، وليس جزءًا من CVE نفسه)
من shell المرحلة 1، وُجد أن `/var/run/docker.sock` مُثبَّت داخل الحاوية - وهو نمط Docker-outside-of-Docker (DooD)، شائع عند تكوين مشغّل المهام `Docker` الخاص بـ Kestra، لأنه يحتاج إلى daemon للتواصل معه.
الوصول إلى ذلك المقبس بأي شكل يعادل صلاحيات **root** على المضيف: إذ تتيح واجهة Docker API للعميل تكوين عمليات ربط تعسفية لنظام ملفات المضيف ومساحات أسماء PID/الشبكة الخاصة بالمضيف للحاويات التي ينشئها، كما أن الـ daemon خلف المقبس يعمل أصلًا بصلاحيات root على المضيف.
هذا ليس استغلالًا لنواة النظام أو هروبًا من الحاوية - بل هو Docker API يفعل ما صُمم لفعله، لكنه وصل من مكان لم يكن ينبغي أن يكون قابلًا للوصول منه.
باستخدام المقبس، أنشأت حاوية شقيقة مع ربط نظام ملفات المضيف بالداخل ومساحات أسماء PID والشبكة الخاصة بالمضيف، ثم شغّلتها.
**ملاحظة:** ظهر أيضًا أثناء الاختبار متغيّر ثانٍ أكثر هدوءًا، رغم أنني لم أوثّقه بلقطة شاشة منفصلة. فبدلًا من إنشاء حاوية شقيقة جديدة دائمًا، يتيح لك الوصول نفسه إلى المقبس تشغيل `POST /containers/{id}/exec` ضد حاوية قيد التشغيل بالفعل، فلا يكون هناك حدث إنشاء حاوية على الإطلاق. على مضيف Docker هذا لديّ كل من Kestra وPortainer، ويمكنني استخدام أيٍّ منهما للهروب نفسه. وهذا مهم للكشف: أي قاعدة تركّز على إنشاء حاوية جديدة ذات صلاحيات مرتفعة تفوّت هذا المتغيّر.
تأكيد صلاحيات root والعثور على المقبس موجودًا هناك، غير مقيّد بأي قيد:

التحقق من أن Docker daemon قابل للوصول فعلًا عبر المقبس:

سرد الصور الموجودة محليًا بالفعل، حتى لا أحتاج إلى سحب أي شيء:

المحاولة الأولى: حاوية ذات صلاحيات مرتفعة مع ربط نظام ملفات المضيف بالداخل:

المحاولة الثانية، هذه المرة بإضافة مساحات أسماء PID والشبكة الخاصة بالمضيف:

المحاولة الثالثة، بالدخول عبر chroot إلى نظام ملفات المضيف المربوط مباشرة:

المستمع جاهز وينتظر على المنفذ الذي سيتصل به shell الهروب:

بدء الحاوية:

**صلاحيات root، لكن هذه المرة على المضيف، وليس الحاوية:**

إصدار النواة مطابق للمضيف الحقيقي، وليس لعرض معزول لحاوية:

الترقية إلى shell تفاعلي مناسب لبقية الجلسة:

### 5.3 المرحلة 3 - الاستمرارية، مؤكَّدة التنفيذ
من shell بصلاحيات root على المضيف أعددت آليتي استمرارية مستقلتين،
**أولًا**، مفتاح SSH. تحققت ممن لديه صلاحية الوصول بالفعل:

ثم فحصت إعدادات sshd نفسها بحثًا عن أي شيء قد يمنع مفتاحًا جديدًا:

أنشأت زوج مفاتيح على جهاز المهاجم:

تأكدت من أن sshd يستمع فعلًا:

أدرجت المفتاح العام في `authorized_keys` الخاص بـ root:

وسجّلت الدخول بالمفتاح الخاص المطابق:

**ملاحظة:** هذا وصول بصلاحيات root مستقل عن سلسلة RCE الأصلية. حتى لو تم ترقيع Kestra، يظل هذا المفتاح يعمل.
**ثانيًا**، منارة cron. أدرجت استدعاءً بصلاحيات root مضبوطًا للعمل على فاصل زمني، ثم اختبرت بمستمع جديد لمعرفة ما إذا كان يُنفَّذ فعلًا وفق الجدول:

**لقد نُفِّذ. موطئ قدم ثانٍ على المضيف، مستقل عن كل من RCE ومفتاح SSH.**
### 5.4 الجدول الزمني الموثّق لسلسلة القتل.
الجدول الزمني أدناه مختلف: فهو مُعاد بناؤه بالكامل من بيانات قياس عن بُعد مستقلة من جانب المدافع (IDS الشبكة + أمن وقت تشغيل المضيف)، مسحوبة ومُتحقَّق منها مباشرةً مقابل بيانات Splunk حقيقية.
**RCE الأساسي - الشبكة تكشف التسليم، والمضيف يؤكد التنفيذ، بفارق 103 ثوانٍ:**
| الوقت (EDT) | الطبقة | الحدث |
| ------------ | ------------------ | -------------------------------------------------------------------------------------------- |
| 02:46:09.778 | الشبكة (Suricata) | توقيع ET العام الخاص بهذه الثغرة بالتحديد يُنفَّذ |
| 02:47:52.277 | المضيف (Falco) | تأكيد reverse shell داخل حاوية Kestra، مع التقاط الأمر الدقيق ومعرّف الحاوية |
**التصعيد - الشبكة والمضيف كلاهما يدعم بشكل مستقل جزءًا مختلفًا من الحدث نفسه:**
| الوقت (EDT) | الطبقة | الحدث |
| ------------ | ------------------ | ---------------------------------------------------------------------------------------------------------------------------------- |
| 03:48:55.503 | المضيف (Falco) | Reverse shell من حاوية التصعيد |
| 03:51:57.360 | الشبكة (Suricata) | تدفق TCP **و** تنبيه قائم على المحتوى - رُصدت السلسلة الحرفية `uid=0(root)` تغادر المضيف بنص صريح عند تشغيل `id` |
## 6. هندسة الكشف
بنيت الكشوفات مقابل بيانات قياس عن بُعد حقيقية ملتقطة، ثم اختبرت كل واحد منها مقابل إعادة تشغيل. تُظهر المصفوفة أين كانت التغطية موجودة قبل أن أبدأ وأين لم تكن.
### 6.0 مصفوفة تغطية الكشف
| المرحلة | الشبكة (Suricata) | المضيف (Falco) | المضيف (auditd/journald) | الحالة |
| --- | --- | --- | --- | --- |
| طلب الاستغلال الأولي | توقيع ET العام يُنفَّذ | لا رؤية لطبقة التطبيق | - | مغطّى (موجود مسبقًا) |
| تنفيذ RCE | - | قاعدة أصلية، موسومة بـ T1059 | - | مغطّى (موجود مسبقًا) |
| تصعيد مقبس Docker (التقنية) | - | فجوة: يلتقط فقط الـ shell الناتج، وليس استدعاءات API لإساءة استخدام المقبس | سجلات EXECVE تلتقط استدعاءات `curl --unix-socket` الدقيقة | وُجدت فجوة، وأُغلقت بـ auditd + قاعدة Falco مخصصة |
| تأكيد أثر التصعيد | تنبيه محتوى على مخرجات `id` المسرّبة | قاعدة shell العامة نفسها | - | مغطّى (موجود مسبقًا، عبر الطبقات) |
| استمرارية SSH | - | - | journald: دورة حياة PAM كاملة بالإضافة إلى بصمة المفتاح | مغطّى (المضيف فقط) |
| استمرارية Cron | - | - | journald وlinux_audit، مصدران، بإيقاع 5 دقائق الدقيق | مغطّى (المضيف فقط) |
الفجوة هي تصعيد مقبس docker. تلتقط قواعد Falco الافتراضية الـ shell الذي تُنشئه حاوية مخترقة، لكن لا شيء في المجموعة الافتراضية المستقرة يعلّم على عملية تصل إلى `/var/run/docker.sock` لتحريك Docker API مباشرة. أما القواعد التي قد تلامس إطلاق حاويات ذات صلاحيات مرتفعة، `Launch Privileged Container` و`Launch Sensitive Mount Container`، فتُشحن بمستوى نضج `incubating` و`sandbox`، لذا لا تحمّلها المجموعة الافتراضية أيضًا. أغلقت الفجوة ببحث ارتباط auditd (الكشف 03) وقاعدة Falco مخصصة (§6.3).
### 6.1 Splunk - خمسة بحوث ارتباط، منشورة ومجدولة
جميعها الخمسة تعمل مباشرةً في Splunk (`*/5 * * * *`، مع تفعيل تتبّع التنبيهات، وتقييد لكل حقل)، وليست مجرد نص مكتوب ومتروك. الـ SPL الكامل، وملاحظات FP الدقيقة، والخطورة، ووسوم MITRE، وأدلة الاستجابة لكل منها موجودة في `detections/splunk/*.spl`. جدول الحالة أدناه هو النتيجة المُختبرة مباشرةً لكل منها، بما في ذلك خطأ حقيقي وجدته وأصلحته.
| # | الكشف | MITRE | الحالة |
| --- | ---------------------------------------------------------- | -------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| 01 | توقيع استغلال الشبكة (يستهلك تنبيه Suricata ET) | T1190 | **نُفِّذ** - تأكدت إعادة التشغيل التاريخية، ولا أحداث جديدة منذ ذلك الحين (خارج نطاق البحث الحالي) |
| 02 | تنفيذ RCE على المضيف (قاعدة Falco لإعادة التوجيه إلى الشبكة) | T1059 | **نُفِّذ** - تأكدت إعادة التشغيل التاريخية |
| 03 | إساءة استخدام مقبس Docker (auditd، سادّ الفجوة) | T1610, T1611 | **نُفِّذ على المجدول المباشر نفسه** - تأكد `triggered_alert_count: 1` في تشغيل `*/5 * * * *` الحقيقي، وليس مجرد اختبار يدوي |
| 04 | استمرارية تسجيل دخول root عبر SSH | T1098.004, T1021.004 | **نُفِّذ** - تأكدت إعادة التشغيل التاريخية |
| 05 | استمرارية منارة Cron | T1053.003 | **نُشر مع خطأ وجدته وأصلحته مباشرةً.** نافذة الإرسال `-10m` احتوت فقط على اثنتين من ثلاث فترات 5 دقائق التي تحتاجها عتبة `distinct_intervals >= 3`، لذا لم يكن بإمكانه التنفيذ أبدًا رغم استمرار عمل المنارة في البيانات الحقيقية. وسّعتها إلى `-30m` وأعدت النشر - وقد نفّذها المجدول 53 مرة منذ ذلك الحين، لذا يصمد الإصلاح. |
تقسيم العمل في الكشف 03 متعمّد: فبدلًا من إعادة تنفيذ منطق توقيع Suricata نفسه في SPL، أو محاولة جعل Falco يلتقط تقنية على مستوى المقبس لم يُبنَ لها، تستهلك طبقة SIEM هنا سجل EXECVE الخاص بـ auditd لاستدعاءات `curl --unix-socket` الدقيقة - مصدر القياس عن بُعد الذي ثبت أنه الأكثر موثوقية لهذه التقنية بالتحديد.
1. **الكشف 01** - تنفيذ توقيع ET (تنبيه `suricata:eve`):```spl
index=main sourcetype=suricata:eve event_type=alert
alert.signature="ET WEB_SPECIFIC_APPS Kestra Unauthenticated Remote Code Execution (CVE-2026-53576)"
| stats count min(_time) as first_seen max(_time) as last_seen
values(src_ip) as source_ips
by dest_ip dest_port
| eval first_seen=strftime(first_seen,"%Y-%m-%d %H:%M:%S")
| eval last_seen=strftime(last_seen,"%Y-%m-%d %H:%M:%S")

Detection 02 - قاعدة redirect-to-network الخاصة بـ Falco، مقسّمة لكل حاوية. ينتقل Source IP من عنوان الجسر الخاص بحاوية Kestra (172.17.0.3، RCE الأساسي على المنفذ 4489) إلى المضيف نفسه (172.66.66.67، التصعيد على المنفذ 4491) - التصعيد من الحاوية إلى المضيف أصبح مرئيًا - بينما تبقى الوجهة ثابتة: مستمع المهاجم على 172.66.66.125:

Detection 03 - سجلات EXECVE الخاصة بـ auditd للأمر curl --unix-socket docker.sock:

Detection 04 - تسجيل دخول root عبر SSH في journald، مع التقاط بصمة المفتاح:

Detection 05 - منارة cron المخفية في ملف نقطي (/usr/local/bin/.sysmon) تعمل بصلاحيات root بإيقاع دقيق كل 5 دقائق: 79 فترة زمنية مميزة على مدى ~6.5 ساعات (04:30-11:00 EDT). عتبة distinct_intervals >= 3 هي ما يفصل المنارة الدورية عن مهمة cron لمرة واحدة:

جميع الخمسة منشورة كعمليات بحث محفوظة مجدولة (*/5 * * * *):

دليل على أن مجدول cron يشغّل هذه فعليًا، وليس فقط أنها موجودة: جميع الخمسة نُفّذت 54 مرة. Detection 03 أطلقت مرة واحدة (إساءة استخدام docker-socket، 06:35 EDT) وDetection 05 أطلقت 53 مرة (منارة cron التي لا تزال نشطة). تُظهر Detections 01/02/04 صفر إطلاقات لأنها أحداث تاريخية لمرة واحدة (طلب الاستغلال، RCE، تسجيل دخول SSH) التي تجاوزت نافذة البحث -10m، بينما أي نسخة حية أو متكررة ستظل تُنبّه:

نمط القشرة العكسية /dev/tcp/ - المستخدم في كل من RCE الأساسي واستدعاء التصعيد. يوفّر SigmaHQ قاعدة له: "Suspicious Reverse Shell Command Line" (المعرّف 738d9bcf-6999-4fdb-b4ac-3033037db8ab، من إعداد Florian Roth في Nextron Systems)، وإحدى كلماتها المفتاحية هي bash -i >& /dev/tcp/ - وهو بالضبط ما ظهر في التسجيل لدينا.
لذا سحبت تلك القاعدة دون تغيير (detections/sigma/lnx_shell_susp_rev_shells.yml) وفحصت كلمتها المفتاحية مقابل نفس حدث Falco الذي التقطه Detection 02 بالفعل. Sigma لا "تُطلق" من تلقاء نفسها - فهي توقيع محمول، وليست محركًا قيد التشغيل - لكن يمكنني إظهار كلمتها المفتاحية وهي تصادف بيانات قياس عن بُعد حقيقية من هذه الجولة بدلًا من مثال نظري.
قاعدة SigmaHQ العامة "Suspicious Reverse Shell Command Line" - كلمتها المفتاحية bash -i >& /dev/tcp/ مقابل نفس الحدث الحقيقي الخاص بـ Detection 02:

detections/falco/docker_socket_abuse.yaml - منشورة على نسخة Falco الحية ومؤكَّد إطلاقها على إعادة تشغيل حقيقية، 2026-09-24T10:27:29Z.
مجموعة القواعد الافتراضية لـ Falco لا تغطي هذا. اكتشاف عملية تصل إلى /var/run/docker.sock ليس فكرة جديدة - أمثلة Falco الخاصة بـ Sysdig نفسها تفعل ذلك بمراقبة open_write على مسار المقبس - لكن لا توجد قاعدة كهذه في المجموعة المُشحونة/الافتراضية (المشروع لديه طلب مفتوح لواحدة، falcosecurity/falco #2940)، والقاعدة الافتراضية المجاورة الوحيدة تلتقط فقط واجهات سطر الأوامر docker/kubectl، وليس curl --unix-socket الخام.
المشكلة: نهج open_write-على-المقبس القياسي لم يُطلق في هذا الإعداد - مع modern_bpf ومرآة سلبية، يُوصَل إلى المقبس عبر connect()، وليس open(). لذا أطابق سطر أوامر العملية عند إنشائها بدلًا من ذلك (spawned_process + proc.cmdline contains "docker.sock")، وهي نفس فئة الأحداث التي يتعامل معها Falco بشكل موثوق هنا. تُطلق مرتين لكل استدعاء - غلاف الصدفة وورقة curl - مع سياق كامل:```
priority=Critical, container_id=d417e027d444, image=kestra/kestra:v1.3.20, user=root, cmdline="curl -s --unix-socket /var/run/docker.sock http://localhost/version", tags=[T1610, T1611]
قاعدة Falco المخصصة التي أُطلقت - "Unexpected Process Accessing Docker Socket" (T1610/T1611):

قواعد Falco الجاهزة التي أُطلقت - المجموعة الافتراضية لا تحتوي على قاعدة docker-socket، وهذه هي الفجوة:

### 6.4 Suricata - التغطية العامة الموجودة، وتأجيل القاعدة المخصصة
طبقة الشبكة الخاصة بالاستغلال الأساسي مغطاة بالفعل بتوقيع عام من Emerging Threats، وهو `ET WEB_SPECIFIC_APPS Kestra Unauthenticated Remote Code Execution (CVE-2026-53576)`، والذي أُطلق على حركة مرور حقيقية خلال المرحلة 2.
فيما يلي نفس التجاوز كما ظهر على طبقة الشبكة، وقد بنيت الاستعلام من نمط الثغرة. كل طلب ينتهي مساره بـ `/configs` على نقطة نهاية `flows` أو `executions` أعاد `200`، بينما أعاد مسار عادي (`/flows/search`) الاستجابة المتوقعة `401`.
عمود `Attacker IP (XFF)` هو أصل HTTP الحقيقي، مقروءًا من ترويسة `X-Forwarded-For`: `10.10.10.106`، وهو جهاز Mac الخاص بي الذي يشغّل Burp. أما `src_ip` الخاص بـ Suricata فلا يرى سوى قفزة الوكيل العكسي (`172.66.66.1`). وهذا جهاز مختلف عن صندوق Kali ذي العنوان `172.66.66.125` الذي التقط لاحقًا الأصداف العكسية ونفّذ تسجيل الدخول عبر SSH، لذا فإن استغلال HTTP والاستدعاءات العكسية جاءا من مضيفين منفصلين.

### 6.5 لوحة المعلومات
`cve_2026_53576_kill_chain` منشورة على Splunk وتحتوي على: مؤشرات الأداء الرئيسية (طبقات الكشف، تقنيات ATT&CK، الكشوفات المنشورة، آليات الاستمرارية)، ومخطط أعمدة للجدول الزمني للهجوم ملوّن حسب طبقة القياس عن بُعد، وخريطة سلسلة القتل MITRE ATT&CK مع عدد أدلة حيّ لكل مرحلة، والجدول الزمني المترابط بين الشبكة والمضيف من §5.4، وتغطية الكشف حسب البحث المحفوظ المجدول، وتفصيل تقنية docker-socket، وجدول مؤشرات الاختراق المسحوب مباشرة من السجلات.
- مؤشرات الأداء الرئيسية، ومخطط الجدول الزمني للهجوم، وبداية خريطة ATT&CK:

- بقية خريطة ATT&CK، وسلسلة القتل المترابطة، وتغطية الكشف بجانب تفصيل docker-socket، وجدول مؤشرات الاختراق:

## 7. تعيين ATT&CK
| التكتيك | التقنية | الدليل |
| -------------------- | --------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- |
| الوصول الأولي | T1190 - استغلال تطبيق مواجه للجمهور | طلبات Control/plant/execute (§5.1)؛ إطلاق توقيع Suricata ET، §5.4 |
| التنفيذ | T1059.004 - مُفسّر الأوامر والسكربتات: Unix Shell | مهمة `Commands` في Kestra، شجرة عمليات المضيف (`07-kestra-process-tree.png`)؛ قاعدة Falco، §6.1 الكشف 02 |
| القيادة والتحكم | T1095 - بروتوكول غير طبقة التطبيق | صدفة عكسية TCP خام عبر `/dev/tcp/` - لم يُستخدم أي تأطير C2 على طبقة التطبيق |
| الاستكشاف | T1613 - استكشاف الحاويات والموارد | تعداد صور Docker عبر المقبس (`10-docker-images-enum.png`) |
| تصعيد الصلاحيات | T1610 - نشر حاوية | إنشاء/تشغيل حاوية شقيقة عبر Docker API (`11`–`15`)؛ سجلات EXECVE من auditd، §6.1 الكشف 03 |
| تصعيد الصلاحيات | T1611 - الهروب إلى المضيف | تأكيد صلاحيات root على المضيف، تطابق اسم المضيف/النواة (`16`، `17`) |
| الاستمرارية | T1098.004 - التلاعب بالحسابات: مفاتيح SSH المصرّح بها | زرع مفتاح في `/root/.ssh/authorized_keys` (`23`) |
| الحركة الجانبية | T1021.004 - الخدمات عن بُعد: SSH | تسجيل دخول ناجح لـ root بالمفتاح (`24`)؛ journald، §6.1 الكشف 04 |
| الاستمرارية | T1053.003 - المهمة/الوظيفة المجدولة: Cron | منارة Cron، مؤكَّد إطلاقها وفق الجدول (`25`)؛ §6.1 الكشف 05 |
## 8. المعالجة والتحصين
**الإصلاح الأساسي.** الترقية إلى Kestra 1.0.45 (فرع 1.0.x) أو 1.3.21+ (فرع 1.3.x). هذا وحده يُغلق تجاوز المصادقة - المرحلة 1 من هذا التمرين - وهو
الإصلاح الوحيد الذي لا يتطلب ضوابط تعويضية إضافية بمجرد تطبيقه. راجع [GHSA-2q47-568g-9h4f](https://github.com/kestra-io/kestra/security/advisories/GHSA-2q47-568g-9h4f).
**إذا لم يكن الترقيع الفوري ممكنًا**، فالضوابط التعويضية، مرتبة حسب الأثر:
1. **الفرض عبر الوكيل العكسي** - بما أن الفلتر المصاب يفشل فقط عند لاحقة المسار الخام، فإن وكيلًا عكسيًا أمام Kestra (Caddy، في هذا المختبر) يمكنه فرض المصادقة بشكل مستقل على أي مسار يطابق `/api/v1/*/(flows|executions)/.*` بغض النظر عما ينتهي به، مما يُغلق التجاوز على طبقة لا يستطيع خطأ التطبيق الوصول إليها.
2. **تقييد تركيب مقبس Docker** - هذا يُغلق المرحلتين 2–3 بالكامل، بمعزل عن ترقيع Kestra. لا تقم بالتركيب الربطي (bind-mount) لـ `/var/run/docker.sock` داخل حاوية Kestra. إذا كان مشغّل مهام `Docker` مطلوبًا فعلاً، فاستخدم وكيل مقبس محدود النطاق (مثل `docker-socket-proxy`) يسمح بقائمة محددة من استدعاءات API بدلاً من منح وصول كامل للـ daemon - فالوصول الكامل إلى المقبس يعادل صلاحيات root على المضيف، كما هو موضّح في §5.2.
3. **تحصين SSH** - اعتمدت الآلية الأولى في سلسلة الاستمرارية على إمكانية الوصول إلى root عبر SSH بالمفتاح أصلاً. كان `PermitRootLogin no` (أو اشتراط نقطة عبور/MFA لـ root) سيمنع مسار الاستمرارية ذلك تحديدًا بغض النظر عن RCE الأولي - ويستحق التنفيذ بمعزل عن هذه الثغرة.
4. **تغطية الكشف المؤقتة** - عمليات الربط في Splunk وقاعدة Falco المخصصة، وكلها منشورة ومُتحقق منها خلال هذا التمرين، توفر التغطية المؤقتة لمراحل هذه السلسلة تحديدًا ريثما يُجدول الترقيع.
**نظافة ما بعد الحادث**، إذا وُجد أن هذا النمط قد استُغل بالفعل: تعامل معه كاختراق كامل للمضيف، وليس مجرد اختراق للتطبيق - قم بتدوير كل بيانات الاعتماد والأسرار التي كان لنُسخة Kestra وصول إليها (مدخلات مخزن KV، وبيانات اعتماد الاتصال بالأنظمة اللاحقة)، وليس فقط وصول Kestra نفسه.
**الحالة في البرية.** `CVE-2026-49869`، الإشعار التوأم لنفس هذا الخطأ، مُدرج في كتالوج KEV الخاص بـ CISA ومرتبط بحملات ملحوظة لتعدين العملات وسرقة بيانات اعتماد السحابة. أما `CVE-2026-53576` (هذا التقرير) فليس له إدراج KEV خاص به، لكنه نفس الثغرة. أدوات إدارة الثغرات التي تتعقب رقم CVE واحدًا فقط من الرقمين قد تُبلّغ بأقل من التعرض الفعلي.
## 9. المراجع
- إشعار أمان Kestra - [GHSA-2q47-568g-9h4f](https://github.com/kestra-io/kestra/security/advisories/GHSA-2q47-568g-9h4f) (CVE-2026-53576، المصدر الأساسي لهذا التقرير)
- الإشعار التوأم - [GHSA-5vc5-wxxq-3fjx](https://github.com/kestra-io/kestra/security/advisories/GHSA-5vc5-wxxq-3fjx) (CVE-2026-49869، خطأ مطابق، مُدرج في CISA KEV)
- CVE.org - [CVE-2026-53576](https://www.cve.org/CVERecord?id=CVE-2026-53576)، [CVE-2026-49869](https://www.cve.org/CVERecord?id=CVE-2026-49869)
- كتالوج الثغرات المستغلة المعروفة لدى CISA - https://www.cisa.gov/known-exploited-vulnerabilities-catalog (مدخل CVE-2026-49869، أُضيف في 2026-09-02)
- الإصدارات المُصلَحة، وكلاهما مؤكَّد الوجود وموسوم - [v1.3.21](https://github.com/kestra-io/kestra/releases/tag/v1.3.21) (2026-06-02، سجل التغييرات يشير صراحةً إلى "potential authentication bypass in the authentication filter")، [v1.0.45](https://github.com/kestra-io/kestra/releases/tag/v1.0.45) (2026-06-03)
- تقنية تصعيد مقبس Docker (§5.2) - [HackTricks: Docker Breakout / Privilege Escalation](https://hacktricks.wiki/en/linux-hardening/privilege-escalation/docker-security/docker-breakout-privilege-escalation/index.html)، [Trail of Bits: Understanding Docker Container Escapes](https://blog.trailofbits.com/2019/07/19/understanding-docker-container-escapes/)، [MindPatch: Docker Escape](https://www.mindpatch.net/posts/docker-escape/)
- قاعدة Sigma (§6.2) - القاعدة العامة التي استخدمتها بدلاً من كتابة قاعدتي الخاصة: [SigmaHQ "Suspicious Reverse Shell Command Line"](https://github.com/SigmaHQ/sigma/blob/master/rules/linux/builtin/lnx_shell_susp_rev_shells.yml) (المعرّف `738d9bcf-6999-4fdb-b4ac-3033037db8ab`، Florian Roth / Nextron Systems)، مستخدمة بموجب [Detection Rule License 1.1](https://github.com/SigmaHQ/sigma/blob/master/LICENSE.Detection.Rules.md)
- قاعدة Falco (§6.3) - فجوة docker-socket هي طلب مفتوح لدى المشروع الأصلي ([falcosecurity/falco #2940](https://github.com/falcosecurity/falco/issues/2940))؛ والقاعدة المخصصة تتبع النمط الموجود في [أمثلة Docker + Falco من Sysdig](https://www.sysdig.com/blog/docker-falco-security)