php - كيف يمكنني منع حقن سكل في فب؟


إذا تم إدخال إدخال المستخدم دون تعديل في استعلام سكل، يصبح التطبيق عرضة لحقن سكل ، كما هو الحال في المثال التالي:

$unsafe_variable = $_POST['user_input']; 

mysql_query("INSERT INTO `table` (`column`) VALUES ('$unsafe_variable')");

وذلك لأن المستخدم يمكن إدخال شيء مثل value'); DROP TABLE table;-- value'); DROP TABLE table;-- ، ويصبح الاستعلام:

INSERT INTO `table` (`column`) VALUES('value'); DROP TABLE table;--')

ما الذي يمكن عمله لمنع حدوث ذلك؟




Answers


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

لديك أساسا خياران لتحقيق ذلك:

  1. استخدام بدو (لأي برنامج تشغيل قاعدة بيانات معتمدة):

    $stmt = $pdo->prepare('SELECT * FROM employees WHERE name = :name');
    
    $stmt->execute(array('name' => $name));
    
    foreach ($stmt as $row) {
        // do something with $row
    }
  2. استخدام ميسكلي (ل ميسكل):

    $stmt = $dbConnection->prepare('SELECT * FROM employees WHERE name = ?');
    $stmt->bind_param('s', $name);
    
    $stmt->execute();
    
    $result = $stmt->get_result();
    while ($row = $result->fetch_assoc()) {
        // do something with $row
    }

إذا كنت متصلا بقاعدة بيانات بخلاف ميسكل، فهناك خيار ثاني خاص بالسائق يمكنك الرجوع إليه (مثل pg_prepare() و pg_execute() ل بوستغريزل). بدو هو الخيار العالمي.

قم بإعداد الاتصال بشكل صحيح

لاحظ أنه عند استخدام PDO للوصول إلى قاعدة بيانات ميسكل لا يتم استخدام البيانات التي تم إعدادها بشكل افتراضي . لإصلاح هذا لديك لتعطيل محاكاة البيانات المعدة. مثال على إنشاء اتصال باستخدام بدو هو:

$dbConnection = new PDO('mysql:dbname=dbtest;host=127.0.0.1;charset=utf8', 'user', 'pass');

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

في المثال أعلاه وضع الخطأ ليست ضرورية للغاية، ولكن ينصح لإضافته . بهذه الطريقة لن يتوقف البرنامج النصي مع Fatal Error عندما يذهب شيء خاطئ. وأنه يعطي المطور الفرصة catch أي خطأ (ق) التي throw ن كما PDOException s.

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

على الرغم من أنه يمكنك تعيين مجموعة charset في خيارات منشئ، فمن المهم أن نلاحظ أن الإصدارات "القديمة" من فب (<5.3.6) تجاهل بصمت المعلمة تشارسيت في دسن.

تفسير

ما يحدث هو أن عبارة سكل التي تمرير prepare وتحليلها من قبل خادم قاعدة البيانات. من خلال تحديد معلمات (إما معلمة أو مسماة مثل :name في المثال أعلاه) تخبر مشغل قاعدة البيانات حيث تريد التصفية. ثم عند استدعاء execute ، يتم الجمع بين البيان أعدت مع قيم المعلمة التي تحددها.

الشيء المهم هنا هو أن قيم المعلمة يتم دمجها مع العبارة المترجمة، وليس سلسلة سكل. يعمل حقن سكل عن طريق خداع النص البرمجي إلى تضمين السلاسل الخبيثة عند إنشاء سكل لإرسالها إلى قاعدة البيانات. لذلك عن طريق إرسال سكل الفعلي بشكل منفصل عن المعلمات، يمكنك الحد من خطر تنتهي مع شيء كنت لا تنوي. سيتم التعامل مع أي معلمات ترسلها عند استخدام عبارة محضرة فقط كسلاسل (على الرغم من أن محرك قاعدة البيانات قد تفعل بعض التحسين حتى المعلمات قد ينتهي بالأرقام أيضا، بطبيعة الحال). في المثال أعلاه، إذا كان المتغير $name نيم يحتوي على 'Sarah'; DELETE FROM employees 'Sarah'; DELETE FROM employees النتيجة ستكون مجرد البحث عن سلسلة "'Sarah'; DELETE FROM employees" ، وأنك لن ينتهي مع جدول فارغ .

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

أوه، وبما أنك سألت عن كيفية القيام بذلك لإدراج، وهنا مثال (باستخدام بدو):

$preparedStatement = $db->prepare('INSERT INTO table (column) VALUES (:column)');

$preparedStatement->execute(array('column' => $unsafeValue));

هل يمكن استخدام البيانات المعدة للاستعلامات الديناميكية؟

على الرغم من أنه لا يزال بإمكانك استخدام عبارات تم إعدادها لمعلمات الاستعلام، لا يمكن أن تكون بنية الاستعلام الديناميكي نفسه بارامتريزد ولا يمكن تمييز بارامتريزد بعض ميزات الاستعلام.

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

// Value whitelist
// $dir can only be 'DESC' otherwise it will be 'ASC'
if (empty($dir) || $dir !== 'DESC') {
   $dir = 'ASC';
}



تحذير: رمز عينة السؤال يستخدم تمديد mysql ، الذي تم إهماله في فب 5.5.0 وإزالتها تماما في فب 7.0.0.

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

كنت قد حصلت على خيارين - الهروب من الأحرف الخاصة في غير unsafe_variable الخاص بك، أو باستخدام الاستعلام المعلمة. كلاهما سوف يحميك من حقن سكل. يعتبر الاستعلام باراميريزد أفضل الممارسات ولكن سوف تتطلب تغيير إلى تمديد ميسكل أحدث في فب قبل أن تتمكن من استخدامه.

سنقوم بتغطية سلسلة تأثير أقل هروب واحد أولا.

//Connect

$unsafe_variable = $_POST["user-input"];
$safe_variable = mysql_real_escape_string($unsafe_variable);

mysql_query("INSERT INTO table (column) VALUES ('" . $safe_variable . "')");

//Disconnect

انظر أيضا، تفاصيل وظيفة mysql_real_escape_string .

لاستخدام الاستعلام المعلمة، تحتاج إلى استخدام ميسكلي بدلا من وظائف الخلية . لإعادة كتابة المثال، سنحتاج إلى شيء مثل ما يلي.

<?php
    $mysqli = new mysqli("server", "username", "password", "database_name");

    // TODO - Check that connection was successful.

    $unsafe_variable = $_POST["user-input"];

    $stmt = $mysqli->prepare("INSERT INTO table (column) VALUES (?)");

    // TODO check that $stmt creation succeeded

    // "s" means the database expects a string
    $stmt->bind_param("s", $unsafe_variable);

    $stmt->execute();

    $stmt->close();

    $mysqli->close();
?>

المهمة الرئيسية التي تريد أن تقرأ على سيكون هناك mysqli::prepare .

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

يرجى ملاحظة أن القضية التي سألت عنها هي بسيطة إلى حد ما وأن الحالات الأكثر تعقيدا قد تتطلب نهجا أكثر تعقيدا. خاصه:

  • إذا كنت ترغب في تغيير بنية سكل استنادا إلى إدخال المستخدم، الاستعلامات المعلمة لن تساعد، ولا يتم تغطية الهروب المطلوبة من قبل mysql_real_escape_string . في هذا النوع من الحالات، سيكون من الأفضل لك تمرير إدخال المستخدم من خلال القائمة البيضاء لضمان السماح للقيم "الآمنة" فقط من خلال.
  • إذا كنت تستخدم الأعداد الصحيحة من إدخال المستخدم في حالة واتخاذ نهج mysql_real_escape_string ، سوف تعاني من المشكلة التي وصفها متعدد الحدود في التعليقات أدناه. هذه الحالة هي أكثر صعوبة لأن الأعداد الصحيحة لن تكون محاطة يقتبس، حتى تتمكن من التعامل مع من خلال التحقق من صحة أن إدخال المستخدم يحتوي على أرقام فقط.
  • هناك حالات أخرى على الأرجح لست على علم بها. قد تجد هذا هو مورد مفيد على بعض المشاكل أكثر خفية التي يمكن أن تواجهها.



كل إجابة هنا تغطي فقط جزء من المشكلة.
في الواقع، هناك أربعة أجزاء الاستعلام المختلفة التي يمكن أن نضيف إليها بشكل حيوي:

  • سلسلة
  • رقم
  • معرف
  • كلمة بناء جملة.

كما أن البيانات المعدة لا تغطي سوى اثنتين منها

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

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

$orders  = array("name","price","qty"); //field names
$key     = array_search($_GET['sort'],$orders)); // see if we have such a name
$orderby = $orders[$key]; //if not, first one will be set automatically. smart enuf :)
$query   = "SELECT * FROM `table` ORDER BY $orderby"; //value is safe

ومع ذلك، هناك طريقة أخرى لتأمين معرفات - الهروب. طالما كان لديك معرف نقلت، يمكنك الهروب من الخلف في الداخل من خلال مضاعفة لهم.

كخطوة أخرى، يمكننا استعارة فكرة رائعة حقا عن استخدام بعض العناصر النائبة (وكيل لتمثيل القيمة الفعلية في الاستعلام) من العبارات المعدة وابتكار عنصر نائب لنوع آخر - عنصر نائب معرف.

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

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

ومع ذلك، هناك مشكلة مع كلمات بناء جملة سكل (مثل AND DESC و مثل) ولكن القائمة البيضاء تبدو النهج الوحيد في هذه الحالة.

تحديث

على الرغم من أن هناك اتفاق عام على أفضل الممارسات المتعلقة حقن حقن سكل، لا تزال هناك العديد من الممارسات السيئة كذلك. وبعضهم عميق الجذور في عقول مستخدمي فب. على سبيل المثال، في هذه الصفحة نفسها هناك (على الرغم من أنها غير مرئية لمعظم الزائرين) أكثر من 80 إجابات محذوفة - كل ما تمت إزالته من قبل المجتمع بسبب سوء الجودة أو الترويج للممارسات السيئة أو القديمة. والأسوأ من ذلك، فإن بعض الإجابات السيئة لا يتم حذفها بل تزدهر.

على سبيل المثال، هناك (1) هي (2) لا تزال (3) العديد من الإجابات (4) (5) ، بما في ذلك الإجابة الثانية الأكثر أوبفوتد مما يوحي لك سلسلة اليدوية الهروب - نهج عفا عليها الزمن التي ثبت أنها غير آمنة.

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

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

بغض النظر عن ما قال دليل فب للأعمار، *_escape_string بأي حال من الأحوال يجعل البيانات آمنة وأبدا لم يقصد به. بالإضافة إلى كونها عديمة الفائدة لأي جزء سكل غير السلسلة، دليل الهروب هو الخطأ لأنه دليل على عكس الآلية.

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

لذلك، على عكس أي "الهروب"، البيانات المعدة هو التدبير الذي يحمي حقا من حقن سكل (عند الاقتضاء).

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




أوصي باستخدام بدو (فب كائنات البيانات) لتشغيل الاستعلامات سكل المعلمة.

ليس فقط هذا لا يحمي من حقن سكل، فإنه يسرع أيضا الاستفسارات.

