في هذا الدرس 6تصفّح المواضيع
تُعد ثغرة حقن قواعد البيانات (SQL Injection — SQLi) من أخطر الثغرات الأمنية في هندسة البرمجيات على الإطلاق؛ وتنشأ عندما يقوم المبرمج ببناء جملة SQL عبر دمج نص المدخلات الواردة من المستخدم مباشرةً داخل نص الاستعلام بدلاً من فصل الكود عن البيانات:
- الخلط الكارثي بين أوامر SQL وبيانات المستخدم: عندما يكتب التطبيق جملة نصية مدمجة مثل
"SELECT * FROM users WHERE email = '" + input + "'"، فإن محلل خادم MySQL لا يستطيع التمييز بين الكود الذي كتبه المبرمج وبين النص الذي أدخله الزائر. - كسر علامات التنصيص: إذا أدخل المهاجم علامة تنصيص مفردة (
') متبوعة بأوامر منطقية مثلORأوUNION SELECTأو رمز التعليق (--)، فإن نص المستخدم يخرج من كونه بيانات نصية ليتحول إلى أوامر SQL فعلية ينفذها الخادم! - المدخلات الرقمية معرضة للحقن أيضاً: حتى بدون علامات تنصيص، فإن دمج معرّف رقمي غير مفحوص مثل
105 OR 1=1داخلWHERE id = ...يحقن شرطاً منطقياً كاملاً.
-- الاستعلام الطبيعي المقصود:
SELECT id, total_usd FROM orders WHERE order_code = 'ORD-500';
-- الاستعلام بعد تشويهه بدمج النصوص المباشر:
SELECT id, total_usd FROM orders WHERE order_code = '' OR 1=1;-- Safe intended lookup for a single customer order:
SELECT id, customer_id, total_usd
FROM orders
WHERE order_code = 'ORD-500';
-- What happens when untrusted input "' OR '1'='1" is concatenated directly:
SELECT id, customer_id, total_usd
FROM orders
WHERE order_code = '' OR '1'='1';
لفهم آلية عمل الحماية الهندسية، دعنا نشرح بالتفصيل الدقيق كيف يحوّل النص الخبيث ' OR 1=1 -- شجرة التحليل النحوي (Syntax Tree) داخل محرك الاستعلام:
- 1. الإغلاق المبكر للنص (
'): تقوم علامة التنصيص الأولى التي يدخلها المهاجم بإغلاق علامة التنصيص التي فتحها المبرمج فيWHERE email = '. - 2. زرع شرط صائب دائماً (
OR 1=1): بما أن المعادلة1=1نتيجتهاTRUEدائماً، يصبح شرطWHEREمحققاً لكل صف في الجدول. - 3. تعطيل بقية الاستعلام بالتعليق (
--أو#): في MySQL، يحوّل الرمز--(شرطتان متبوعتان بمسافة) أو الرمز#كل ما يأتي بعده في نفس السطر (مثل شرط التحقق من كلمة المرور أو حالة الحساب) إلى تعليق مهمل! - 4. تسريب جداول أخرى عبر
UNION SELECT: إذا كان الموقع يعرض نتائج البحث، قد يحقن المهاجمUNION SELECTلدمج بيانات من جداول حساسة أخرى وعرضها على الشاشة.
-- Observe how Boolean logic evaluates inside the WHERE filter:
SELECT
('' = '' AND 'a' = 'b') AS normal_failed_login,
('' = '' OR 1 = 1) AS injected_always_true;
-- Everything after '-- ' on the same line is ignored by the SQL parser:
SELECT 'admin_session_granted' AS status WHERE '' = '' OR 1 = 1 -- AND is_active = 0;
محاكي الوقاية من حقن SQL والاستعلامات المحضرة (Prepared Statements) في MySQL 8
تقضي الاستعلامات المحضرة مسبقاً (Prepared Statements / Parameterized Queries) على ثغرات حقن SQL نهائياً، لأنها تفصل فصلاً تاماً بين مرحلة بناء هيكل الاستعلام ومرحلة إرسال البيانات عبر مرحلتين مستقلتين في بروتوكول MySQL:
- المرحلة الأولى — التحضير والترجمة (
PREPARE): يرسل التطبيق نص الاستعلام مزوداً بعلامات استفهام (?) كمواضع حجز للقيم:SELECT id, email FROM users WHERE email = ?. يقوم خادم MySQL بتحليل الجملة نحوياً وبناء شجرة التنفيذ وتثبيتها نهائياً. - المرحلة الثانية — التنفيذ وتمرير القيم (
EXECUTE): يرسل التطبيق قيم المتغيرات في حزمة مستقلة تماماً. وبما أن شجرة الاستعلام قد بُنيت واكتملت في المرحلة الأولى، يضع الخادم القيمة المرسلة داخل الخانة المخصصة لها كبيانات حرفية صمّاء، ولا يمررها على محلل أوامر SQL أبداً! - ميزة الأداء عند التكرار: عند تنفيذ نفس الاستعلام مئات المرات بقيم مختلفة، يوفر التحضير المسبق وقت التحليل النحوي المتكرر.
المرحلة 1 (PREPARE) : يبني الخادم هيكل الأمر -> SELECT id FROM users WHERE email = [PARAM_1]
المرحلة 2 (EXECUTE) : يضع القيمة كنص حرفي -> [PARAM_1] = "' OR '1'='1" (استحالة تغيير الهيكل!)PREPARE safe_lookup FROM
'SELECT id, email, status FROM customers WHERE email = ? AND status = ?';
SET @email_param = '[email protected]';
SET @status_param = 'active';
EXECUTE safe_lookup USING @email_param, @status_param;
DEALLOCATE PREPARE safe_lookup;
إلى جانب دوال التحضير في لغات البرمجة، يوفر خادم MySQL 8 أوامر SQL مباشرة للتحضير والتنفيذ وإخلاء الذاكرة، وتُستخدم بكثرة في الجلسات التفاعلية وداخل الإجراءات المخزنة الديناميكية:
PREPARE stmt_name FROM 'SELECT ... WHERE category = ? AND unit_price <= ?';: يترجم نص الاستعلام ويحفظه في ذاكرة الجلسة باسمstmt_name.SET @cat = 'Storage', @max_p = 200.00;: يجهز القيم المراد تمريرها داخل متغيرات الجلسة المسبوقة بعلامة@.EXECUTE stmt_name USING @cat, @max_p;: ينفذ الاستعلام المحضر ويربط المتغيرات بالترتيب مكان علامات الاستفهام (?).DEALLOCATE PREPARE stmt_name;(أو المرادفDROP PREPARE stmt_name;): يحرر الذاكرة المحجوزة للاستعلام المحضر في الخادم فور انتهاء الحاجة إليه، مما يمنع استنزاف الحد الأقصىmax_prepared_stmt_count.
+----+-------------------+-----------+------------+
| id | product_name | category | unit_price |
+----+-------------------+-----------+------------+
| 15 | NVMe SSD 2TB | Storage | 149.00 |
+----+-------------------+-----------+------------+PREPARE filter_products FROM
'SELECT id, product_name, category, unit_price
FROM products
WHERE category = ? AND unit_price <= ?
ORDER BY unit_price ASC';
SET @cat_name = 'Storage';
SET @max_price = 200.00;
EXECUTE filter_products USING @cat_name, @max_price;
DEALLOCATE PREPARE filter_products;
قاعدة هندسية بالغة الأهمية: علامات الاستفهام (?) في الاستعلامات المحضرة تقبل قيم البيانات فقط، ولا يمكن استخدامها لتمرير أسماء الجداول أو أسماء الأعمدة أو كلمات الترتيب مثل ASC / DESC! فكيف نسمح للمستخدم بترتيب النتائج حسب عمود يختاره بأمان تام؟
- لماذا لا يعمل
ORDER BY ?لترتيب الأعمدة؟ إذا مررت النص'unit_price'مكان علامة الاستفهام فيORDER BY ?، فسيعامله MySQL كنص ثابت متساوٍ في كل الصفوف ولن يرتب الجدول! - الحل الأول — استخدام تعبير
CASEالآمن داخل الاستعلام المحضر: مرر خيار المستخدم كقيمة عادية (?) داخل جملةCASEتحول الخيارات المسموحة فقط إلى الأعمدة الحقيقية المناظرة لها. - الحل الثاني — القائمة البيضاء الصارمة (Strict Whitelist): افحص اسم العمود المطلوب في كود التطبيق مقابل مصفوفة ثابتة من الأعمدة المسموحة فقط، وارفض أي قيمة خارج القائمة البيضاء فوراً.
+----+-------------------+------------+
| id | product_name | unit_price |
+----+-------------------+------------+
| 10 | USB-C Hub | 29.00 |
| 15 | NVMe SSD 2TB | 149.00 |
+----+-------------------+------------+PREPARE safe_sorted_products FROM
'SELECT id, product_name, unit_price FROM products
WHERE category = ?
ORDER BY
CASE WHEN ? = ''price_asc'' THEN unit_price END ASC,
CASE WHEN ? = ''price_desc'' THEN unit_price END DESC,
id ASC';
SET @cat = 'Storage', @sort = 'price_asc';
EXECUTE safe_sorted_products USING @cat, @sort, @sort;
DEALLOCATE PREPARE safe_sorted_products;
يلخص الجدول المرجعي التالي منظومة الدفاع المتكاملة متعددة الطبقات (Defense-in-Depth) لتأمين وإدارة قواعد بيانات MySQL 8 في بيئات الإنتاج:
| طبقة الحماية الهندسية | التطبيق القياسي في MySQL 8 | الخطر الأمني الذي تمنعه |
|---|---|---|
| 1. الاستعلامات المحضرة | PREPARE ... FROM '... WHERE col = ?' / PDO | القضاء الجذري على حقن قواعد البيانات (SQL Injection) |
| 2. القائمة البيضاء للمعرفات | تعبير CASE أو التحقق الصارم من أسماء الأعمدة | منع الحقن في جمل الترتيب الديناميكية ORDER BY |
| 3. تقييد الحسابات والمصادقة | CREATE USER 'app'@'10.0.1.%' وتشفير SHA-256 | منع الاتصالات الخارجية غير المصرح بها وكسر كلمات المرور |
| 4. مبدأ أقل الصلاحيات والأدوار | GRANT SELECT, INSERT, UPDATE ON shop_db.* | حصر صلاحيات التطبيق في قاعدته ومنع حذف الجداول |
| 5. النمط الصارم والقيود | STRICT_TRANS_TABLES وقيود CHECK / FK | رفض البيانات التالفة أو المقتطعة أو اليتيمة داخل المحرك |
| 6. النسخ الاحتياطي والاستعادة | mysqldump --single-transaction + السجل الثنائي | استعادة البيانات بالكامل حتى أي ثانية تسبق الكارثة |
ملخص الدرس: أتقنت في هذا الدرس كيف يؤدي دمج النصوص إلى ثغرات الحقن (SQLi)، وكيف تفصل الاستعلامات المحضرة (PREPARE / EXECUTE / DEALLOCATE PREPARE) الكود عن البيانات، وكيفية استخدام القائمة البيضاء لأسماء الأعمدة.
الخطوة التالية والدرس القادم: طبّق منظومة الحماية والأداء المتكاملة التي تعلمتها عبر دروس دورة MySQL 8.4 الخمسة والستين في مشاريعك الإنتاجية.
ملخص الدرس
حصاد الدرسمراجعة مركّزة لأهم المفاهيم والقواعد الهندسية التي أتقنتها في هذا الدرس قبل التطبيق العملي
ماذا تعلّمت في هذا الدرس؟
إن الجمع بين الاستعلامات المحضرة (PREPARE / EXECUTE / DEALLOCATE PREPARE) والقائمة البيضاء لأسماء الأعمدة ومبدأ أقل الصلاحيات والنسخ الاحتياطي المتسق يتوّج إتقانك الهندسي الكامل لقواعد بيانات MySQL 8. الخطوة التالية: وظّف هذه المهارات الهندسية المتكاملة في بناء وتأمين قواعد بيانات تطبيقاتك الحقيقية!
سجّل الدخول لحفظ تقدمك
تابع إنجاز المواضيع والمصطلحات والمهام، وكمّل من آخر خطوة على أي جهاز.
المصطلحات4
راجع المعنى، اشرحه لنفسك، ثم علّم البطاقة كمفهومة.
- 01 Prepared Statements الاستعلامات المحضرة
- تعلّم الحماية من ثغرات حقن قواعد البيانات SQL Injection واستخدام الاستعلامات المحضرة (PREPARE و EXECUTE) في MySQL 8 مع أمثلة وتطبيقات تفاعلية.
- للمراجعة
- 02 How String Concatenation Causes SQLi كيف يسبب دمج النصوص الحقن
- المفهوم الهندسي الأساسي والصياغة التطبيقية لقسم كيف يسبب دمج النصوص الحقن في خادم MySQL 8.4.
- للمراجعة
- 03 Anatomy of Authentication Bypass تشريح هجوم تجاوز الشرط
- المفهوم الهندسي الأساسي والصياغة التطبيقية لقسم تشريح هجوم تجاوز الشرط في خادم MySQL 8.4.
- للمراجعة
- 04 How Prepared Statements Separate Code فصل الكود عن البيانات المحضرة
- المفهوم الهندسي الأساسي والصياغة التطبيقية لقسم فصل الكود عن البيانات المحضرة في خادم MySQL 8.4.
- للمراجعة
لا توجد بطاقات تطابق البحث والتصفية.
اقرأ البطاقات بحرية. سجّل الدخول لحفظ تقدم مراجعتك.
الاختصارات4
راجع المعنى، اشرحه لنفسك، ثم علّم البطاقة كمفهومة.
- 01 SQLi SQLi
- SQL Injection
- ثغرة حقن قواعد البيانات الناتجة عن دمج مدخلات المستخدم النصية مباشرة داخل جملة SQL مما يغير منطق الاستعلام.
- للمراجعة
- 02 AST AST
- Abstract Syntax Tree
- شجرة التحليل النحوي الداخلية للاستعلام التي يبنيها خادم MySQL ويثبتها خلال مرحلة التحضير PREPARE.
- للمراجعة
- 03 PDO PDO
- PHP Data Objects
- واجهة الاتصال القياسية بقواعد البيانات في لغة PHP والتي تدعم الاستعلامات المحضرة وربط المعاملات الآمن.
- للمراجعة
- 04 OWASP OWASP
- Open Worldwide Application Security Project
- المنظمة العالمية لأمن تطبيقات الويب التي تصدر المعايير القياسية للوقاية من ثغرات الحقن وحماية قواعد البيانات.
- للمراجعة
لا توجد بطاقات تطابق البحث والتصفية.
اقرأ البطاقات بحرية. سجّل الدخول لحفظ تقدم مراجعتك.
مهامك قبل الاختبار
خطوة صغيرة كل مرة. وإنجاز تقدر ترجع له.
-
نفّذ جمل SQL الواردة في قسم كيف يسبب دمج النصوص الحقن داخل بيئة MySQL 8 المحلية وتحقق من المخرجات.
-
جرّب الحالات الثلاث داخل محاكي الوقاية من حقن SQL والاستعلامات المحضرة (Prepared Statements) في MySQL 8 في قسم تشريح هجوم تجاوز الشرط وقارن سلوك المحرك.
تأشير المهمة إقرار منك بإتمامها، وليس تصحيحًا آليًا للكود. يُحفظ تقدمك في حسابك.
اختبر فهمك.
ووصلها للإتقان.
كل سؤال خطوة لقدّام. اختار، اكتب كود، وشوف نتيجتك فورًا.
أكمل المهام، واجمع كل الإجابات الصحيحة. أقل من 100%؟ راجع وأعد المحاولة.
الأسئلة متاحة للاطلاع. سجّل الدخول للتفاعل وحفظ تقدمك.
لمحة عن التحدي6 أسئلة تنتظرك +
ما السبب الجذري لحدوث ثغرة حقن قواعد البيانات (SQL Injection) في التطبيقات؟
دمج مدخلات المستخدم مباشرة داخل نص أمر SQL بدلاً من فصل الكود عن البيانات عبر الاستعلامات المحضرة.
لماذا يؤدي النص المحقون ' OR 1=1 -- إلى تجاوز شرط التحقق في استعلام مبني بدمج النصوص؟
يغلق علامة التنصيص مبكراً، ويضيف الشرط الدائم الصواب OR 1=1، ويحوّل بقية جملة WHERE إلى تعليق مهمل.
كيف تمنع الاستعلامات المحضرة (Prepared Statements) ثغرات حقن SQL عند تمرير مدخلات المستخدم؟
يبني الخادم شجرة الاستعلام ويثبتها بعلامات (?) في مرحلة PREPARE، ثم يعامل القيم الممررة في مرحلة EXECUTE كبيانات حرفية فقط ولا يترجمها كأوامر.
ما التسلسل الصحيح لأوامر SQL لتحضير استعلام بمعاملات وتنفيذه ثم تحرير ذاكرته في MySQL 8؟
التسلسل القياسي هو: PREPARE ثم EXECUTE ... USING ثم DEALLOCATE PREPARE.
لماذا لا يصلح وضع علامة الاستفهام (?) مباشرة مكان اسم العمود في ORDER BY ?، وما البديل الآمن؟
لأن (?) تربط القيم فقط فتُعامل كنص ثابت؛ والبديل الآمن هو استخدام تعبير CASE أو التحقق عبر قائمة بيضاء صارمة (Whitelist) لأسماء الأعمدة.
يؤدي تنفيذ الأمر DEALLOCATE PREPARE إلى تحرير الذاكرة المحجوزة للاستعلام المحضر داخل جلسة الخادم.
صواب؛ يحرر الأمر DEALLOCATE PREPARE موارد الذاكرة المرتبطة بالاستعلام المحضر في الجلسة.