حقن إس كيو إل

محمد الحمود، وسيم أبو زينة
ساهم بشكل رئيسي في تحرير هذا المقال

اختراق إس كيو إل (SQL Injection) هو عبارة عن هجوم برمجي ضد التطبيقات التي تحتوي قواعد معطيات تتمثل بحقن رماز مصدري (code) في تطبيق ما ليتم تنفيذه في طبقة قاعدة المعطيات لهذا التطبيق و تعتبر هذه العملية من أخطر أنواع الهجمات ضد مواقع الإنترنت بشكل خاص .

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

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

الصيغ العامة لهجوم Sql Injection

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

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

SqlDataSource_Login.SelectCommand = "Select * from Users Where username = '" + TextBox_UserName.Text + "';";


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

' or '1'='1

ليصبح شكل التعليمة النهائية هو :

SELECT * FROM Users WHERE username =  OR '1'='1';

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

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

mohammad'; drop table Users--

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

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

var sql = "select * from users where username = '" + username + "' 
and password = '" + password + "'";

الآن إذا جاء المهاجم و أدخل المعلومات التالية :

Username: admin'-- (باعتبار أن admin هو اسم مدير الموقع )

عندها سيتمكن المهاجم من الدخول إلى الموقع بحساب المدير.

في حال أدخل المهاجم المعلومات التالية :

Username: ' or 1=1-- 

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

في حال أدخل المهاجم المعلومات التالية :

Username: '; drop table users-- 

عندها كما في المثال السابق سيمسح الجدول الخاص بكافة الأعضاء في الموقع .

الحصول على المعلومات عن طريق رسائل الأخطاء

كان David Litchfield هو أول من اكتشف هذه التقنية و تعتمد في جوهرها على الاستفادة من رسائل الأخطاء التي يتسبب بها المهاجم و يستطيع عن طريق هذه الرسائل أن يقوم باكتشاف هيكلية قاعدة المعطيات (أي معرفة أسماء الجداول و أسماء الأعمدة و أنواعها) ليستفيد من ذلك في خطوات أخرى .

لنفترض وجود قاعدة معطيات فيها جدول باسم Users مؤلفة من id من النوع int و username و password من النوع nvarchar و تحوي بضعة مستخدمين . فإذا كان المهاجم يريد إدخال حساب خاص به عن طريق تعليمة insert فمن الصعب جداً أن يكون محظوظاً في تخمين اسم الجدول و أسماء الأعمدة و أنواع المعطيات فيها لذلك سيلجأ إلى تقنية الاستفادة من رسائل الأخطاء التي ستعطيه معلومات كاملة عن قاعدة المعطيات كما يلي :

في البداية سيحتاج المهاجم إلى معرفة اسم قاعدة البيانات لذلك سيدخل العبارة التالية في الحقل المخصص لإدخال اسم المستخدم :

Username: ' having 1=1--

مما سيتسبب بالخطأ التالي :

Column 'Users.id' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.

هنا استطاع المهاجم الحصول على معلومتين هامتين ، الأولى هي اسم الجدول و هو Users و الثانية هي اسم أول عمود في الجدول و هو العمود id . حسناً الآن يريد المهاجم معرفة اسم العمود الثاني لذلك سيكتب ما يلي :

Username: ' group by users.id having 1=1-- 

أي قام بكتابة اسم العمود id ليظهر له العمود الذي يليه عن طريق التسبب بالخطأ التالي :

Column 'Users.username' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.

هنا ظهر اسم العمود الثاني وهو username . و بنفس الطريقة سيستطيع معرفة اسم العمود الثالث و أي أعمدة أخرى متبقية .

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

Username: ' union select sum(username) from users--

مما سيظهر الخطا التالي :

Operand data type nvarchar is invalid for sum operator.

فيعلم المهاجم أن نوع البيانات في العمود username هو nvarchar . و بهذه الطريقة نستطيع معرفة نوع البيانات في أي عمود .

بقي على المهاجم أن يعرف إذا ما كان الـ id يتزايد تلقائياً أم لا لذلك سيحاول إدخال مستخدم جديد مع تحديد الـ id  :

'; insert into Users values( 666, 'fakeUser', 'fakePassword')--

فإذا كان العمود id يتزايد تلقائياً سينتج الخطأ التالي :

An explicit value for the identity column in table 'Users' can only be specified when a column list is used and IDENTITY_INSERT is ON.

أصبح بإمكان المهاجم الآن إدخال ما يريد إلى الجدول Users بعد أن حصل على المعلومات اللازمة لذلك و يستطيع أن يكتب :

'; insert into Users values( 'fakeUser', 'fakePassword')--

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

انظر أيضا

المصادر

وصلات خارجية