اختراق لغة الاستعلام البنيوية
من ويكيبيديا، الموسوعة الحرة
أختراق لغة الأستعلام البنيوية (بالإنجليزية: SQL INJECTION) ، او حقن لغة الأستعلام البنيوية (SQL) هي وسيلة لأكتشاف اي ثغرة أمنية موجودة بطبقة قاعدة البيانات التابعة لأي برنامج (DATABASE LAYER). هذه الثغرات ممكن ان تكون حاضرة عندما لا يتم تصفية مدخلات المستخدم لبعض الحروف والرموز الخاصة (ESCAPE CHARACTERS) المضمنة داخل جمل لغة الأستعلام البنيوية, او ان لا يتم مراجعة نوعية المدخلات ان كانت نصية ام عددية (STRONGLY TYPED) مما يسبب عدم التكهن بنتيجة تنفيذها.
فهرس |
[تحرير] أنواع ثغرات أختراق لغة الأستعلام البنيوية (FORMS OF SQL INJECTION VULNERABILITIES)
[تحرير] عدم تصفية الرموز الخاصة (ESCAPE CHARACTERS) بشكل صحيح
هذا النوع من أختراق لغة الاستعلام البنيوية يحصل عندما لا يتم تصفية مدخلات المستخدم من الرموز الخاصة التي يتم أدراجها داخل جمل بصيغة لغة الأستعلام البنيوية والتي يمكن ان تؤدي للتلاعب بهذه الجمل المدخلة لقاعدة البيانات من قبل مستخدمي البرنامج. الجملة التالية تبين هذه الثغرة:
SELECT * FROM users WHERE name = ' + userName + ';
هذه الجملة سوف تستدعي جميع السجلات الخاصة بأسم المستخدم (userName) من جدول (users), لكن اذا تم تغير المتغير (userName) بشكل معين وباستخدام الرمز الخاص (') من قبل المستخدم المخترق (MALICIOUS USER), فمن الممكن لهذه الجملة ان تفعل أكثر مما هو منوي عليه, مثلا يمكن استبدال قيمة المتغير (userName) بالجملة الأتية:
a' or 't'='t
وبالتالي تصبح الجملة كالاتي:
SELECT * FROM users WHERE name = 'a' OR 't'='t';
أذا تم أستخدام الجملة السابقة بأجراء التأكد من هوية المستخدم (AUTHENTICATION PROCEDURE), فمن الممكن أستخدام هذه الطريقة للحصول على الصلاحية لأن نتيجة المعادلة 't'='t' هي دائما صحيحة (TRUE).
في بعض خوادم لغة الأستعلام البنيوية (SQL SERVERS) مثل (MS SQL SERVER) يمكن حقن أي جملة صحيحة عن طريق أستخدام هذه الطريقة بتنفيذ عدة جمل (جمل متعددة) في وقت واحد اي في نفس المدخل, مثلا يمكن لقيمة (userName) في الجملة الاتية أن تتسبب بمحو جدول المستخدمين (users) من قاعدة البيانات بالأضافة لأظهار جميع بيانات جدول (data):
a'; DROP TABLE users; SELECT * FROM data WHERE name LIKE '%
وبالتالي تصبح الجملة كالاتي:
SELECT * FROM users WHERE name = 'a'; DROP TABLE users; SELECT * FROM DATA WHERE name LIKE '%';
بعض تطبيقات لغة الأستعلام البنيوية الأخرى لا تسمح بتنفيذ عدة أوامر في جملة واحدة للحماية من المخترقين ومنعهم من حقن جمل الأستعلام بشكل منفصل, ولكن هذا لا يمنعهم من تعديل هذه الجمل.
[تحرير] 2- معالجة نوع الحقل الخاطئة (INCORRECT TYPE HANDLING)
هذا الشكل من الأختراق يحصل عندما لا يتم التأكد من نوع الحقل المدخل من قبل المستخدم. يمكن لهذا الأختراق ان يحصل مثلا عند أستخدام حقل من نوع عددي (NUMERIC) في جملة الأستعلام, ولكن المبرمج لم يقم بمراقبة مدخلات المستخدم لمعرفة أذا كانت من نوع عددي ام لا. مثلا:
SELECT * FROM DATA WHERE id = " + a_variable + ";
من الواضح في هذه الجملة ان المقصود من المتغير (a_variable) ان يكون عدد مرتبط بالحقل (id), ولكن اذا كان في الحقيقة من نوع نص فمن الممكن ان يتم التلاعب به من قبل المستخدمين كما يشائون, وبالتلي يمكنهم ان يمرروا جمل مخربة. مثال:
1; DROP TABLE users
وبالتالي تصبح الجملة كالاتي:
SELECT * FROM DATA WHERE id = 1; DROP TABLE users;
وعند تنفيذها سوف يتم محو جدول (users) من قاعدة البيانات.
[تحرير] 3- ثغرات داخل خادم قاعدة البيانات نفسه (VALNERABILITIES INSIDE THE DATABASE SERVER)
من الممكن ان تظهر الثغرات أحيانا داخل برنامج خادم قاعدة البيانات نفسه, كما الحال في (MySQL Server) مع الوظيفة real_escape_chars().
لمزيد من المعلومات عن هذه الحالة زر الصفحة التالية:
[1] http://dev.mysql.com/doc/refman/5.0/en/news-5-0-22.html
[تحرير] حماية البرامج من أختراق لغة الأستعلام البنيوية (SECURING APPLICATIONS AGAINST SQL INJECTION)
[تحرير] 1معالجة البرامج وتحصينها (APPLICATION REMEDATION)
من السهل الحماية من أختراق لغة الأستعلام البنيوية في معظم لغات البرمجة التي تستهدف تطبيقات شبكة الأنترنت. في لغة برمجة (Perl DBI) مثلا فأن الوظيفة (DBI::quote) تستخدم قبل بعض الرموز (ESCAPES SPECIAL CHARACTERS) بدلا من الرمز ('). فل نفرض ان المنتغبر ($sql) يؤشر على (DBI OBJECT):
$query = $sql->prepare("SELECT * FROM users WHERE name = ".$sql->quote($user_name));
تسمح (DBI) بأستخدام حائزي المكان (PLACE HOLDERS), والتي تتيح لك ألزام (BIND) البيانات لجملة معينة منفصلة عن تعريف جملة الأستعلام. اما بالنسبة لقواعد البيانات التي لا تدعم حائزي المكان بالأصل, تقوم (DBI) بمحاكاتهم (EMULATES) تلقائيا عن طريق أضافة الوظيفة (DBI::quote) للقيم.
$query = $sql->prepare("SELECT * FROM users WHERE name = ?"); $query->execute($user_name);
الفائدة من هذه الطريقة انه ليس علينا ان نتذكر تطبيق (DBI::quote) لكل قيمة, لأنها أما ملزمة او منصوصة على نحو ملائم, بحسب نظام أدارة قواعد البيانات (DBMS) الذي نستخدمه. هكذا يتلاشى الموضوع الأساسي في أختراق لغة الأستعلام البنيوية.
[تحرير] 2- معالجة قواعد البيانات وتحصينها (DATABASE REMEDATION)
[تحرير] الأمتيازات الأمنية (SECURITY PRIVILEGES)
ان وضع امتيازات امنية على قواعد البيانات هو أبسط مثال لحماية قواعد البيانات, وبالتالي القليل من التطبيقات تسمح للمستخدم ان يمحي جدول او قاعدة بيانات كاملة.
هذه الأستراتيجية لا تحل مشكلة أختراق لغة الأستعلام البنيوية, ولكنها تخفف من شدة الضرر المحتمل.
[تحرير] الأجراءات المخزنة (STORED PROCEDURES)
معظم قواعد البيانات توفر أمكانية تجهيز جمل الأستعلام في طبقة قواعد البيانات عن طريق الأجراءات المخزنة, عوضا عن أستخدام طبقة التطبيق (APPLICATION LAYER) لبناء لغة الأستعلام البنيوية بشكل ديناميكي. الأجراءات المخزنة تشمل أجراءات قواعد البيانات متكررة الأستخدام والتي تنادى عن طريق (TYPED PARAMETER). هذه الطريقة توفر عدة فوائد أمنية منها: عن طريق أستخدام ال (TYPED PARAMETERS) فأنه يتم تصفية وفلترة مدخلات المستخدم, بالأضافة إلى أن معظم قواعد البيانات تسمح للأجراءات المخزنة بالتنفيذ تحت أمتيازات أمنية معينة, مما يقيد أمكانية قيام التطبيق بعمل اي شيء خارج نطاق الأعمال المحددة مسبقا في الأجراءات المخزنة.
ومع كل هذا فان هذه الطريقة لا تحل مشكلة أختراق لغة الأستعلام البنيوية بشكل كامل, لأنه أذا كانت مدخلات المستخدم (NOT PARAMETERIZED) او غير مفلترة مثل: أذا أعطينا أجراءين مخزنين (GET_PASSWORD(userName)) و (GET_USER(userName, password)), فأن بأمكان المخترق أن يخترق الشيفرة (CODE) في (GET_USER CALL) أذا كان الرقم السري غير مكتوب بشكل صحيح (CORRECTLY ESCAPED) كالتالي:
(GET_USER('admin', "|| GET_PASSWORD('admin') ||"))
لذا فهي ليست أمنة بشكل كامل.
[تحرير] الحماية من أختراق الجمل المتعددة (PREVENTING MULTI-STATEMENT ATTACK)
كما ذكرنا مسبقا المخاطر المتعلقة بأستخدام الجمل المتعددة, فعلى سبيل المثال لو أخذنا موقع ألكتروني يظهر قائمة من السلع لأسم مستخدم (userName) معين, فأن جملة الأستعلام ستكون:
SELECT * FROM items WHERE userName='$userName';
فمن الممكن ان يقوم المستخدم بأدخال الجملة الأتية:
SELECT * FROM items WHERE userName='' OR userName IS NOT NULL OR userName='';
أيضا لو لم نستخدم الرموز الخاصة (QUOTES):
SELECT * FROM items WHERE userid=$userid;
فمن الممكن ان يقوم المستخدم بأدخال الجملة الأتية وهي لا تحوي على الرموز الخاصة (QUOTES):
SELECT * FROM items WHERE userid=33 OR userid IS NOT NULL OR userid=44;
الحل الأنسب لهذه المشكلة هي تعريف المتغير (userid) بأن له قيمة عددية فقط, مثل:
if (!ctype_digit($userid)){ die("Invalid characters in userid.");}
وهكذا تحل هذه المشكلة.
[تحرير] عدم تفعيل الجمل النصية (DISABELING LITERALS)
من الممكن حل مشكلة أختراق لغة الأستعلام البنيوية في حال ان محرك قاعدة البيانات يدعم خاصية "عدم تفعيل الجمل النصية" والتي تعني ان تعمل قاعدة البيانات في وضع (MODE) لا يسمح للنصوص والأرقام (TEXT AND NUMBER LITERALS) ان يكونوا في جملة الأستعلام, وبالمقابل فقط حائزي المكان مسموح بأستخدامهم. لذا جمل بالشكل الأتي:
SELECT * FROM items WHERE userid=2; SELECT * FROM users WHERE name='Smith';
غير مسموح بتنفيذهم في هذا الوضع وسيظهر لنا خطأ (EXCEPTION), ويجب علينا كتابتهم هكذا:
SELECT * FROM items WHERE userid=?; SELECT * FROM users WHERE name=?;
في حال عدم تفعيل الجمل النصية فأن علينا أستخدام رموز حائزي المكان والتي يجب أستخدامها لجميع مدخلات المستخدمين. حاليا فقط ال (H2 DATABASE ENGINE) يدعم خاصية "عدم تفعيل الجمل النصية" و هذه التكنولوجيا لم تسجل لها براءة اختراع بعد.