
CVE-2026-20251 — Splunk Secure Gateway jsonpickle deserialization RCE (CVSS 8.8) | ReactiveZero Security Research
الباحث: Fady Oueslati · ReactiveZero Security Research
المرجع: 2026FO-SPLUNK-20251
CVSS: 8.8 (CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H)
الحالة: مفتوحة — التصحيح متاح
يمكن لمستخدم مصادق عليه بصلاحيات منخفضة تحقيق تنفيذ تعليمات برمجية عن بعد على مضيف Splunk عن طريق تخزين مستند مصمم خبيثًا في مخزن KV (مجموعة mobile_alerts). لاحقًا، تقرأ Splunk Secure Gateway (SSG) هذا المستند وتمرره مباشرة إلى jsonpickle.decode()، مما يعيد بناء كائنات Python عشوائية — بما في ذلك تلك التي تنفذ أوامر نظام التشغيل.
تستدعي الدالة مع safe=True، ولكن هذا العلم يمنع فقط مسار التقييم القديم py/repr. أما العلامات py/reduce و و و و فهي غير متأثرة وقابلة للاستغلال بالكامل.
py/objectpy/typepy/functionpy/moduleيوجد مُحقق منفصل (check_alert_data_valid_json ) يهدف إلى حظر العلامات الخطيرة ولكنه يقصر الدائرة عند أول مفتاح معروف: أي مستند يكون أول مفتاح فيه من المستوى الأعلى هو py/object مسموحًا به (قيمته تبدأ بـ spacebridgeapp) يُرجع True فورًا، تاركًا المفاتيح المجاورة — بما في ذلك أداة py/reduce الخبيثة — دون فحص.
| الفرع | الإصدار المُصحح |
|---|---|
| Splunk Secure Gateway 3.9.x | 3.9.20 |
| Splunk Secure Gateway 3.10.x | 3.10.6 |
| Splunk Secure Gateway 3.8.x | 3.8.67 |
| Splunk Enterprise | 10.0.7 / 10.2.4 / 10.4.0+ |
المثيل المُختبر: SSG 3.9.19 على Splunk Enterprise 10.0.6 (macOS x86_64).
الخطوة 0 يقوم المهاجم ذو الصلاحيات المنخفضة بكتابة مستند ملتف مصمم خبيثًا
في مجموعة 'mobile_alerts' في مخزن KV عبر واجهة REST API الخاصة بـ Splunk.
لا حاجة لدور المسؤول أو القوة.
الخطوة 1 تقوم SSG بمعالجة طلب جلب التنبيه.
يقرأ alerts_request_processor.py المستند ويمرره إلى
check_alert_data_valid_json().
→ يرى المُحقق "py/object": "spacebridgeapp..." كمفتاح أول،
ويعيد True، ولا يفحص المفتاح المجاور "notification" الذي يحمل
أداة py/reduce أبدًا.
الخطوة 2 يُمرر المستند (المُحقّق الآن) إلى
jsonpickle.decode(..., safe=True).
يقوم jsonpickle بتحميل class() كائن Alert الجاذب، ويُنشئ مثيله،
ثم يتكرر عبر سماته المخزنة. عندما يصل إلى قيمة
"notification"، يتم تشغيل _restore_reduce():
stage1 = f(*args) # unpickler.py ~line 526
ليس لـ safe=True أي تأثير على هذا المسار البرمجي.
النتيجة تنفيذ تعليمات برمجية عشوائية كحساب خدمة Splunk.
يتطلب فقط تسجيل دخول صالح بصلاحيات منخفضة في Splunk.
{
"py/object": "spacebridgeapp.data.alert_data.Alert",
"notification": {
"py/reduce": [
{"py/function": "subprocess.check_output"},
{"py/tuple": [["uname", "-a"]]}
]
}
}
يفحص المُحقق py/object أولاً (مسموح به)، فيعيد True، ولا يصل أبداً إلى notification.
يوضح poc_cve_2026_20251.py الشرطين اللذين يشكلان سلسلة الاستغلال الكاملة:
| الإثبات الفرعي | ما يظهره |
|---|---|
| أ — تجاوز المُحقق | يعيد check_alert_data_valid_json() القيمة True للمستند الملتوي، دون فحص أداة py/reduce في القيمة المجاورة أبدًا |
| ب — تنفيذ py/reduce | ينفذ jsonpickle.decode(..., safe=True) الأمر subprocess.check_output(['uname', '-a'])، مما يثبت أن safe=True لا يمنع هذا المسار البرمجي |
الحمولة هي عمدًا غير ضارة (قراءة فقط uname -a). هذا ليس استغلالًا هجوميًا.
jsonpickle المدمج مع SSG (يتم تحميله من /Applications/Splunk/etc/apps/splunk_secure_gateway/lib)python3 poc_cve_2026_20251.py -h 127.0.0.1
لا تقم بتشغيله على أنظمة إنتاجية أو أي نظام لا تملكه وليس لديك إذن كتابي صريح لاختباره.
الملف: bin/spacebridgeapp/request/alerts_request_processor.py
alert_json = await response.json()
if not check_alert_data_valid_json(alert_json[0]):
raise SpacebridgeApiRequestError("alert_data is not valid", ...)
alert = jsonpickle.decode(json.dumps(alert_json[0]), safe=True) # ← المصدر
الملف: bin/spacebridgeapp/rest/devices/alert_helper.py
# المحقق يقصر الدائرة على أول مفتاح بادئة 'py':
for key, value in data.items():
if key.startswith("py"):
if key == "py/id":
return value.isinstance(int)
elif key == "py/object":
return value.startswith("spacebridgeapp") # ← يعيد فورًا
else:
return False
# ... لا يتم الوصول أبداً إلى المفاتيح المجاورة
الأساسية: ترقية Splunk Secure Gateway إلى إصدار مُصحح (3.9.20+ أو 3.10.6+ أو 3.8.67+) وترقية Splunk Enterprise إلى 10.0.7+ / 10.2.4+ / 10.4.0+.
إجراءات التخفيف قصيرة المدى (إذا لم يكن التصحيح ممكنًا فورًا):
mobile_alertsنمط هندسي دفاعي: لا تقم أبدًا بإعادة بناء أنواع عشوائية من بيانات مخزنة متأثرة خارجيًا. استبدل jsonpickle.decode() في المدخلات التي يمكن للمهاجم الوصول إليها بمُحلل صارم يعتمد على مخطط، أو قدم قائمة classes= مسموح بها إلى decode(). تأكد من أن روتينات التحقق تجتاز الهياكل المتداخلة بالكامل بدلاً من تقصير الدائرة عند أول مفتاح معروف.
تشمل نفس مجموعة الاستشارات CVE-2026-20253 (CVSS 9.8، إنشاء ملفات عشوائي غير مصادق عليه عبر نقطة نهاية جانبية لـ PostgreSQL). لم تكن هذه الثغرة موجودة في إصدار macOS x86_64 المُختبر من Splunk Enterprise 10.0.6: لا يتم تضمين المكون الجانبي لـ PostgreSQL في هذا النظام الأساسي، ولا توجد ملفات ثنائية أو عمليات جانبية، ولم يُلاحظ أي منفذ مقابل.
يوضح هذا مبدأ ضمان مهمًا: سلسلة الإصدار المتأثر هي شرط ضروري لكن غير كافٍ لقابلية الاستغلال. التحقق على مستوى المكونات يغير صورة المخاطر الحقيقية بشكل جوهري.
| الحقل | القيمة |
|---|---|
| مرجع المشاركة | 2026FO-SPLUNK-20251 |
| نوع الاختبار | التحقق من الثغرات من الصندوق الأبيض (تحليل الشفرة الثابتة) |
| التاريخ | 26 يونيو 2026 |
| النطاق | مثيل بحث محلي من Splunk Enterprise 10.0.6 (127.0.0.1:8089) |
| التصنيف | سري |
ReactiveZero Security Research