الجدران النارية و TLS وحماية الشبكة
ما الذي يحمي تطبيقك خارج كوده، وكيف يُخدع خادمك ليطلب ما لا يجوز؟ ⏱ نحو 40 دقيقة.
- تصف طبقات حماية البنية التحتية.
- تشرح خدمات
TLSالثلاث. - تدرك أن
WAFيسند الكود لا يحلّ محلّه. - تكتشف
SSRFوتصلحه بقائمة مسموح.
١طبقات حماية البنية التحتية
أمن الكود لا يكفي؛ يسنده أمن البنية التحتية حوله. تمرّ البيانات عبر طبقات، كل طبقة تصفّي ما قبلها:
| الطبقة | دورها |
|---|---|
| الجدار الناري الشبكي | يفتح المنافذ اللازمة فقط (مثلًا 443)، ويغلق الباقي |
TLS/HTTPS | يشفّر النقل ويوثّق هوية الخادم بشهادة |
| جدار تطبيقات الويب WAF | يصفّي أنماط الهجوم المعروفة قبل وصولها للتطبيق |
| التطبيق | الدفاعات في الكود (كل ما سبق في المقرر) |
٢TLS: الثقة في النقل
TLS (الذي يجعل HTTP يصير HTTPS) يقدّم ثلاثة:
| الخدمة | المعنى |
|---|---|
| التشفير | لا يُقرأ ما ينتقل في الطريق |
| السلامة | يُكتشف العبث بالبيانات المنقولة |
| التوثيق | شهادة الخادم تثبت أنه من يدّعي |
الشهادة يصدرها طرف موثوق (CA)، ويتحقق المتصفح منها. انتهاء الشهادة أو ضعف إصدار TLS قديم ثغرة؛ استخدم TLS حديثًا وجدّد الشهادات.
٣SSRF: حين يُخدع خادمك ليطلب
فئة A10 في OWASP: تزوير الطلب من الخادم (SSRF). إن سمحت لخادمك بجلب رابط يحدده المستخدم، قد يوجّهه المهاجم إلى موارد داخلية لا يصلها هو مباشرة (خدمات داخل الشبكة، بيانات اعتماد السحابة). الخادم موثوق داخليًّا، فيصبح وكيلًا للمهاجم.
const express = require('express');const app = express();app.use(express.json());app.use(express.urlencoded({ extended: false })); const ALLOW = ['api.weather.sa', 'api.rafee.sa']; // قائمة المضيفات المسموحة app.get('/fetch', (req, res) => { const host = String(req.query.host || ''); if (!ALLOW.includes(host)) // ✓ لا نطلب إلا المسموح return res.status(400).json({ error: 'مضيف غير مسموح' }); res.json({ ok: true, fetchedFrom: host }); // (في الواقع: طلب فعلي للمضيف)}); app.listen(3000);
الطلب الأول لمضيف مسموح نجح. والثاني لعنوان بيانات اعتماد السحابة الداخلي (169.254.169.254) رُفض؛ لأنه ليس في قائمة المسموح. القائمة تمنع الخادم من أن يُوجَّه إلى الداخل.
توقّع وتحقّق
الجدار الناري الشبكي:
TLS يقدّم:
SSRF يخدع الخادم ليطلب:
الدفاع عن SSRF:
الخلاصة
- طبقات البنية: جدار شبكي، و
TLS، وWAF، ثم دفاعات الكود. TLSيقدّم تشفيرًا وسلامة وتوثيقًا بشهادة من طرف موثوق.WAFيسند أمن الكود ويُتجاوَز؛ لا تتكل عليه وحده.SSRF: خادمك يُخدع ليطلب موارد داخلية؛ الدفاع قائمة مضيفات مسموحة.
تحدٍّ برمجي: سدّ ثغرة SSRF
متقدممسار الجلب يطلب أي مضيف يحدده المستخدم، فهو عرضة لـ SSRF نحو الموارد الداخلية. قيّده بقائمة مضيفات مسموحة.
- عرّف قائمة مسموحة تضم
api.weather.saوapi.rafee.sa. - مضيف مسموح يُقبل.
- مضيف غير مسموح (مثل عنوان داخلي) يُرفض 400.
👀 اعرض الاستجابات المطلوبة
GET /fetch?host=api.weather.saGET /fetch?host=169.254.169.254GET /fetch?host=localhost
- الخادم يعمل ويرد على كل الطلبات بلا أخطاء غير معالَجة
- مضيف مسموح يُقبل
- عنوان داخلي يُرفض ← 400
- localhost يُرفض ← 400
- يستخدم قائمة مسموحة
💡 تلميح 1
const ALLOW = ['api.weather.sa', 'api.rafee.sa'];.💡 تلميح 2
if (!ALLOW.includes(host)) return res.status(400)….💡 تلميح 3
حاول بنفسك أولًا؛ للمسألة أكثر من حلّ صحيح.
const express = require('express');const app = express();app.use(express.json());app.use(express.urlencoded({ extended: false })); const ALLOW = ['api.weather.sa', 'api.rafee.sa'];app.get('/fetch', (req, res) => { const host = String(req.query.host || ''); if (!ALLOW.includes(host)) return res.status(400).json({ error: 'مضيف غير مسموح' }); res.json({ ok: true, fetchedFrom: host });});app.listen(3000);