وباستخدام بدو بدلا من mysql_ ، mysqli_ ، و pgsql_ وظائف، وجعل التطبيق الخاص بك أكثر من ذلك بقليل المستخرجة من قاعدة البيانات، في نادرة الحدوث الذي لديك للتبديل مقدمي قاعدة البيانات.




استخدام PDO وإعداد الاستعلامات.

( $conn هو كائن PDO )

$stmt = $conn->prepare("INSERT INTO tbl VALUES(:id, :name)");
$stmt->bindValue(':id', $id);
$stmt->bindValue(':name', $name);
$stmt->execute();



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

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

نهجي:

  • إذا كنت تتوقع الإدخال ليكون عدد صحيح تأكد من انها صحيحة حقا . في لغة من نوع متغير مثل فب هذا هو مهم جدا . يمكنك استخدام على سبيل المثال هذا الحل بسيط جدا ولكن قوية: sprintf("SELECT 1,2,3 FROM table WHERE 4 = %u", $input);

  • إذا كنت تتوقع أي شيء آخر من عدد صحيح عرافة ذلك . إذا كنت عرافة ذلك، سوف الهروب تماما كل المدخلات. في C / C ++ هناك وظيفة تسمى mysql_hex_string() ، في فب يمكنك استخدام bin2hex() .

    لا تقلق من أن السلسلة التي تم إبعادها سوف يكون لها حجم 2x من طولها الأصلي لأنه حتى إذا كنت تستخدم mysql_real_escape_string ، فب لديه لتخصيص نفس القدرة ((2*input_length)+1) ، وهو نفسه.

  • وغالبا ما تستخدم هذه الطريقة عرافة عند نقل البيانات الثنائية، ولكن لا أرى أي سبب لعدم استخدامها على كافة البيانات لمنع هجمات حقن سكل. لاحظ أنه يجب عليك مسبقا إعداد البيانات باستخدام 0x أو استخدام وظيفة ميسكل UNHEX بدلا من ذلك.

لذلك، على سبيل المثال، الاستعلام:

SELECT password FROM users WHERE name = 'root'

سيصبح:

SELECT password FROM users WHERE name = 0x726f6f74

أو

SELECT password FROM users WHERE name = UNHEX('726f6f74')

عرافة هو الهروب الكمال. لا توجد طريقة لحقن.

الفرق بين وظيفة أونهكس والبادئة 0x

كان هناك بعض النقاش في التعليقات، لذلك أريد أخيرا أن أوضح. وهذان النهجان متشابهان جدا، لكنهما مختلفان قليلا في بعض النواحي:

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

يعمل أونهكس () على أي عمود؛ لم يكن لديك ما يدعو للقلق سلسلة فارغة.

وغالبا ما تستخدم أساليب عرافة كهجوم

لاحظ أن هذا الأسلوب عرافة غالبا ما تستخدم هجوم حقن سكل حيث الأعداد الصحيحة هي تماما مثل سلاسل وهرب فقط مع mysql_real_escape_string . ثم يمكنك تجنب استخدام يقتبس.

على سبيل المثال، إذا كنت تفعل شيئا من هذا القبيل:

"SELECT title FROM article WHERE id = " . mysql_real_escape_string($_GET["id"])

هجوم يمكن أن يضخ لك بسهولة جدا. ضع في اعتبارك رمز الحقن التالي الذي تم إرجاعه من النص البرمجي:

سيليكت ... وير إد = -1 ونيون كل حدد table_name من information_schema.tables

والآن مجرد استخراج هيكل الجدول:

سيليكت ... وير إد = -1 ونيون آل حدد column_name from information_schema.column حيث table_name = 0x61727469636c65

وبعد ذلك فقط حدد ما تريد تلك البيانات. أليس باردا؟

ولكن إذا كان المبرمج لموقع الحقن عرافة فإنه لا يمكن أن يكون الحقن لأن الاستعلام سوف تبدو مثل هذا: SELECT ... WHERE id = UNHEX('2d312075...3635')




مهم

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

هناك مكتبات مثل Aura.Sql و إيسيدب التي تسمح للمطورين لاستخدام البيانات استعداد أسهل. لمعرفة المزيد حول لماذا البيانات استعداد أفضل في وقف حقن سكل ، راجع هذا mysql_real_escape_string() تجاوز وثغرات الضعف سكل حقن إنكود في ووردبريس مؤخرا .

منع الحقن - mysql_real_escape_string ()

فب لديه وظيفة مصنوعة خصيصا لمنع هذه الهجمات. كل ما عليك القيام به هو استخدام الفم من وظيفة، mysql_real_escape_string .

