هذه المواجهة الأخيرة في مسار الويب لوحة الغربان الكاملة لا تسقط بثغرة واحدة بل بسلسلة من ثلاث تبدأ زائرا وتربط تسريب معرفات ثم جلسة متوقعة ثم حقن قالب لتصل إلى المفتاح الرئيسي الذي يسقط اللوحة
لوحة الغربان تطبيق من عدة صفحات اللوحة والأعضاء وجلستي وأداة التقارير تبدأ زائرا صفحة الأعضاء تسرب تلميح مفتاح أي عضو وصفحة جلستي تكشف شكل الجلسة المتوقع وأداة التقارير للمدراء تعرض قالبا على سياق فيه المفتاح الرئيسي لا خطوة تكفي وحدها
لماذا نجح الحل
كل ثغرة وحدها محدودة لكن ربطها يصنع اختراقا كاملا تسريب المعرفات أعطى التلميح والتلميح مع شكل الجلسة المتوقع صنع جلسة admin وجلسة admin فتحت أداة قابلة لحقن القوالب كشفت المفتاح هكذا تعمل الهجمات الحقيقية سلسلة لا ثغرة مفردة والدفاع يكسر السلسلة عند كل حلقة فحص ملكية على الأعضاء وجلسات عشوائية موقعة وقوالب لا تبنى من مدخل المستخدم
السبب الجذري
ثلاثة جذور مجتمعة غياب تفويض الكائن على الأعضاء وجلسة مشتقة بشكل متوقع وعرض قالب من مدخل المستخدم بسياق حساس كل واحدة حلقة في السلسلة
كيف يصلح الكود
اكسر السلسلة عند كل حلقة تفويض على الكائنات وجلسات عشوائية موقعة وقوالب ثابتة لا تبنى من المستخدم
الكود المصاب
app.post('/member', (req, res) => res.json(members[req.body.id])); // IDOR
const role = session.split(':')[0]; // predictable session
res.send(render(req.body.template, { config: { master } })); // SSTI
الكود الآمن
app.post('/member', requireOwner, (req, res) => res.json(ownRecord(req.user))); // ownership
const { role } = verifySigned(session); // random, signed
res.send(renderFixedTemplate({ name: req.user.name })); // no user template
الأثر في الواقع
سلاسل الثغرات هي ما يحول مشاكل متوسطة إلى اختراق كامل للوحات الإدارة في الواقع وتقارير المكافآت الكبرى غالبا سلاسل لا ثغرة واحدة
كيف يكتشفها المدافعون
المدافع يفكر بالسلاسل لا الثغرات المفردة يفرض فحص الملكية وجلسات عشوائية موقعة ويمنع عرض قوالب من المستخدم ويرصد التنقل من تسريب معرف إلى رفع صلاحية إلى أداة إدارية