موقع PHP الخاص بك تحت المجهر: لماذا يحب المخترقون الأمان الضعيف
\n\nتخيل: لقد أمضيت أسابيع في تطوير مدونة رائعة أو متجر إلكتروني باستخدام PHP. الموقع يعمل، والزوار سعداء. ولكن في يوم "جميل"، تدخل إلى لوحة التحكم، فتجدها فارغة. تم حذف قاعدة البيانات. أو ما هو أسوأ، تظهر إعلانات كازينو على الصفحة الرئيسية، ويتم إعادة توجيه جميع المستخدمين إلى موقع تصيد.
\n\nقصة مألوفة؟ لسوء الحظ، بالنسبة للعديد من مطوري PHP المبتدئين (وليس فقط)، هذا هو الواقع. الأمر المحبط هو أن 90% من هذه الهجمات تحدث بسبب ثغرات تبدو بسيطة: هجمات SQL injection و البرمجة النصية عبر المواقع (XSS). لا يخترق القراصنة خوارزميات التشفير المعقدة - بل يستغلون ببساطة عدم انتباه المبرمجين.
\n\nفي هذه المقالة، لن نلقي محاضرات مملة. سنفهم كيف تعمل هذه الهجمات "من الداخل"، والأهم من ذلك، سنتعلم كيفية وضع حواجز قوية. ستتعلم كيف تجعل كود PHP الخاص بك صعب المنال على المهاجمين. هيا بنا!
\n\nهجمات SQL injection: عندما تتحدث قاعدة البيانات بصوت المخترق
\n\nهجوم SQL injection هو نوع من الهجمات يقوم فيه المهاجم "بإدخال" كود SQL ضار في استعلام قاعدة البيانات. إذا كان تطبيقك لا يقوم بتصفية البيانات المدخلة، يمكن للمخترق أن يجعل قاعدة البيانات تنفذ أي أمر: من سرقة كلمات المرور إلى حذف الجداول بالكامل.
\n\nكيف يبدو الكود الضعيف؟
\n\nتخيل نموذج تسجيل دخول بسيط. غالبًا ما يبدو كود المبتدئين هكذا:
\n\n<?php\n$login = $_POST['login'];\n$password = $_POST['password'];\n\n// خطير! إدخال مباشر في الاستعلام\n$query = "SELECT * FROM users WHERE login = '$login' AND password = '$password'";\n$result = mysqli_query($link, $query);\n?>\n\nيبدو منطقيًا. ولكن ماذا سيحدث إذا أدخل المهاجم السلسلة التالية في حقل اسم المستخدم:
\n\n' OR '1'='1\n\nسيتحول الاستعلام إلى:
\n\nSELECT * FROM users WHERE login = '' OR '1'='1' AND password = '...'\n\nالشرط '1'='1' صحيح دائمًا. تهانينا، لقد دخل المخترق للتو إلى النظام بدون كلمة مرور! وإذا أدخل '; DROP TABLE users; --، فسيختفي جدول المستخدمين إلى الأبد.
هروب البيانات مقابل الاستعلامات المُعدة مسبقًا: أيهما تختار؟
\n\nتنصح العديد من الكتب القديمة باستخدام الدالة mysqli_real_escape_string(). نعم، تقوم بهروب الأحرف الخاصة، لكن هذا من الماضي. لهذه الطريقة عيوب:
- \n
- من السهل نسيان تطبيق الدالة على كل متغير. \n
- لا تحمي من جميع أنواع الحقن (مثل عند العمل مع LIKE). \n
- يصبح الكود غير نظيف ويصعب صيانته. \n
الطريقة الحديثة والصحيحة هي الاستعلامات المُعدة مسبقًا (prepared statements) عبر PDO أو MySQLi. تفصل هذه الطريقة بين منطق الاستعلام والبيانات. تقوم قاعدة البيانات أولاً "بتجميع" قالب الاستعلام، ثم تقوم بإدخال البيانات فيه. حتى لو قام المخترق بإرسال كود ضار، فسيتم التعامل معه كسلسلة نصية عادية، وليس كجزء من أمر SQL.
\n\nكتابة كود آمن باستخدام PDO
\n\nهذا هو الشكل الذي يجب أن يبدو عليه الاستعلام الآمن لقاعدة البيانات باستخدام PDO (كائنات بيانات PHP):
\n\n<?php\n// الاتصال بقاعدة البيانات\n$dsn = 'mysql:host=localhost;dbname=mydb;charset=utf8mb4';\n$pdo = new PDO($dsn, 'user', 'password');\n\n// ضبط وضع الأخطاء (مهم للتصحيح، لكن قم بإزالته في الإنتاج)\n$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);\n\n// تحضير الاستعلام (القالب)\n$stmt = $pdo->prepare("SELECT * FROM users WHERE login = :login AND password = :password");\n\n// ربط المعاملات وتنفيذها\n$stmt->execute([\n ':login' => $_POST['login'],\n ':password' => $_POST['password']\n]);\n\n$user = $stmt->fetch();\n\nif ($user) {\n echo "مرحبًا بك!";\n} else {\n echo "اسم المستخدم أو كلمة المرور غير صحيحة";\n}\n?>\n\nحول