الرئيسية تعليم لغات البرمجة التأمين ضد ثغرات حقن SQL وثغرات XSS في PHP

التأمين ضد ثغرات حقن SQL وثغرات XSS في PHP

amr gamal سبتمبر 26, 2026

في بناء تطبيقات الويب باستخدام لغة PHP بالمستوى المتوسط، ينتقل تركيز المطور من مجرد كتابة كود ينجز الوظيفة المطلوب تنفيذها إلى بناء تطبيقات متينة قادرة على الصمود أمام محاولات الاختراق والهجمات السيبرانية الشائعة. لم يعد كافياً أن تعمل الصفحة بشكل صحيح، بل يجب أن تكون محصنة ضد المدخلات الخبيثة التي يرسلها المستخدمون عمداً أو عن طريق الخطأ. في هذا الدرس، سنركز على اثنين من أخطر التهديدات الأمنية التي تواجه تطبيقات الويب وهما: ثغرات حقن أوامر قواعد البيانات (SQL Injection) وثغرات البرمجة عبر المواقع (Cross-Site Scripting - XSS). سنتعرف على كيفية حدوثهما برمجياً، وطرق التصدي لهما باستخدام المعايير الحديثة في PHP، مع أمثلة عملية واضحة لتأمين بيانات التطبيق والمستخدمين.

فهم خطورة ثغرات حقن SQL وكيفية منعها كلياً

تحدث ثغرة حقن SQL عندما يقوم المطور بدمج مدخلات المستخدم مباشرة داخل استعلام قاعدة البيانات (SQL Query) دون تنقية أو فصل بين هيكل الاستعلام والبيانات المُدخلة. هذا الخطأ يسمح للمهاجم بإدخال أوامر SQL خبيثة تؤدي إلى قراءة جداول حساسة، أو تعديل البيانات، أو حتى حذف قاعدة البيانات بالكامل. لنفترض أننا نبحث عن مستخدم بريده الإلكتروني مُدخل عبر نموذج بحث. الكود غير الآمن التالي يوضح كيف تقع المشكلة:

<?php
// كود غير آمن - عرضة لحقن SQL
$conn = new PDO('mysql:host=localhost;dbname=my_database', 'root', 'password');
$email = $_POST['email'];

// الدمج المباشر للمتغير يفتح الباب للاختراق
$sql = "SELECT * FROM users WHERE email = '$email'";
$result = $conn->query($sql);
?>

في الكود أعلاه، إذا قام المستخدم بإدخال نص يحتوي على أوامر SQL مثل ' OR '1'='1، سيتحول الاستعلام إلى صيغة تمنح المهاجم صلاحية الدخول أو جلب كافة سجلات جدول المستخدمين. الحل البرمجي القياسي والوحيد المعتمد لمنع ذلك هو استخدام الاستعلامات المُجهّزة (Prepared Statements) عبر امتداد PDO أو MySQLi. الاستعلامات المُجهّزة تفصل تماماً بين بنية الاستعلام وبين البيانات المُدخلة، حيث يتم إرسال الاستعلام أولاً إلى محرك قاعدة البيانات ليتم تحليله وبناؤه، ثم تُرسل البيانات لاحقاً كقيم بحتة لا يمكن تفسيرها كأوامر برمجية.

<?php
// كود آمن باستخدام الاستعلامات المجهزة عبر PDO
$conn = new PDO('mysql:host=localhost;dbname=my_database', 'root', 'password');
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

$email = $_POST['email'];

// استخدام العلامات النقطية (Placeholders)
$stmt = $conn->prepare('SELECT id, username, email FROM users WHERE email = :email');

// تنفيذ الاستعلام مع تمرير البيانات بأمان
$stmt->execute(['email' => $email]);
$user = $stmt->fetch(PDO::FETCH_ASSOC);

if ($user) {
    echo "مرحباً بك، " . htmlspecialchars($user['username'], ENT_QUOTES, 'UTF-8');
} else {
    echo "المستخدم غير موجود.";
}
?>

في هذا المثال الآمن، قمنا بإنشاء كائن اتصال بـ PDO، ثم استخدمنا الدالة prepare() مع علامة نقطية :email، وبعدها نفذنا الاستعلام عبر تمرير المصفوفة التي تحتوي على المدخلات. بهذه الطريقة، حتى لو أدخل المستخدم كود SQL خبيث، سيتعامل معه النظام على أنه نص عادي للبحث وليس أمراً برمجياً.

فهم ثغرات XSS (Cross-Site Scripting) وحماية المخرجات

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

حماية التطبيق من XSS تعتمد على قاعدة أساسية في هندسة الأمان: "أدخل بحذر، وأخرج بأمان" (Input validation, Output encoding). عند عرض أي بيانات قادمة من المستخدم في المتصفح، يجب استخدام دالة الترميز المناسبة مثل htmlspecialchars() في PHP لتحويل الرموز الخاصة مثل < و > إلى كيانات HTML آمنة لا يمكن للمتصفح تفسيرها كأكواد برمجية.

<?php
// محاكاة لتعليق وارد من مستخدم
$user_comment = "<script>alert('اختراق XSS');</script> مرحباً بالعالم";

// تطبيق ترميز المخرجات الآمن
$safe_comment = htmlspecialchars($user_comment, ENT_QUOTES, 'UTF-8');

