تلويث النموذج الأولي Prototype Pollution
كيف يكتب مفتاح __proto__ في JSON المدموج على النموذج الأولي المشترك فترث كل الكائنات قيم المهاجم ولماذا تفشل قوائم حظر المفاتيح
- المسار
- أمن الويب
- الوقت المتوقع
- 25 د
- المستوى
- متوسط
قبل هذا الدرس
في جافاسكربت كل كائن عادي يرث من نموذج أولي مشترك وتلويث النموذج الأولي أن تكتب بيانات المهاجم خاصية على ذلك النموذج المشترك بدل كائن واحد فبعدها يبدو أن كل كائن في التطبيق يملك تلك الخاصية وخاصية isAdmin ملوثة واحدة تقلب فحوص الصلاحية في التطبيق كله
في هذه اللابات التلويث محاكى على كائن نموذج أولي بديل فلا يمس النموذج الأولي الحقيقي ولا محرك اللابات والسلوك الذي تراه كائن جديد يرث القيمة المزروعة هو بالضبط ما يفعله التلويث الحقيقي
ما هي الثغرة؟
دمج متكرر ينسخ JSON المستخدم في كائن
for (const key in source) {
if (typeof source[key] === 'object') merge(target[key] ||= {}, source[key]);
else target[key] = source[key]; // __proto__ يمر مباشرة
}أرسل proto فيه isAdmin بقيمة true فيكتب الدمج isAdmin على النموذج الأولي وبعدها تصبح الخاصية موجودة في كل كائن جديد
لماذا تحدث؟
الدمج يثق بكل مفتاح والنموذج الأولي يوصل إليه عدة أسماء proto و constructor.prototype فمنع proto وحده يترك constructor مفتوحا وفحص المفاتيح العليا فقط يترك proto متداخلا يلوث عند نزول الدمج
كيف تتوقف؟
تخط المفاتيح الخطرة proto و constructor و prototype في كل عمق لا المستوى العلوي فقط والأفضل تجنب الدمج في كائنات عادية أصلا استخدم Map أو كائنات بلا نموذج أولي عبر Object.create(null) وتحقق من المدخل بمخطط حتى لا تصل المفاتيح غير المتوقعة الدمج
اللابات الثلاثة أدناه تمشي السلم لوث عبر proto وتجاوز حذف proto بـ constructor.prototype وتجاوز الفحص العلوي بمفتاح متداخل
اللابات
تلويث عبر الدمج
محلولسهللاب في المتصفح
لوث النموذج الأولي لتصبح اللوحة الجديدة لوحة مدير
ادخل اللابمقفلتجاوز منع __proto__
محلولمتوسطلاب في المتصفح
لوث النموذج الأولي رغم حذف __proto__
ادخل اللابمقفلتلويث عبر مسار متداخل
محلولصعبلاب في المتصفح
لوث النموذج الأولي بمفتاح متداخل يتجاوز الفحص العلوي
ادخل اللابمقفل