mysql_real_escape_string يأخذ سلسلة التي سيتم استخدامها في استعلام الخلية وإعادة نفس السلسلة مع جميع محاولات حقن سكل هرب بأمان. في الأساس، فإنه سيتم استبدال تلك الاقتباسات مزعجة (') يمكن للمستخدم إدخال مع بديل ميسكل آمنة، اقتباس هرب'.

ملاحظة: يجب أن تكون متصلا بقاعدة البيانات لاستخدام هذه الوظيفة!

// الاتصال ب ميسكل

$name_bad = "' OR 1'"; 

$name_bad = mysql_real_escape_string($name_bad);

$query_bad = "SELECT * FROM customers WHERE username = '$name_bad'";
echo "Escaped Bad Injection: <br />" . $query_bad . "<br />";


$name_evil = "'; DELETE FROM customers WHERE 1 or username = '"; 

$name_evil = mysql_real_escape_string($name_evil);

$query_evil = "SELECT * FROM customers WHERE username = '$name_evil'";
echo "Escaped Evil Injection: <br />" . $query_evil;

يمكنك العثور على مزيد من التفاصيل في الخلية - منع حقن سكل .




تحذير الأمان : هذه الإجابة لا تتماشى مع أفضل الممارسات الأمنية. الهروب غير كافية لمنع حقن سكل ، واستخدام البيانات المعدة بدلا من ذلك. استخدم الإستراتيجية الموضحة أدناه على مسؤوليتك الخاصة. (كما تمت إزالة mysql_real_escape_string() في فب 7.)

هل يمكن أن تفعل شيئا أساسيا مثل هذا:

$safe_variable = mysql_real_escape_string($_POST["user-input"]);
mysql_query("INSERT INTO table (column) VALUES ('" . $safe_variable . "')");

وهذا لن يحل كل مشكلة، ولكنها نقطة انطلاق جيدة جدا. لقد تركت عناصر واضحة مثل التحقق من وجود المتغير، شكل (أرقام، أحرف، الخ).




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




الاستعلام المعلمة والتحقق من صحة المدخلات هو الطريق للذهاب. هناك العديد من السيناريوهات التي قد يحدث فيها حقن سكل، على الرغم من استخدام mysql_real_escape_string() .

هذه الأمثلة عرضة لحقن سكل:

$offset = isset($_GET['o']) ? $_GET['o'] : 0;
$offset = mysql_real_escape_string($offset);
RunQuery("SELECT userid, username FROM sql_injection_test LIMIT $offset, 10");

أو

$order = isset($_GET['o']) ? $_GET['o'] : 'userid';
$order = mysql_real_escape_string($order);
RunQuery("SELECT userid, username FROM sql_injection_test ORDER BY `$order`");

في كلتا الحالتين، لا يمكنك استخدام ' لحماية التغليف.

المصدر : حقن سكل غير متوقع (عندما الهروب ليست كافية)




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

اعتماد نمط مفك وإطار مثل كاكيفب أو كودينيتر هو على الارجح الطريق الصحيح للذهاب: المهام المشتركة مثل إنشاء استعلامات قاعدة بيانات آمنة تم حلها وتنفيذها مركزيا في مثل هذه الأطر. أنها تساعدك على تنظيم تطبيق الويب الخاص بك بطريقة معقولة وتجعلك تفكر أكثر حول تحميل وحفظ الكائنات من حول بناء بشكل آمن استعلامات سكل واحدة.




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

ما هو حقن سكل وكيفية الوقاية

دليل فب لحقن سكل

شرح مايكروسوفت من حقن سكل والوقاية في فب

وبعض أخرى مثل منع حقن سكل مع الخلية و فب

الآن، لماذا تحتاج إلى منع الاستعلام الخاص بك من حقن سكل؟

أود أن أخبركم: لماذا نحاول منع حقن سكل مع مثال قصير أدناه:

الاستعلام عن مباراة مصادقة تسجيل الدخول:

$query="select * from users where email='".$_POST['email']."' and password='".$_POST['password']."' ";

الآن، إذا كان شخص (هاكر) يضع

$_POST['email']= admin@emali.com' OR '1=1

وكلمة المرور أي شيء ....

سيتم تحليل الاستعلام في النظام فقط تصل:

$query="select * from users where email='admin@emali.com' OR '1=1';

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




I يؤيدون الإجراءات المخزنة ( تمت زيارتها الخلية المخزنة دعم الإجراءات منذ 5.0 ) من الناحية الأمنية - من مزايا و-

  1. معظم قواعد البيانات (بما في ذلك الخلية ) تمكين وصول المستخدم إلى أن يقتصر على تنفيذ الإجراءات المخزنة. التحكم في الوصول الأمن الحبيبات الدقيقة مفيدة لمنع تصاعد الهجمات الامتيازات. وهذا ما يمنع التطبيقات للخطر من أن تكون قادرة على تشغيل SQL مباشرة من قاعدة البيانات.
  2. أنها مجردة الاستعلام SQL الخام من التطبيق بحيث معلومات أقل من بنية قاعدة البيانات متاحة للتطبيق. وهذا يجعل من الصعب على الناس أن يفهموا البنية الأساسية لقواعد البيانات وتصميم الهجمات مناسبة.
  3. أنها تقبل المعلمات فقط، وبالتالي فإن مزايا استعلامات بمعلمات هناك. بالطبع - IMO لا تزال تحتاج إلى تطهير المدخلات الخاصة بك - وخاصة إذا كنت تستخدم SQL الحيوي داخل الإجراء المخزن.

مساوئ هي -

  1. انهم (الإجراءات المخزنة) هي صعبة للحفاظ على وتميل إلى مضاعفة بسرعة كبيرة. وهذا يجعل إدارتها قضية.
  2. فهي ليست مناسبة جدا للاستعلامات ديناميكية - إذا كانت مبنية على تقبل قانون الديناميكي كمعلمات ثم يبطل الكثير من المزايا.



اعتقد انه اذا كان هناك من يريد استخدام PHP و MySQL أو بعض خادم قاعدة بيانات أخرى:

  1. التفكير في تعلم PDO (كائنات PHP البيانات) - هو عبارة عن طبقة الوصول إلى قاعدة البيانات وتوفير طريقة موحدة للوصول إلى قواعد بيانات متعددة.
  2. التفكير في تعلم MySQLi
  3. استخدام وظائف PHP الأم مثل: strip_tags ، mysql_real_escape_string أو إذا رقمية متغير، فقط (int)$foo. قراءة المزيد عن نوع من المتغيرات في PHP هنا . إذا كنت تستخدم المكتبات مثل شركة تنمية نفط عمان أو MySQLi، دائما استخدام شركة تنمية نفط عمان :: اقتباس () و mysqli_real_escape_string () .

مكتبات الأمثلة على ذلك:

---- PDO

----- لا النائبة - مهيأة للحقن SQL! انها سيئة

$request = $pdoConnection->("INSERT INTO parents (name, addr, city) values ($name, $addr, $city)");

----- النائبة اسمه

$request = $pdoConnection->("INSERT INTO parents (name, addr, city) values (?, ?, ?);

----- النائبة مسمى

$request = $pdoConnection->("INSERT INTO parents (name, addr, city) value (:name, :addr, :city)");

--- MySQLi

$request = $mysqliConnection->prepare('
       SELECT * FROM trainers
       WHERE name = ?
       AND email = ?
       AND last_login > ?');

    $query->bind_param('first_param', 'second_param', $mail, time() - 3600);
    $query->execute();

PS :

شركة تنمية نفط عمان يفوز في هذه المعركة بكل سهولة. مع دعم لمدة اثني عشر برامج تشغيل قاعدة البيانات المختلفة والمعلمات المسماة، لا يمكننا تجاهل فقدان الأداء صغيرة، والتعود على API لها. من الناحية الأمنية، وكلاهما آمنا طالما المطور يستخدم بالطريقة التي من المفترض أن يتم استخدامها

ولكن في حين أن كلا PDO وMySQLi هي سريعة جدا، MySQLi يؤدي معنويا أسرع في المعايير - ~ 2.5٪ للبيانات غير مستعدة، و~ 6.5٪ للاستعداد منها.

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




اكتب يلقي إن أمكن المعلمات الخاصة بك. ولكنها تعمل فقط على أنواع بسيطة مثل كثافة العمليات، منطقي وتعويم.

$unsafe_variable = $_POST['user_id'];

$safe_variable = (int)$unsafe_variable ;

mysql_query("INSERT INTO table (column) VALUES ('" . $safe_variable . "')");



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

أيضا يمكنك 'إعداد' حججك قبل إعداد الاستعلام الخاص بك بحيث يمكنك بناء الاستفسارات ديناميكية وفي نهاية دينا كامل الاستعلام البيانات المعدة. قاعدة بيانات DALMP طبقة تجريد عن الخلية باستخدام PHP.




باستخدام هذه الوظيفة PHP mysql_escape_string()يمكنك الحصول على الوقاية جيد بطريقة سريعة.

فمثلا:

SELECT * FROM users WHERE name = '".mysql_escape_string($name_from_html_form)."'

mysql_escape_string - يهرب سلسلة لاستخدامها في mysql_query

لمزيد من الوقاية يمكنك إضافة في نهاية ...

wHERE 1=1   or  LIMIT 1

وأخيرا تحصل عليه:

SELECT * FROM users WHERE name = '".mysql_escape_string($name_from_html_form)."' LIMIT 1



بالنسبة لأولئك غير متأكد من كيفية استخدام شركة تنمية نفط عمان (قادمة من mysql_وظائف)، ولقد تقدمت المجمع PDO جدا وبسيطة جدا وهذا هو ملف واحد. كان موجودا لاظهار كم هو سهل أن تفعل كل الأشياء المشتركة تطبيقات تحتاج إلى القيام به. يعمل مع كيو، الخلية، وسكليتي.

في الأساس، وقراءتها أثناء قراءة الدليل لمعرفة كيفية وضع وظائف شركة تنمية نفط عمان لاستخدامها في الحياة الحقيقية لجعلها بسيطة لتخزين واسترجاع القيم في شكل أنت تريد.

أريد عمود واحد

$count = DB::column('SELECT COUNT(*) FROM `user`);

أريد مجموعة (الرئيسية => قيمة) نتائج (أي لصنع selectbox)

$pairs = DB::pairs('SELECT `id`, `username` FROM `user`);

أريد نتيجة صف واحد

$user = DB::row('SELECT * FROM `user` WHERE `id` = ?', array($user_id));

أريد مجموعة من النتائج

$banned_users = DB::fetch('SELECT * FROM `user` WHERE `banned` = ?', array(TRUE));



هناك عدد قليل من المبادئ التوجيهية للهروب أحرف خاصة في عبارات SQL.

لا تستخدم الخلية ، تم إهمال هذا التمديد، استخدم MySQLi أو شركة تنمية نفط عمان .

MySQLi

للهروب من أحرف خاصة يدويا في سلسلة يمكنك استخدام mysqli_real_escape_string وظيفة. فإن وظيفة لا تعمل بشكل صحيح ما لم يتم تعيين مجموعة الأحرف الصحيحة مع mysqli_set_charset .

مثال:

$mysqli = new mysqli( 'host', 'user', 'password', 'database' );
$mysqli->set_charset( 'charset');

$string = $mysqli->real_escape_string( $string );
$mysqli->query( "INSERT INTO table (column) VALUES ('$string')" );

للهروب التلقائي من القيم مع بيانات معدة، واستخدام mysqli_prepare ، و mysqli_stmt_bind_param حيث يجب توفير أنواع للمتغيرات ربط المقابلة لتحويل المناسبة:

مثال:

$stmt = $mysqli->prepare( "INSERT INTO table ( column1, column2 ) VALUES (?,?)" );

$stmt->bind_param( "is", $integer, $string );

$stmt->execute();

لا يهم إذا كنت تستخدم عبارات المعدة أو mysqli_real_escape_string، لديك دائما لمعرفة نوع البيانات المدخلة كنت تعمل مع.

حتى إذا كنت تستخدم بيان معد سلفا، يجب عليك تحديد أنواع المتغيرات من أجل وظيفة mysqli_stmt_bind_param.

واستخدام mysqli_real_escape_string هو، كما يقول اسمها، والهروب الأحرف الخاصة في سلسلة، لذلك لن يجعل الأعداد الصحيحة آمنة. والغرض من هذه الوظيفة هو منع كسر السلاسل في بيانات SQL، والأضرار التي لحقت قاعدة البيانات التي يمكن أن تسببها. mysqli_real_escape_string هي وظيفة مفيدة عندما تستخدم بشكل صحيح، وخصوصا عندما يقترن sprintf.

مثال:

$string = "x' OR name LIKE '%John%";
$integer = '5 OR id != 0';

$query = sprintf( "SELECT id, email, pass, name FROM members WHERE email ='%s' AND id = %d", $mysqli->real_escape_string( $string ), $integer );

echo $query;
// SELECT id, email, pass, name FROM members WHERE email ='x\' OR name LIKE \'%John%' AND id = 5

$integer = '99999999999999999999';
$query = sprintf( "SELECT id, email, pass, name FROM members WHERE email ='%s' AND id = %d", $mysqli->real_escape_string( $string ), $integer );

echo $query;
// SELECT id, email, pass, name FROM members WHERE email ='x\' OR name LIKE \'%John%' AND id = 2147483647



يمكنني استخدام ثلاث طرق مختلفة لمنع تطبيق الويب الخاص بي من كونها عرضة للحقن SQL.

  1. استخدام mysql_real_escape_string()، وهي وظيفة محددة مسبقا في PHP ، وهذا الرمز إضافة إلى الخطوط المائلة العكسية الأحرف التالية: \x00، \n، \r، \، '، "و \x1a. تمرير قيم الإدخال كمعلمات لتقليل فرصة لحقن SQL.
  2. الطريقة الأكثر تقدما في استخدام PDOs.

آمل أن يكون هذا سيساعدك.

النظر في الاستعلام التالي:

$iId = mysql_real_escape_string("1 OR 1=1"); $sSql = "SELECT * FROM table WHERE id = $iId";

سوف mysql_real_escape_string () لا تحمي هنا. إذا كنت تستخدم علامات الاقتباس المفردة ( '') حول المتغيرات الخاصة بك داخل الاستعلام الخاص بك هو ما يحمي لكم ضد هذا. هنا هو الحل أدناه للحصول على هذا:

$iId = (int) mysql_real_escape_string("1 OR 1=1"); $sSql = "SELECT * FROM table WHERE id = $iId";

هذا السؤال له بعض الإجابات جيدة حول هذا الموضوع.

أقترح، وذلك باستخدام PDO هو الخيار الأفضل.

تصحيح:

mysql_real_escape_string()تم إهمال اعتبارا من PHP 5.5.0. استخدام إما mysqli أو شركة تنمية نفط عمان.

بديلا لmysql_real_escape_string () هو

string mysqli_real_escape_string ( mysqli $link , string $escapestr )

مثال:

$iId = $mysqli->real_escape_string("1 OR 1=1");
$mysqli->query("SELECT * FROM table WHERE id = $iId");



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

 GRANT SELECT, INSERT, DELETE ON database TO username@'localhost' IDENTIFIED BY 'password';

وهذا تقييد المستخدم للحصول على محصورة فقط مع الاستعلام المحدد فقط. إزالة الإذن حذف، وأنها لن تحصل على حذف ذلك البيانات من الاستعلام اطلق من الصفحة بي. الشيء الثاني القيام به هو طرد الامتيازات بحيث ينعش الخلية الأذونات والتحديثات.

FLUSH PRIVILEGES; 

مزيد من المعلومات حول تدفق .

لمعرفة الامتيازات الحالية للمستخدم إطلاق الاستعلام التالي.

select * from mysql.user where User='username';

معرفة المزيد عن منحة .




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

الآن، وجهة نظرنا هي منع التهديدات الأمنية مثل هجمات حقن SQL، فإن السؤال يسأل (كيف لمنع هجوم حقن SQL باستخدام PHP)، تكون أكثر واقعية، وتصفية البيانات أو مسح البيانات المدخلة هو الحال عند استخدام بيانات المستخدم المدخلات داخل مثل الاستعلام، وذلك باستخدام PHP أو أي لغة برمجة أخرى ليست هي القضية، أو على النحو الموصى به من قبل المزيد من الناس على استخدام التكنولوجيا الحديثة مثل بيان محضرة أو أي أدوات أخرى يدعم حاليا منع حقن SQL، يعتبرون أن هذه الأدوات لم يعد متوفر؟ كيف يمكنك تأمين التطبيق الخاص بك؟

توجهي ضد حقن SQL هو: مسح بيانات المستخدم الإدخال قبل إرساله إلى قاعدة البيانات (قبل استخدامه داخل أي استعلام).

تصفية البيانات ل(تحويل البيانات غير آمنة لبيانات آمنة) نعتبر أن شركة تنمية نفط عمان و MySQLi غير متوفر، كيف يمكنك الحصول على طلبك؟ هل تجبرني على استخدامها؟ ماذا عن لغات أخرى غير PHP؟ أنا أفضل أن تقدم أفكارا عامة لأنها يمكن أن تستخدم لحدود أوسع ليس فقط للغة معينة.

  1. المستخدم SQL (الحد امتياز المستخدم): عمليات SQL الأكثر شيوعا هي (SELECT، UPDATE، INSERT)، ثم، لماذا إعطاء امتياز UPDATE إلى المستخدم الذي لا يتطلب ذلك؟ على سبيل المثال تسجيل الدخول، وصفحات البحث تستخدم فقط SELECT، ثم، لماذا استخدام المستخدمين DB في هذه الصفحات مع امتيازات عالية؟ القاعدة: لا تخلق مستخدم قاعدة بيانات واحدة لجميع الامتيازات، لجميع عمليات SQL، يمكنك إنشاء مخطط لديك مثل (deluser، selectuser، updateuser)، وأسماء المستخدمين لسهولة الاستخدام.

نرى مبدأ الامتيازات الأقل

  1. تصفية البيانات: قبل بناء أي إدخال المستخدم الاستعلام يجب التحقق من صحة وتصفيتها، للمبرمجين، من المهم تحديد بعض خصائص كل متغيرات المستخدم المدخلات: نوع البيانات، ونمط البيانات، وطول البيانات . حقل رقم بين (x و y) يجب التحقق من صحة بالضبط باستخدام قاعدة بالضبط، لحقل الذي هو سلسلة (النص): نمط هو الحال، على سبيل المثال، يجب أن اسم المستخدم يحتوي فقط بعض الأحرف يتيح القول [أ زا-Z0-9_-.] طول يتراوح بين (س و ن) حيث x و n (أعداد صحيحة، س <= ن). القاعدة: إنشاء فلاتر الدقيق وقواعد التحقق من صحة وأفضل الممارسات بالنسبة لي.

  2. استخدام أدوات أخرى: هنا، وسوف نتفق أيضا مع لكم ان بيان معد (الاستعلام parametrized) والإجراءات المخزنة، وعيوب هنا هي هذه الطرق يتطلب مهارات متقدمة التي لا وجود لها بالنسبة لمعظم المستخدمين، فإن الفكرة الأساسية هنا هي أن نميز بين الاستعلام SQL والبيانات التي يتم استخدامها في الداخل، كلا النهجين يمكن استخدامها حتى مع بيانات غير آمنة، وذلك لأن البيانات المستخدم الإدخال هنا لا تضيف شيئا إلى الاستعلام الأصلي مثل (أي أو س س =). لمزيد من المعلومات، يرجى قراءة OWASP SQL حقن منع الغش ورقة .

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

وأخيرا، دعونا نعتبر أن المستخدم يرسل هذا النص أدناه بدلا من إدخال اسم المستخدم له:

[1] UNION SELECT IF(SUBSTRING(Password,1,1)='2',BENCHMARK(100000,SHA1(1)),0) User,Password FROM mysql.user WHERE User = 'root'

هذا المدخل يمكن التحقق من وقت مبكر دون أي بيان معد سلفا والإجراءات المخزنة، ولكن لتكون على الجانب الآمن، واستخدامها يبدأ بعد تصفية البيانات المستخدم والتحقق من الصحة.

النقطة الأخيرة هي اكتشاف سلوك غير متوقع مما يتطلب المزيد من الجهد والتعقيد. انها لا ينصح لتطبيقات الويب العادية. سلوك غير متوقع في إدخال المستخدم أعلاه هو SELECT، UNION، IF، فرعية، BENCHMARK، SHA، وجذر مرة واحدة هذه الكلمات اكتشفت، يمكنك تجنب الإدخال.

UPDATE1:

وعلق المستخدم أن هذا المنصب لا طائل منه، OK! هنا هو ما OWASP.ORG المقدمة:

الدفاعات الأولية:

الخيار رقم 1: استخدام البيانات ممهدة (معلمات استعلامات)
الخيار رقم 2: استخدام الإجراءات المخزنة
الخيار رقم 3: الهروب عن الموردة العضو الإدخال

دفاعات إضافية:

فرض أيضا: الامتيازات الأقل
نفذ أيضا: قائمة البيضاء الإدخال التحقق من صحة

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

Update2:

من دليل PHP، PHP: تحضير بيانات - دليل :

حقن الهروب وSQL

سيتم هرب المتغيرات ملزمة تلقائيا من قبل الملقم. إدراج خادم قيمهم هرب في الأماكن المناسبة في القالب بيان قبل التنفيذ. يجب أن تقدم تلميح إلى الخادم لنوع المتغير ملزمة، لإنشاء تحويل المناسب. اطلع على وظيفة mysqli_stmt_bind_param () لمزيد من المعلومات.

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

Update3:

أنا خلقت حالات الاختبار لمعرفة كيفية PDO وMySQLi إرسال الاستعلام إلى خادم MySQL عند استخدام بيان معد سلفا:

شركة تنمية نفط عمان:

$user = "''1''"; //Malicious keyword
$sql = 'SELECT * FROM awa_user WHERE userame =:username';
$sth = $dbh->prepare($sql, array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY));
$sth->execute(array(':username' => $user));

الاستعلام المفتاح:

    189 Query SELECT * FROM awa_user WHERE userame ='\'\'1\'\''
    189 Quit

MySQLi:

$stmt = $mysqli->prepare("SELECT * FROM awa_user WHERE username =?")) {
$stmt->bind_param("s", $user);
$user = "''1''";
$stmt->execute();

الاستعلام المفتاح:

    188 Prepare   SELECT * FROM awa_user WHERE username =?
    188 Execute   SELECT * FROM awa_user WHERE username ='\'\'1\'\''
    188 Quit

من الواضح أن بيان معد سلفا كما الهروب البيانات، ولا شيء آخر.

كما ذكر أيضا في البيان أعلاه The automatic escaping of values within the server is sometimes considered a security feature to prevent SQL injection. The same degree of security can be achieved with non-prepared statements, if input values are escaped correctly، وبالتالي، وهذا يثبت أن التحقق من صحة البيانات مثل intval()فكرة جيدة عن القيم عدد صحيح قبل إرسال أي استفسار، بالإضافة إلى ذلك، منع بيانات المستخدم الخبيثة قبل إرسال الاستعلام النهج الصحيح وصالحة .

يرجى الاطلاع على هذا السؤال لمزيد من التفاصيل: PDO يرسل الاستعلام الخام إلى الخلية في حين يرسل Mysqli الاستعلام المعدة، وكلاهما إنتاج نفس النتيجة

المراجع:

  1. SQL حقن الغش ورقة
  2. حقن SQL
  3. أمن المعلومات
  4. مبادئ الأمن
  5. تأكيد صحة البيانات



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




هناك الكثير من الأجوبة عن PHP و MySQL ، ولكن هنا هو رمز PHP وأوراكل لمنع حقن SQL وكذلك الاستخدام المنتظم للسائقين OCI8:

$conn = oci_connect($username, $password, $connection_string);
$stmt = oci_parse($conn, 'UPDATE table SET field = :xx WHERE ID = 123');
oci_bind_by_name($stmt, ':xx', $fieldval);
oci_execute($stmt);



تحذير: النهج المبين في هذا الجواب لا ينطبق إلا على سيناريوهات محددة للغاية وليست آمنة منذ هجمات حقن SQL لا تعتمد فقط على القدرة على حقن X=Y.

إذا كان المهاجمون يحاولون الإختراق مع النموذج عبر PHP في $_GETمتغير أو مع سلسلة الاستعلام URL، وسوف تكون قادرة على إلقاء القبض عليهم لو انهم غير آمنة.

RewriteCond %{QUERY_STRING} ([0-9]+)=([0-9]+)
RewriteRule ^(.*) ^/track.php

لأن 1=1، 2=2، 1=2، 2=1، 1+1=2، الخ ... هي الأسئلة الشائعة إلى قاعدة بيانات SQL من أحد المهاجمين. ربما أيضا انها تستخدم من قبل العديد من التطبيقات القرصنة.

ولكن يجب أن تكون حذرا، التي يجب أن لا إعادة كتابة استعلام آمن من موقع الويب الخاص بك. رمز أعلاه يعطيك معلومات سرية، لإعادة كتابة أو إعادة توجيه (فهو يعتمد عليك) أن القرصنة محددة سلسلة الاستعلام الحيوية في الصفحة التي سيتم تخزين المهاجم عنوان IP ، أو حتى على الكوكيز، والتاريخ، ومتصفح، أو أي دولة أخرى حساسة المعلومات، حتى تتمكن من التعامل معها في وقت لاحق عن طريق حظر حسابه أو الاتصال بجهات.




عن طريق شركة تنمية نفط عمان و MYSQLi هو ممارسة جيدة لمنع حقن SQL، ولكن إذا كنت تريد حقا للعمل مع وظائف الخلية والاستفسارات، سيكون من الأفضل استخدام

mysql_real_escape_string

$unsafe_variable = mysql_real_escape_string($_POST['user_input']);

وهناك المزيد من القدرة على منع هذا: مثل تحديد - إذا كان إدخال سلسلة، عدد، حرف أو مجموعة، هناك الكثير من وظائف يحمل في ثناياه عوامل للكشف عن هذا. كما أنه سيكون من الأفضل لاستخدام هذه المهام للتأكد من إدخال البيانات.

is_string

$unsafe_variable = (is_string($_POST['user_input']) ? $_POST['user_input'] : '');

is_numeric

$unsafe_variable = (is_numeric($_POST['user_input']) ? $_POST['user_input'] : '');

ومن أفضل بكثير لاستخدام هذه المهام للتأكد من البيانات المدخلة مع mysql_real_escape_string.




هي فكرة جيدة لاستخدام "وجوه العلائقية مخطط" مثل Idiorm :

$user = ORM::for_table('user')
->where_equal('username', 'j4mie')
->find_one();

$user->first_name = 'Jamie';
$user->save();

$tweets = ORM::for_table('tweet')
    ->select('tweet.*')
    ->join('user', array(
        'user.id', '=', 'tweet.user_id'
    ))
    ->where_equal('user.username', 'j4mie')
    ->find_many();

foreach ($tweets as $tweet) {
    echo $tweet->text;
}

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




لقد كتبت هذه الوظيفة قليلا قبل عدة سنوات:

function sqlvprintf($query, $args)
{
    global $DB_LINK;
    $ctr = 0;
    ensureConnection(); // Connect to database if not connected already.
    $values = array();
    foreach ($args as $value)
    {
        if (is_string($value))
        {
            $value = "'" . mysqli_real_escape_string($DB_LINK, $value) . "'";
        }
        else if (is_null($value))
        {
            $value = 'NULL';
        }
        else if (!is_int($value) && !is_float($value))
        {
            die('Only numeric, string, array and NULL arguments allowed in a query. Argument '.($ctr+1).' is not a basic type, it\'s type is '. gettype($value). '.');
        }
        $values[] = $value;
        $ctr++;
    }
    $query = preg_replace_callback(
        '/{(\\d+)}/', 
        function($match) use ($values)
        {
            if (isset($values[$match[1]]))
            {
                return $values[$match[1]];
            }
            else
            {
                return $match[0];
            }
        },
        $query
    );
    return $query;
}

function runEscapedQuery($preparedQuery /*, ...*/)
{
    $params = array_slice(func_get_args(), 1);
    $results = runQuery(sqlvprintf($preparedQuery, $params)); // Run query and fetch results.   
    return $results;
}

وهذا يسمح تشغيل البيانات في أونيلينير C # -ish String.Format مثل:

runEscapedQuery("INSERT INTO Whatever (id, foo, bar) VALUES ({0}, {1}, {2})", $numericVar, $stringVar1, $stringVar2);

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

SECURITY UPDATE: والسابق str_replaceإصدار الحقن يسمح بإضافة {#} ورموز إلى بيانات المستخدم. هذا preg_replace_callbackلا يسبب مشاكل إذا نسخة استبدال يحتوي على هذه الرموز.