حقن SQL لتجاوز mysql_real_escape_string(): تحليل الثغرات الأمنية

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

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

ابدأ الدورة

«أنقذوني! دالة mysql_real_escape_string() لا تعمل!»



إذا سبق لك أن بحثت في Google عن «SQL injection that gets around mysql_real_escape_string()»، فأنت لست وحدك. هذا السؤال على Stack Overflow حصد عشرات الآلاف من المشاهدات وأصبح من كلاسيكيات أمن الويب. كان يبدو أنك تأخذ mysql_real_escape_string() وستكون محميًا. لكن لا. يجد المخترقون ثغرات، ويجد المطورون شيبًا في شعرهم.



في هذه المقالة، سنحلل بالضبط كيف يمكن لحقن SQL تجاوز تهريب mysql_real_escape_string() في PHP. سترى أمثلة حقيقية على الكود، وستفهم لماذا لم يعد النهج «القديم الجيد» يعمل، وستتعلم كيف تحمي نفسك حقًا. هيا بنا!



لماذا mysql_real_escape_string() ليست حلاً سحريًا؟



بدايةً - القليل من التاريخ. ظهرت الدالة mysql_real_escape_string() في عصر PHP 4 و5، عندما كان الجميع يستخدمون إضافة mysql_*. تقوم بتهريب الأحرف الخاصة مثل علامات الاقتباس والشرطة المائلة العكسية وأحرف التحكم. لكن المشكلة أنها تعمل فقط في سياق ترميز واحد.



إذا كان ترميز العميل والخادم غير متطابقين - تبدأ الفوضى. وإذا كنت تستخدم ترميزات متعددة البايت (مثل GBK أو SJIS) - فقد تصبح الدالة أسوأ عدو لك.



المثال الكلاسيكي: هجوم متعدد البايت



تخيل أن موقعك يستخدم الترميز GBK (صيني)، وأنت ترسل السلسلة النصية:



$_POST['name'] = "0xbf27"; // هل هو ' مهرب أم مجرد '؟


في GBK، الرمز 0xbf27 هو حرف صيني صالح. لكن إذا «رأت» mysql_real_escape_string() الرمز 0x27 (الفاصلة العليا)، فستقوم بتهريبه بشرطة مائلة عكسية: 0xbf5c27. المشكلة أن 0xbf5c هو أيضًا رمز صالح في GBK! والنتيجة أن الفاصلة العليا 0x27 تبقى غير مهربة، ويمكن للمخترق إدراج كود SQL الخاص به.



// كود ضعيف$name = mysql_real_escape_string($_POST['name']);$query = "SELECT * FROM users WHERE name = '$name'";

// إذا تم إدخال: 0xbf27// ستعيد الدالة: 0xbf5c27// في GBK هذا: حرف صيني + فاصلة عليا// يصبح الاستعلام: SELECT * FROM users WHERE name = 'حرف_صيني' OR 1=1 -- '


ها هي! تم الحقن بنجاح. وهذا ليس مجرد نظرية - تم العثور على مثل هذه الثغرات في مشاريع حقيقية.



الثغرات النموذجية عند استخدام mysql_real_escape_string()



دعنا نذكر الأخطاء الأكثر شيوعًا التي تسمح بتجاوز التهريب:



  • الترميز الخاطئ - كما في المثال أعلاه. إذا كان الخادم يعتقد أن البيانات بصيغة UTF-8، بينما يرسلها العميل بصيغة GBK، فإن التهريب ينهار.
  • استخدام الحقول الرقمية بدون علامات اقتباس - إذا قمت بإدراج رقم مباشرة، فلن يعمل التهريب. مثال: SELECT * FROM users WHERE id = $id - ويكتب المخترق 1 OR 1=1.
  • استعلامات LIKE - لا يعالج التهريب الرمزين % و _. يمكن تنفيذ حقن SQL أعمى عبر الأنماط.
  • التهريب المتكرر - إذا قمت باستدعاء الدالة مرتين، تتضاعف الشرطة المائلة العكسية وتختفي الحماية.


مثال: هجوم على حقل رقمي



// كود ضعيف$id = mysql_real_escape_string($_GET['id']);$query = "SELECT * FROM products WHERE id = $id"; // لا حاجة لعلامات الاقتباس!

// المخترق يدخل: 1 UNION SELECT username, password FROM users// يصبح الاستعلام: SELECT * FROM products WHERE id = 1 UNION SELECT username, password FROM users


التهريب هنا عديم الفائدة - لا توجد علامات اقتباس لتهريبها. المخترق ببساطة يدخل SQL الخاص به مباشرة.



طرق الحماية الحديثة (التي تعمل)



كفى قصص رعب - دعنا ننتقل إلى الحلول. إذا كنت تكتب بلغة PHP وتريد نسيان حقن SQL، إليك قائمة المهام الخاصة بك:



1. استخدم PDO أو MySQLi مع prepared statements



هذا

المدونات

توصيات الكتب