أقل الصلاحيات و HTTPS ورؤوس الأمان
قبل سدّ كل ثغرة على حدة: مبادئ ورؤوس تحمي تطبيقك كله. ⏱ نحو 40 دقيقة.
- تطبّق مبدأ أقل الصلاحيات والدفاع بالعمق.
- تشرح ما يحميه
HTTPSوأين يُستخدم. - تضيف رؤوس الأمان بـ
helmetوتخفي بصمة الخادم. - تدرك خطر المكوّنات القديمة وطرق فحصها.
١مبادئ تحكم كل قرار
قبل الثغرات المحددة، ثلاثة مبادئ تحكم التصميم الآمن كله، من الخطة: «تطبيق مبادئ أمان الويب مثل أقل الصلاحيات (Least Privilege) و HTTPS».
| المبدأ | المعنى | تطبيق |
|---|---|---|
| أقل الصلاحيات | امنح كل طرف أدنى صلاحية تكفي لعمله فقط | حساب القاعدة للتطبيق لا يملك DROP TABLE |
| الدفاع بالعمق | طبقات متتالية، إن أخطأت واحدة أمسكت الأخرى | تحقق في الواجهة والخادم والقاعدة |
| الفشل الآمن | عند الخطأ، ارفض لا تسمح | خطأ في التحقق ← امنع الوصول |
| التبسيط | الكود الأبسط أقل ثغرات | لا تكتب تشفيرك بنفسك |
«أقل الصلاحيات» أهمها أثرًا: لو اخترق مهاجم جزءًا، فالضرر محدود بصلاحية ذلك الجزء. حساب قاعدة بيانات التطبيق يجب ألا يملك صلاحية حذف الجداول، فحتى لو نجح حقن SQL لن يمحو القاعدة.
٢HTTPS أولًا
HTTPS يشفّر كل ما ينتقل بين المتصفح والخادم، فيمنع تنصّت الشبكة (تهديد كشف المعلومات) والعبث بالبيانات في الطريق (تهديد العبث). بدونه، كل كلمة مرور ورمز جلسة يسير نصًّا مكشوفًا على الشبكة.
| بدون HTTPS | مع HTTPS |
|---|---|
| كلمة المرور تسير نصًّا مكشوفًا | مشفّرة في الطريق |
| يمكن حقن سكربت في الصفحة شبكيًّا | المحتوى موقّع ضد العبث |
| رمز الجلسة قابل للالتقاط | محمي، خاصة مع كوكي Secure |
وفي العمل الحقيقي يُضاف رأس Strict-Transport-Security (HSTS) ليُلزم المتصفح باستخدام HTTPS دائمًا. وهذا أحد ما تضيفه مكتبة helmet تلقائيًّا.
٣رؤوس الأمان وبصمة الخادم
الخادم الافتراضي يكشف معلومات ويفتقر لرؤوس الحماية. انظر خادمًا عاريًا: يعلن أنه Express في رأس X-Powered-By، فيسهّل على المهاجم البحث عن ثغرات هذه النسخة:
const express = require('express');const app = express();app.use(express.json());app.use(express.urlencoded({ extended: false })); app.get('/', (req, res) => res.json({ app: 'متجر رفيق' }));app.listen(3000);
لاحظ الرأس X-Powered-By: Express. وهو هدية للمهاجم: يعرف منصتك فيبحث عن ثغراتها المعروفة.
الحل سطران: إخفاء البصمة، وإضافة رؤوس الأمان بمكتبة helmet التي تضيف حزمة رؤوس وقائية بإعداد واحد:
const express = require('express');const helmet = require('helmet');const app = express(); app.disable('x-powered-by'); // أخفِ أن الخادم Expressapp.use(helmet()); // أضف رؤوس الأمان القياسية app.get('/', (req, res) => res.json({ app: 'متجر رفيق' }));app.listen(3000);
اختفى X-Powered-By، وأُضيفت رؤوس مثل Content-Security-Policy و X-Content-Type-Options و Strict-Transport-Security. كل رأس يسدّ بابًا.
| الرأس | يحمي من |
|---|---|
Content-Security-Policy | تنفيذ سكربتات غريبة (XSS) |
X-Content-Type-Options | تخمين المتصفح لنوع المحتوى |
X-Frame-Options | تضمين موقعك في إطار (clickjacking) |
Strict-Transport-Security | النزول إلى HTTP غير المشفّر |
توقّع وتحقّق
«أقل الصلاحيات» يعني:
HTTPS يحمي أساسًا:
رأس X-Powered-By يُفضَّل:
مكتبة helmet تضيف:
الخلاصة
- أقل الصلاحيات يحدّ الضرر إذا اخترق المهاجم جزءًا من النظام.
HTTPSيشفّر كل ما ينتقل بين المتصفح والخادم، ويُطبَّق على الموقع كله.helmetيضيف رؤوس أمان وقائية بإعداد واحد، وإخفاءX-Powered-Byيقلل المعلومات.- حدّث المكوّنات وافحصها بـ
npm audit؛ المكتبة القديمة ثغرة جاهزة.
تحدٍّ برمجي: تحصين خادم «رفيق»
متوسطهذا الخادم يعمل لكنه مكشوف: يعلن أنه Express ولا يحمل أي رأس أمان. حصّنه دون تغيير مساراته.
- أخفِ الرأس
X-Powered-By. - أضف رؤوس الأمان القياسية بمكتبة
helmet. - أبقِ المسارين
/و/healthيعملان كما هما.
👀 اعرض الاستجابات المطلوبة
GET /GET /health
- الخادم يعمل ويرد على كل الطلبات بلا أخطاء غير معالَجة
- المسار / يعمل ← 200
- الصفحة الرئيسية ترد باسم المتجر
- المسار /health يعمل ← 200
- لا يكشف
X-Powered-By - يضيف رأس
X-Content-Type-Options - يستخدم helmet
💡 تلميح 1
const helmet = require('helmet');.💡 تلميح 2
app.disable('x-powered-by');.💡 تلميح 3
app.use(helmet()); قبل المسارات.حاول بنفسك أولًا؛ للمسألة أكثر من حلّ صحيح.
const express = require('express');const helmet = require('helmet');const app = express(); app.disable('x-powered-by');app.use(helmet()); app.get('/', (req, res) => res.json({ app: 'متجر رفيق' }));app.get('/health', (req, res) => res.json({ ok: true }));app.listen(3000);