أمان تطبيقات JavaScript: أهم 10 ثغرات للمبتدئين
أمان تطبيقات الويب هو أحد أهم المواضيع لأي مطور. JavaScript (خاصة على جانب الخادم Node.js) غالبًا ما تكون هدفًا للمهاجمين بسبب شعبيتها. في هذه المقالة، سنشرح 10 من أكثر الثغرات شيوعًا التي يواجهها المطورون المبتدئون، ونوضح كيفية تجنبها.
1. XSS (البرمجة النصية عبر المواقع)
XSS هو أحد أكثر الهجمات شيوعًا، حيث يقوم المهاجم بإدخال script ضار في صفحة الويب. يحدث هذا عندما يتم إدراج بيانات من المستخدم في HTML دون هروب (escape).
كود خطير (ضعيف):
app.get('/search', (req, res) => { const query = req.query.q; res.send(`<h1>نتائج البحث: ${query}</h1>`);});كود آمن (حماية):
const escapeHtml = require('escape-html');
app.get('/search', (req, res) => { const query = escapeHtml(req.query.q); res.send(`<h1>نتائج البحث: ${query}</h1>`);});2. حقن SQL (SQL Injection)
إذا كنت تستخدم قواعد بيانات SQL (مثل SQLite أو PostgreSQL)، فإن الاستعلامات غير المهربة يمكن أن تؤدي إلى تسرب البيانات.
كود خطير:
const user = req.body.username;db.query(`SELECT * FROM users WHERE name = '${user}'`);كود آمن (استخدام الاستعلامات المعلمة):
const user = req.body.username;db.query('SELECT * FROM users WHERE name = $1', [user]);3. إلغاء التسلسل غير الآمن (Insecure Deserialization)
استخدام JSON.parse() على بيانات غير موثوقة يمكن أن يؤدي إلى هجمات من نوع "تلوث النموذج الأولي (prototype pollution)".
مثال على الثغرة:
const data = JSON.parse(req.body.jsonData);// إذا كانت data تحتوي على __proto__، فقد يغير ذلك النموذج الأولي لـ Objectالحماية: قم دائمًا بالتحقق من صحة البيانات قبل التحليل (parsing) أو استخدم مكتبات مثل fast-json-stable-stringify.
4. عدم التحقق من الإدخال (Input Validation)
لا تثق أبدًا في البيانات القادمة من المستخدم. تحقق دائمًا من نوع البيانات وطولها وتنسيقها.
// سيء: نقبل كل شيءapp.post('/profile', (req, res) => { const { name, age } = req.body; // ...});
// جيد: نتحقق من الصحةconst schema = { name: 'string', age: 'number' };if (typeof req.body.name !== 'string') throw new Error('اسم غير صالح');5. CSRF (تزوير الطلب عبر المواقع)
هجوم يجبر فيه المهاجم المستخدم على تنفيذ إجراء غير مرغوب فيه على موقع يكون المستخدم مسجلاً دخوله إليه.
الحماية: استخدم رموز CSRF المميزة (CSRF tokens).
const csrf = require('csurf');app.use(csrf({ cookie: true }));
app.get('/form', (req, res) => { res.render('form', { csrfToken: req.csrfToken() });});6. تسرب المعلومات عبر الأخطاء
لا تعرض أبدًا رسائل خطأ مفصلة للمستخدم - فهذا يعطي المتسللين معلومات حول هيكل تطبيقك.
سيء:
app.use((err, req, res, next) => { res.status(500).send(err.stack); // تسرب تتبع الاستدعاءات!});جيد:
app.use((err, req, res, next) => { console.error(err.stack); // نسجلها لأنفسنا res.status(500).send('خطأ داخلي في الخادم');});7. الاستخدام غير الآمن لـ eval() و Function()
الدوال eval() و new Function() تنفذ سلسلة نصية ككود - وهذا خطير للغاية إذا كانت السلسلة تحتوي على بيانات مستخدم.
// خطير! لا تفعل هذا أبدًاconst userInput = req.body.code;eval(userInput); // يمكن للمهاجم تنفيذ أي كودالبديل: