
إعلان أمني عام وتحليل فني لثغرة CVE-2026-36590، وهي ثغرة حجب الخدمة في NanoMQ v0.24.9.
يحتوي هذا المستودع على الإشعار الأمني العام والتحليل الفني للثغرة CVE-2026-36590، وهي ثغرة حرمان من الخدمة تؤثر على EMQ NanoMQ v0.24.9.
هذا المستودع عام لتوفير مرجع فني يسهل الوصول إليه لمراجعة CVE. سيتم تحديد التصنيف النهائي لـ CVE-2026-36590 من قِبل فريق CVE أو الـ CNA المعني.
فريق NanoMQ اعترض على هذا الأمر ويعتبره مرتبطًا بالإعدادات. يركز هذا المستودع على الأدلة الفنية، بما في ذلك مواد إعادة الإنتاج، ونتائج ASAN، وسجلات وقت التشغيل، وتحليل الكود المصدري.
/nanomq/nng/src/supplemental/mqtt/mqtt_qos_db_api.c / nni_qos_db_setعند بناء NanoMQ v0.24.9 بدون دعم SQLite بينما يتم ضبط sqlite.enable على true، قد يظل مؤشر قاعدة بيانات QoS NULL. أثناء معالجة رسائل MQTT QoS، قد يُرجع nni_qos_db_set مبكرًا دون تحرير مرجع رسالة مستنسخة. قد تتسبب رسائل MQTT PUBLISH المتكررة ذات QoS > 0 في استهلاك مستمر للذاكرة، مما يؤدي في النهاية إلى حرمان من الخدمة.
تعتمد المشكلة على إعداد وقت تشغيل غير افتراضي، لكن الحقائق التالية تُظهر سبب استمرار حاجتها إلى مزيد من المراجعة:
يقبل NanoMQ إعداد وقت التشغيل ويواصل العمل، بدلًا من الإبلاغ عن عدم توفر دعم SQLite في البناء الحالي.
يمكن أن يحدث هذا التناقض في الإعدادات عمليًا. قد يقوم المستخدم ببناء NanoMQ بأمر البناء العادي، لكنه لاحقًا ينسخ أو يفعل قسم استمرارية SQLite من ملف إعدادات مثال.
مسار الكود المتأثر لا يتحقق بشكل كامل من هذه الحالة غير المتسقة. عندما يعامل إعداد وقت التشغيل SQLite كمفعّل بينما يكون مؤشر قاعدة البيانات NULL، يُرجع nni_qos_db_set() مبكرًا دون تحرير كائن الرسالة المُمرَّر.
بعد قبول هذا الإعداد، يمكن تشغيل المشكلة عبر حركة مرور MQTT عن بُعد. يمكن لرسائل PUBLISH المتكررة ذات QoS > 0 الدخول إلى المسار المتأثر والتسبب في تسربات ذاكرة متراكمة.
أظهرت اختبارات ASAN مع 1 و50 و500 دورة إعادة إنتاج أن البايتات والتخصيصات المتسربة تزداد مع عدد محاولات التشغيل. يشير هذا إلى أن المشكلة تعتمد على عدد المدخلات، وليست تسربًا صغيرًا لمرة واحدة.
يجب على المستخدمين تقييد الوصول إلى مثيلات NanoMQ، وتجنب تعريض خدمات MQTT لعملاء غير موثوقين، وتجنب تفعيل استمرارية SQLite في البنيات التي لا تدعم SQLite. يجب على البائع إضافة تحقق عند بدء التشغيل لإعداد SQLite وتحرير مرجع الرسالة في فرع db == NULL داخل nni_qos_db_set.
Docker/Docker_Reproduction_Guide.mdالملخص يحتوي هذا المستودع على إثبات المفهوم (PoC) والتحليل المفصّل لثغرة تسرب ذاكرة تم اكتشافها في NanoMQ. تسمح المشكلة للمهاجمين عن بُعد بالتسبب في حرمان من الخدمة (DoS) عبر استنزاف ذاكرة النظام باستخدام رسائل MQTT ذات QoS محددة.
لقد أجريت تحليلًا متعمقًا لظاهرة تسرب الذاكرة في Nanomq. من خلال القياس الديناميكي ومراجعة الكود، حددت مسار تسرب موارد حرجًا يُفعَّل عندما يفعّل إعداد وقت التشغيل SQLite (sqlite.enable=true) بينما يُبنى الملف الثنائي دون دعم SQLite (NNG_SUPP_SQLITE غير معرّف).
لإبقاء هذا الأمر موجزًا، قمت بتلخيص النتائج الرئيسية أدناه. للحصول على التحليل الفني الكامل (بما في ذلك تتبعات ASAN التفصيلية، ومخططات دورة الحياة، وسجلات القياس)، يُرجى الرجوع إلى المرفق Analysis_Report.md.
باستخدام AddressSanitizer، حددت مصدر الذاكرة المتسربة إلى nni_msg_alloc داخل tcptran_pipe_recv_cb (nng/src/sp/transport/mqtt/broker_tcp.c). تم تخصيص الذاكرة ولكن لم يتم تحريرها بالكامل أبدًا.
حللت آلية عد المراجع الخاصة بـ nni_msg. يجب أن تشمل دورة حياة رسالة QoS 1 العادية ما يلي:
نظرًا لأن GDB لم يكن عمليًا في هذا السيناريو عالي التزامن، استخدمت القياس الديناميكي لتتبع دورة حياة كائنات ذاكرة محددة (مثل 0x60e00002ffa0).
الاكتشاف: أكدت السجلات عدم تطابق في دورة الحياة:
nmq_pipe_send_start_v4.كشف تتبع تدفق التنفيذ عن سبب فقدان التحرير الثالث:
-DNNG_SUPP_SQLITE، مما أدى إلى إزالة منطق التهيئة في nano_sock_setdb. ومع ذلك، كان nanomq.conf يحتوي على sqlite.enable = true. تسبب هذا في بقاء مؤشر db على NULL.nni_qos_db_set للتخزين، يتحقق الدالة من المؤشر الفارغ:// File: /nanomq/nng/src/supplemental/mqtt/mqtt_qos_db_api.c
void nni_qos_db_set(..., void *db, ..., nng_msg *msg) {
if (db == NULL) {
// CRITICAL FLAW:
// Early return triggers because db is NULL.
// The function holds ownership of 'msg' (Ref++) but fails to release it.
return;
}
// ...
}
تُرجع الدالة بصمت دون استدعاء nni_msg_free(msg). يؤدي هذا إلى فقدان مؤشر الرسالة بشكل لا يمكن استرجاعه، ما يُيتم كتلة الذاكرة فعليًا.
nni_qos_db_set. فهي لا تتعامل مع ملكية مؤشر msg عند تنفيذ إرجاع مبكر بسبب حالة قاعدة بيانات غير صالحة.التوصيات:
nano_sock_setdb أو الدالة main) للتأكد من أن SQLite يعمل بشكل صحيح. إذا تم اكتشاف conf->sqlite.enable == true بينما ماكرو NNG_SUPP_SQLITE غير معرّف أو أن SQLite غير طبيعي، فيجب أن يخرج النظام مع رسالة خطأ أو يضبط enable قسريًا على false ويطبع تحذيرًا.nni_qos_db_set. إذا كان db == NULL، يجب استدعاء nni_msg_free(msg) لموازنة عدد المراجع ومنع تسرب الذاكرة.