ما هو حقن SQL وكيفية منعه في تطبيقات PHP؟

هل تعتقد أن قاعدة بيانات SQL الخاصة بك فعالة وآمنة من التدمير الفوري؟ حسنًا ، حقن SQL يختلف!

نعم ، نتحدث عن تدمير فوري ، لأنني لا أريد أن أفتح هذه المقالة بالمصطلحات المعتادة “تشديد الأمن” و “منع الوصول الضار”. حقن SQL هي خدعة قديمة في الكتاب يعرفها الجميع ، كل مطور ، جيدًا ويدرك جيدًا كيفية منعها. باستثناء ذلك الوقت الغريب عندما يخطئون ، والنتائج يمكن أن تكون كارثية.

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

ما هو حقن SQL؟

مفتاح فهم SQL Injection هو اسمها: SQL + Injection. كلمة “حقن” هنا ليس لها أي دلالات طبية ، بل هي استخدام فعل “حقن”. معًا ، تنقل هاتان الكلمتان فكرة وضع SQL في تطبيق ويب.

وضع SQL في تطبيق ويب. . . أمم . . . أليس هذا ما نفعله على أي حال؟ نعم ، لكننا لا نريد مهاجمًا يقود قاعدة البيانات الخاصة بنا. دعونا نفهم ذلك بمساعدة مثال.

لنفترض أنك تقوم ببناء موقع PHP نموذجي لمتجر محلي للتجارة الإلكترونية ، لذلك قررت إضافة نموذج اتصال مثل هذا:

<form action="record_message.php" method="POST">
  <label>Your name</label>
  <input type="text" name="name">
  
  <label>Your message</label>
  <textarea name="message" rows="5"></textarea>
  
  <input type="submit" value="Send">
</form>

ودعنا نفترض أن الملف send_message.php يخزن كل شيء في قاعدة بيانات حتى يتمكن أصحاب المتجر من قراءة رسائل المستخدم لاحقًا. قد يحتوي على بعض التعليمات البرمجية مثل هذا:

<?php

$name = $_POST['name'];
$message = $_POST['message'];

// check if this user already has a message
mysqli_query($conn, "SELECT * from messages where name = $name");

// Other code here

لذا فأنت تحاول أولاً معرفة ما إذا كان هذا المستخدم لديه بالفعل رسالة غير مقروءة. استعلام SELECT * من الرسائل حيث يبدو name = $ name بسيطًا بما يكفي ، أليس كذلك؟

خاطئ – ظلم – يظلم!

في براءتنا ، فتحنا الأبواب للتدمير الفوري لقاعدة بياناتنا. ولكي يحدث هذا ، يجب أن يستوفي المهاجم الشروط التالية:

  • يعمل التطبيق على قاعدة بيانات SQL (اليوم ، يتم تشغيل كل تطبيق تقريبًا)
  • اتصال قاعدة البيانات الحالي لديه أذونات “تحرير” و “حذف” في قاعدة البيانات
  • يمكن تخمين أسماء الجداول المهمة

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

  قم بإنشاء خطة عمل مثالية باستخدام هذه الأدوات التسعة

جو أوامر مبتورة؟ نعم سيدي! دعونا نرى ما سيصبح عليه الاستعلام عندما يتم تنفيذه بواسطة سكربت PHP:

حدد * من الرسائل WHERE name = Joe ؛ أوامر مبتورة

حسنًا ، يحتوي الجزء الأول من الاستعلام على خطأ في بناء الجملة (لا توجد علامات اقتباس حول “Joe”) ، لكن الفاصلة المنقوطة تجبر محرك MySQL على البدء في تفسير جزء جديد: أوامر مقطوعة. تمامًا مثل ذلك ، بضربة واحدة ، اختفى سجل الطلبات بالكامل!

