أمان TypeScript: حقن SQL وXSS تحت السيطرة

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

الكود الخاص بك تحت المجهر: لماذا أمان TypeScript ليس خيارًا بل ضرورة

\n\n

هل تساءلت يومًا ماذا يحدث عندما يدخل مستخدم في حقل البحث على موقعك ليس فقط "كتب عن Python"، بل شيئًا مثل '; DROP TABLE users; --؟ إذا كان الخادم الخلفي الخاص بك على TypeScript غير مستعد لمثل هذا السيناريو، فأنت لا تخاطر فقط بالحصول على خطأ، بل بفقدان قاعدة البيانات بأكملها. هل يبدو هذا كسيناريو فيلم رعب؟ مرحبًا بك في العالم الحقيقي لتطوير الويب، حيث أمان TypeScript ليس ميزة عصرية، بل هو النظافة الأساسية للكود.

\n\n

في هذه المقالة، لن نلقي محاضرات مملة. سنقوم بتحليل العدوين الرئيسيين لأي تطبيق ويب: حقن SQL وXSS (البرمجة النصية عبر المواقع). ستتعرف على كيفية مهاجمة القراصنة لمشاريعك، والأهم من ذلك، كيفية تحويل كود TypeScript الخاص بك إلى حصن منيع باستخدام أمثلة حقيقية وأفضل الممارسات.

\n\n

حقن SQL: كيف "يتحدث" المهاجمون مع قاعدة البيانات الخاصة بك

\n\n

تخيل أن تطبيقك هو موظف استقبال مهذب ينفذ أي طلب من الضيف. إذا طلب الضيف: "أرني الغرفة رقم 5"، يريه الموظف. ولكن ماذا لو طلب الضيف: "أرني جميع الغرف وأعطني مفاتيح الخزنة"؟ بدون تحقق، سينفذ الموظف هذا أيضًا. حقن SQL يعمل تمامًا بهذه الطريقة: يقوم المهاجم "بتضمين" أوامره في إدخال المستخدم العادي.

\n\n

لنفترض أن لديك استعلامًا بسيطًا للبحث عن مستخدم بالاسم:

\n\n
// ❌ خطير: كود ضعيف\nconst userName = req.body.username; // المستخدم أدخل "admin"\nconst query = `SELECT * FROM users WHERE name = '${userName}'`;\ndb.execute(query);
\n\n

يبدو غير ضار؟ والآن تخيل أن المستخدم يدخل: admin' OR '1'='1. يتحول الاستعلام إلى:

\n\n
SELECT * FROM users WHERE name = 'admin' OR '1'='1'
\n\n

تهانينا! لقد أعطيت المهاجم للتو قائمة بجميع مستخدمي النظام. وإذا أراد حذف شيء ما؟ بسهولة: admin'; DROP TABLE users; -- — ولم يعد لقاعدة البيانات الخاصة بك وجود.

\n\n

كيف تحمي نفسك: الاستعلامات المعلمة هي درعك

\n\n

القاعدة الأساسية لـ الحماية من حقن SQL في TypeScript: لا تقم أبدًا بإدراج بيانات المستخدم مباشرة في سلسلة الاستعلام. استخدم الاستعلامات المعلمة (prepared statements). فهي تفصل بين كود SQL والبيانات، وتتعامل قاعدة البيانات مع إدخال المستخدم فقط كبيانات وليس كأوامر.

\n\n

مثال مع مكتبة pg (لـ PostgreSQL):

\n\n
// ✅ آمن: استعلام معلم\nimport { Pool } from 'pg';\n\nconst pool = new Pool({\n  connectionString: process.env.DATABASE_URL\n});\n\nasync function getUserByName(userName: string): Promise<any> {\n  const query = 'SELECT * FROM users WHERE name = $1';\n  const result = await pool.query(query, [userName]);\n  return result.rows;\n}\n\n// الاستخدام\nconst userInput = req.body.username; // حتى لو كان "admin' OR '1'='1"\nconst user = await getUserByName(userInput);\n// قاعدة البيانات ستتعامل مع هذا كبحث عن مستخدم بهذا الاسم الغريب\nconsole.log(user); // [] — لم يتم العثور على شيء
\n\n

نفس المبدأ يعمل مع ORM الأخرى، مثل Prisma أو TypeORM. فهي تستخدم الاستعلامات المعلمة افتراضيًا، مما يجعل أمان TypeScript ميزة مدمجة.

\n\n
// ✅ آمن: استخدام Prisma\nimport { PrismaClient } from '@prisma/client';\n\nconst prisma = new PrismaClient();\n\nasync function findUser(name: string) {\n  return prisma.user.findUnique({\n    where: { name: name } // Prisma يقوم بهروب بيانات الإدخال بنفسه\n  });\n}
\n\n

هجمات XSS: عندما يبدأ موقعك في بث كود شخص آخر

\n\n

إذا كانت هجمات حقن SQL تضرب قاعدة البيانات، فإن XSS (البرمجة النصية عبر المواقع) تهاجم المستخدمين. تخيل أن مهاجمًا

المدونات

توصيات الكتب