echo "<div class='comment-box'>" . $safe_comment . "</div>";
?>

شرح الكود: دالة htmlspecialchars() قامت بتحويل الأوساط البرمجية إلى نصوص مقروءة على الشاشة بدلاً من تنفيذها كأكواد JavaScript. المعامل ENT_QUOTES يقوم بتحويل علامات التنصيص المفردة والمزدوجة لضمان أمان كامل داخل سمات عناصر HTML أيضاً، بينما يحدد المعامل 'UTF-8' ترميز الأحرف الصحيح.

استخدام الفلترة والتحقق من صحة المدخلات (Input Validation & Sanitization)

الاعتماد على الترميز وحده عند الإخراج لا يكفي دائماً، بل يجب التحقق من صحة المدخلات وتنقيتها عند استقبالها في خادم PHP قبل معالجتها أو تخزينها. توفر PHP دوال مدمجة وممتازة لهذا الغرض ضمن مكتبة الفلترة (Filter Functions). بدلاً من كتابة تعبيرات قياسية معقدة (Regular Expressions) لكل مدخل، يمكنك استخدام دالة filter_var() للتحقق من البريد الإلكتروني، أرقام الهواتف، أو عناوين الروابط.

<?php
$raw_email = $_POST['email'];

// التحقق مما إذا كان البريد الإلكتروني صالحاً بالفعل
$filtered_email = filter_var($raw_email, FILTER_VALIDATE_EMAIL);

if ($filtered_email === false) {
    // البريد الإلكتروني غير صالح، يتم إيقاف العملية وإظهار خطأ
    echo "خطأ: يرجى إدخال بريد إلكتروني صحيح.";
    exit;
}

// إذا وصل الكود إلى هنا، فإن $filtered_email نظيف وآمن للاستخدام
?>

هذا النوع من التحقق يمنع إدخال بيانات غير متوقعة تقلل من استقرار قاعدة البيانات وتحمي التطبيق من أنواع أخرى من الأخطاء المنطقية. علاوة على ذلك، يساعد هذا النهج في بناء واجهات برمجة تطبيقات (APIs) أكثر موثوقية وثباتاً عند استقبال البيانات بصيغ مثل JSON.

أخطاء شائعة يقع فيها المطورون المتوسطون

خلال تطوير تطبيقات PHP، يقع الكثير ممن هم في المستوى المتوسط في بعض الفخاخ الأمنية التي يبدو ظاهرها آمناً بينما هي مخترقة:

  • الاعتماد على الدوال القديمة مثل mysql_real_escape_string(): هذه الدوال أصبحت ملغاة (Deprecated) وغير آمنة بالكامل في بيئات العمل الحديثة. الحل البديل والوحيد المعتمد هو استخدام PDO أو MySQLi مع الاستعلامات المُجهّزة.
  • تأمين الإدخال فقط ونسيان الإخراج: يعتقد بعض المطورين أن تنظيف المتغيرات عند استقبالها يعفيها من خطر XSS. هذا غير صحيح؛ لأن البيانات قد تُخزن في قاعدة البيانات بشكل نظيف لكن يتم عرضها في سياقات مختلفة كJavaScript داخل الصفحة، لذا يجب التركيز على ترميز المخرجات أيضاً.
  • استخدام strip_tags() لحماية XSS بشكل مطلق: إزالة وسوم HTML قد تكون مفيدة أحياناً، لكنها ليست حلاً كافياً ضد جميع ثغرات XSS، حيث يمكن للمهاجمين استخدام سمات خبيثة داخل الوسوم المسموح بها (مثل <a href="javascript:...">).
  • تجاهل ضبط وضع معالجة الأخطاء في PDO: ترك أخطاء قاعدة البيانات تظهر للمستخدم النهائي يكشف هيكل الجداول وأسماء الأعمدة، مما يسهل عمليات الاختراق. يجب دائماً تفعيل وضع الاستثناءات (PDO::ATTR_ERRMODE_EXCEPTION) ومعالجة الأخطاء بهدوء في الخلفية.

خلاصة الدرس وطريقة التحقق من النتائج

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

  1. استخدام الاستعلامات المُجهّزة (Prepared Statements) عبر PDO أو MySQLi لكل استعلام يتعامل مع قاعدة البيانات ويحتوي على مدخلات مستخدم.
  2. استخدام ترميز المخرجات (Output Encoding) عبر دالة htmlspecialchars() مع ضبط الترميز الصحيح قبل عرض أي بيانات دخلت من المستخدم على الشاشة.
  3. التحقق من صحة المدخلات وتنقيتها باستخدام أدوات الفلترة الرسمية في PHP مثل filter_var().

للتحقق من فعالية الإجراءات الأمنية التي قمت بتطبيقها، يمكنك إجراء اختبارات يدوية بإدخال رموز اختبار الأمان الشهيرة (مثل أكواد SQL الصريحة ونصوص الـ JavaScript البسيطة) والتأكد من أن التطبيق يعالجها كنصوص عادية دون تنفيذها أو إحداث أي أخطاء في النظام. يفضل دائماً إجراء عمليات تدقيق دورية للكود المصدري لضمان خلو التطبيق من أي ثغرات محتملة مع تطور المشروع وتوسعه.

الكاتب
عمرو جمال

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