محتويات الدورة

Node.js / المتقدم: خدمات Node.js موثوقة / الدرس 17

الحدود الأمنية وسلامة الاعتماديات

قيد المدخلات غير الموثوقة وقلل امتيازات العملية وعامل تغييرات الاعتماديات كتغييرات تنفيذية.

وقت القراءة التقريبي: 4 دقيقةتاريخ مراجعة المحتوى
في هذه الصفحة

أهداف الدرس

  • اشرح المفاهيم والمفاضلات المتعلقة بموضوع «الحدود الأمنية وسلامة الاعتماديات».
  • توقع المثالين وتحقق من مخرجاتهما وسلوك تنظيف الموارد فيهما.
  • شخّص الإخفاقات الثلاثة الشائعة وطبق الحلول المشروحة على مدخلات مشابهة.

تحديد ما يتحكم فيه المهاجم

احصر نقاط الدخول كالأجسام والاستعلامات والترويسات وأسماء المرفوعات والإعدادات وتحديثات الاعتماديات. اسأل عن المورد أو الامتياز الذي يؤثر فيه كل مدخل. يجب أن يثبت التحقق عقدا ضيقا قبل الملفات والقواعد والعمليات الفرعية والتعابير المكلفة. حدود الحجم والزمن والتزامن ضوابط أمن وموثوقية معا. قد يكون الطلب صحيح الصياغة لكنه مكلفا عمدا. اربط نموذج التهديد بتدفق بيانات محدد بدلا من دالة تنظيف عامة لكل شيء.

اختيار المعرفات بدلا من المسارات

يقبل المثال الأول معرف مستند مقيدا ويحوله إلى اسم ملف، ويرفض نص تجاوز المجلد قبل البناء. هذا أكثر أمانا من إتاحة مسارات عشوائية، لكنه يفترض ملكية الخادم للمجلد وحمايته. تحتاج الروابط الرمزية والمجلدات القابلة للكتابة والسباقات إلى تصميم مستقل. فضّل الواجهات المباشرة على العمليات الفرعية، وعند الضرورة مرر ملفا تنفيذيا ومصفوفة معاملات دون shell. يمنع الفصل توسعات الطرفية لكنه لا يجعل كل خيار للبرنامج الهدف آمنا.

عدم دمج الخصائص العشوائية

قد تغير مفاتيح كائن غير موثوق السلوك عند نسخها إلى إعدادات موثوقة أو دمجها في شيفرة حساسة لسلسلة النماذج. يبني المثال الثاني كائنا من قائمة سماح ويرفض البقية ومنها __proto__. ويتحقق من قيمة theme؛ فلا تعني صحة المفتاح صحة القيمة. هذا محلل ضيق وليس إصلاحا عاما للدمج العميق. تجنب تقييم نص الطلب برمجيا، ولا تستخدم vm حدا أمنيا للشيفرة العدائية. قيد القدرات بالتصميم وعزل النظام حيث يلزم.

javascript مثال كامل: عدم دمج الخصائص العشوائية
import { join } from 'node:path';
function documentPath(base, id) {
  if (typeof id !== 'string' || !/^[a-z0-9]{1,32}$/.test(id)) throw new Error('Invalid document id');
  return join(base, `${id}.json`);
}
console.log(documentPath('/lab-owned', 'report7').endsWith('report7.json'));
try { documentPath('/lab-owned', '../secret'); } catch (error) { console.log(error.message); }
الناتج المتوقع
true
Invalid document id

يحسب المثال المسارات فقط ولا يقرأ أو يكتب في /lab-owned. ترفض قائمة المعرفات صياغة تجاوز المجلد.

تدقيق سلسلة التوريد