الآن بعد أن عرفت كيف يعمل حقن SQL ، حان الوقت للنظر في كيفية إيقافه. الشرطان اللذان يجب الوفاء بهما لحقن SQL ناجح هما:

  • يجب أن يحتوي البرنامج النصي PHP على امتيازات التعديل / الحذف في قاعدة البيانات. أعتقد أن هذا ينطبق على جميع التطبيقات ولن تكون قادرًا على جعل تطبيقاتك للقراءة فقط. 🙂 وخمن ماذا ، حتى لو أزلنا جميع امتيازات التعديل ، لا يزال بإمكان حقن SQL السماح لشخص ما بتشغيل استعلامات SELECT وعرض جميع قاعدة البيانات ، بما في ذلك البيانات الحساسة. بمعنى آخر ، لا يعمل تقليل مستوى الوصول إلى قاعدة البيانات ، ويحتاجه التطبيق الخاص بك على أي حال.
  • يتم معالجة إدخال المستخدم. الطريقة الوحيدة التي يمكن أن يعمل بها إدخال SQL هي عندما تقبل البيانات من المستخدمين. مرة أخرى ، ليس من العملي إيقاف جميع المدخلات لتطبيقك لمجرد أنك قلق بشأن حقن SQL.
  • منع حقن SQL في PHP

    الآن ، بالنظر إلى أن اتصالات قاعدة البيانات والاستعلامات ومدخلات المستخدم هي جزء من الحياة ، كيف يمكننا منع حقن SQL؟ لحسن الحظ ، الأمر بسيط جدًا ، وهناك طريقتان للقيام بذلك: 1) تعقيم مدخلات المستخدم ، و 2) استخدام العبارات المعدة مسبقًا.

    تعقيم مدخلات المستخدم

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

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

      كيف تعمل مصادقة Kerberos؟

    هناك عيب واحد في هذا النهج: إنها تقنية قديمة حقًا تتماشى مع الأشكال القديمة للوصول إلى قاعدة البيانات في PHP. اعتبارًا من PHP 7 ، لم تعد هذه الوظيفة موجودة ، مما يقودنا إلى الحل التالي.

    استخدم العبارات المعدة

    البيانات المعدة هي طريقة لجعل استعلامات قاعدة البيانات أكثر أمانًا وموثوقية. الفكرة هي أنه بدلاً من إرسال الاستعلام الأولي إلى قاعدة البيانات ، فإننا نخبر قاعدة البيانات أولاً بهيكل الاستعلام الذي سنرسله. هذا ما نعنيه بـ “تحضير” البيان. بمجرد إعداد العبارة ، نقوم بتمرير المعلومات كمدخلات ذات معلمات بحيث يمكن لقاعدة البيانات “ملء الفجوات” عن طريق توصيل المدخلات بهيكل الاستعلام الذي أرسلناه من قبل. هذا يزيل أي قوة خاصة قد تمتلكها المدخلات ، مما يؤدي إلى معاملتها على أنها مجرد متغيرات (أو حمولات ، إذا صح التعبير) في العملية برمتها. إليك ما تبدو عليه العبارات المعدة:

    <?php
    $servername = "localhost";
    $username = "username";
    $password = "password";
    $dbname = "myDB";
    
    // Create connection
    $conn = new mysqli($servername, $username, $password, $dbname);
    
    // Check connection
    if ($conn->connect_error) {
        die("Connection failed: " . $conn->connect_error);
    }
    
    // prepare and bind
    $stmt = $conn->prepare("INSERT INTO MyGuests (firstname, lastname, email) VALUES (?, ?, ?)");
    $stmt->bind_param("sss", $firstname, $lastname, $email);
    
    // set parameters and execute
    $firstname = "John";
    $lastname = "Doe";
    $email = "[email protected]";
    $stmt->execute();
    
    $firstname = "Mary";
    $lastname = "Moe";
    $email = "[email protected]";
    $stmt->execute();
    
    $firstname = "Julie";
    $lastname = "Dooley";
    $email = "[email protected]";
    $stmt->execute();
    
    echo "New records created successfully";
    
    $stmt->close();
    $conn->close();
    ?>

    أعلم أن العملية تبدو معقدة بشكل غير ضروري إذا كنت جديدًا على البيانات المعدة ، لكن المفهوم يستحق الجهد المبذول. هنا مقدمة لطيفة لها.

    بالنسبة لأولئك الذين هم بالفعل على دراية بامتداد PHP’s PDO ويستخدمه لإنشاء بيانات معدة ، لدي نصيحة صغيرة.

    تحذير: كن حذرًا عند إعداد PDO

    عند استخدام PDO للوصول إلى قاعدة البيانات ، يمكننا الانغماس في شعور زائف بالأمان. “آه ، حسنًا ، أنا أستخدم PDO. الآن لست بحاجة إلى التفكير في أي شيء آخر “- هذه هي الطريقة التي يسير بها تفكيرنا بشكل عام. صحيح أن PDO (أو العبارات المعدة من MySQLi) كافية لمنع جميع أنواع هجمات حقن SQL ، ولكن يجب أن تكون حذرًا عند إعدادها. من الشائع فقط نسخ الكود ولصقه من البرامج التعليمية أو من مشاريعك السابقة والمضي قدمًا ، ولكن هذا الإعداد يمكنه التراجع عن كل شيء:

    $dbConnection->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);

    ما يفعله هذا الإعداد هو إخبار PDO بمحاكاة العبارات المعدة بدلاً من استخدام ميزة البيانات المعدة بالفعل في قاعدة البيانات. وبالتالي ، ترسل PHP سلاسل استعلام بسيطة إلى قاعدة البيانات حتى لو بدا أن التعليمات البرمجية الخاصة بك تقوم بإنشاء عبارات معدة وإعداد المعلمات وكل ذلك. بمعنى آخر ، أنت عرضة لحقن SQL كما كان من قبل. 🙂

    الحل بسيط: تأكد من ضبط هذه المحاكاة على خطأ.

    $dbConnection->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

    الآن يتم إجبار سكربت PHP على استخدام عبارات معدة على مستوى قاعدة البيانات ، مما يمنع جميع أنواع حقن SQL.

      8 أفضل برامج سطح المكتب البعيد للأعمال الصغيرة والمتوسطة

    منع استخدام WAF

    هل تعلم أنه يمكنك أيضًا حماية تطبيقات الويب من حقن SQL باستخدام WAF (جدار حماية تطبيقات الويب)؟

    حسنًا ، ليس فقط حقن SQL ولكن العديد من الثغرات الأمنية الأخرى في الطبقة 7 مثل البرمجة النصية عبر المواقع ، والمصادقة المعطلة ، والتزوير عبر المواقع ، وعرض البيانات ، وما إلى ذلك ، إما يمكنك استخدام الاستضافة الذاتية مثل Mod Security أو المستندة إلى السحابة على النحو التالي.

    حقن SQL وأطر PHP الحديثة

    يعد إدخال SQL أمرًا شائعًا وسهلًا ومحبطًا وخطيرًا للغاية لدرجة أن جميع أطر عمل الويب PHP الحديثة تأتي مدمجة مع الإجراءات المضادة. في WordPress ، على سبيل المثال ، لدينا وظيفة $ wpdb-> Prepar () ، بينما إذا كنت تستخدم إطار عمل MVC ، فإنه يقوم بكل الأعمال القذرة نيابة عنك ولا يتعين عليك حتى التفكير في منع حقن SQL. إنه أمر مزعج بعض الشيء أنه في WordPress عليك إعداد البيانات بشكل صريح ، ولكن مهلا ، إنه WordPress الذي نتحدث عنه. 🙂

    على أي حال ، وجهة نظري هي أن الجيل الحديث من مطوري الويب ليسوا مضطرين للتفكير في حقن SQL ، ونتيجة لذلك ، فهم ليسوا على دراية بهذا الاحتمال. على هذا النحو ، حتى إذا تركوا بابًا خلفيًا واحدًا مفتوحًا في تطبيقهم (ربما يكون معلمة استعلام $ _GET والعادات القديمة لإطلاق استعلام قذر) ، يمكن أن تكون النتائج كارثية. لذلك من الأفضل دائمًا أن تأخذ الوقت الكافي للتعمق أكثر في الأساسات.

    استنتاج

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