قد يشغّل تثبيت الاعتماديات سكربتات ويدخل شيفرة انتقالية. راجع هوية الحزمة وتغير الملكية والحاجة وفروق القفل والتنبيهات الرسمية قبل التحديث. تحدد npm audit تنبيهات معروفة في بياناتها؛ ولا يثبت التقرير النظيف أمان التطبيق. تجنب إصلاح force آليا دون مراجعة قد يغير إصدارات رئيسية ويكسر التوافق. كرر التثبيت وقلل الاعتماديات وحدّث التصحيحات المدعومة عبر اختبار. قيد اعتمادات البناء ولا تكشف أسرار النشر لوظائف طلبات دمج غير موثوقة.

javascript مثال كامل: تدقيق سلسلة التوريد
function settings(text) {
  const value = JSON.parse(text);
  if (!value || typeof value !== 'object' || Array.isArray(value)) throw new Error('Expected object');
  if (Object.keys(value).some(key => key !== 'theme')) throw new Error('Unknown setting');
  if (!['light', 'dark'].includes(value.theme)) throw new Error('Invalid theme');
  return { theme: value.theme };
}
console.log(JSON.stringify(settings('{"theme":"dark"}')));
try { settings('{"__proto__":{"admin":true}}'); } catch (error) { console.log(error.message); }
console.log(Object.prototype.admin === undefined);
الناتج المتوقع
{"theme":"dark"}
Unknown setting
true

ينسخ المحلل قيمة معتمدة واحدة إلى كائن جديد. ولا تغير الحمولة المرفوضة Object.prototype.

تقليل أثر الأخطاء

شغّل الخدمة بأقل أذونات ملفات وشبكة وقاعدة مطلوبة. احفظ الأسرار في وسيلة تشغيل مناسبة وغيّرها بعد الكشف. استخدم TLS وثقة وكيل صريحة وحدود طلبات وتسجيلا آمنا. عامل جلب الروابط من الخادم كحد SSRF؛ ويجب أن تراعي قائمة السماح التحويلات وDNS والعناوين الداخلية لا النص الأول فقط. اختبر الحالات السلبية وإساءة الحدود في بيئة معزولة. وثّق الحد المفترض وأعد التحقق عند تغير البنية أو الاعتماديات.

الأخطاء الشائعة وإصلاحها

يتجاوز مسار مجلد التخزين

لماذا يحدث؟
عومل نص المستخدم كمسار مأذون.
كيف تصلحه؟
حوّل معرفات مقيدة داخل تخزين يملكه الخادم.
كيف تتجنب تكراره؟
اختبر التجاوز والفواصل والروابط وأذونات المجلد.

يُعد تدقيق نظيف ضمانا

لماذا يحدث؟
اختلط مسح التنبيهات المعروفة بالمراجعة الشاملة.
كيف تصلحه؟
راجع حدود التطبيق وسلوك الاعتماديات أيضا.
كيف تتجنب تكراره؟
اجمع التصحيح وأقل الامتيازات والاختبار الموجه.

تحتوي السجلات ترويسات الاعتماد

لماذا يحدث؟
سُجل الطلب كاملا للتشخيص.
كيف تصلحه؟
احجب الاعتمادات وغيّر الأسرار المكشوفة.
كيف تتجنب تكراره؟
حدد حقول السجل المسموحة واختبر الحجب.

اختبر فهمك

1. لماذا لا تكفي join(base, userPath) سياسة أمنية؟

اعرض الحل المشروح

تطبع join المسارات ولا تقرر الإذن. قد تتجاوز مقاطع الأب المجلد، وقد تغير الروابط والمجلدات القابلة للكتابة المقصد. فضّل معرفات مقيدة تحول إلى أسماء مضبوطة وطبق ملكية المجلد وقواعد الوصول.

2. يقترح التدقيق ترقية force تغير الإصدار الرئيسي لاعتمادية. ما الخطوة المسؤولة؟

اعرض الحل المشروح

اقرأ التنبيه وتعليمات الانتقال وتحقق من التعرض وأعد أصغر تحديث مناسب واختبر السلوك المتأثر منعزلا. راجع القفل قبل الإصدار، وسجل الخطر الباقي وتخفيفه بدلا من افتراض أمان عدم الفعل أو تغيير كاسر غير مختبر.

أهم ما تعلمته

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

المراجع الرسمية