• 0
net_code

ال sql injection بالتفصيل

سؤال

Sql Injection

sqlinjection.jpg

ال sql injection هو حقن كود معين فى مدخلات البرنامج ليتم تنفيذه على مستوى قاعدة البيانات ليتم الحصول على معلومات من قاعدة البيانات غير مصرح بها أو التلاعب بمحتويات قاعدة البيانات

ال SQL Injection ينتج عن ضعف إما فى طبقة التطبيق سواء كان PHP أو ASP …. أو فى طبقة قاعدة البيانات كالثغرة التى ظهرت على يد Josh Berkus و Tom Lane فى الدالة الخاصة بال ماي سكول mysql_real_escape_string و التى يستخدمها مطوري التطبيقات التى تعتمد على قاعدة بيانات Mysql لفلترة المدخلات قبل إدخالها لقاعدة البيانات , حيث إكتشف المطوران خلل فى فلترة هذا الدالة للمدخلات اليونيكود مما يتيح للمخترق تجاوزها – تم إصلاح هذا الخطأ فى النسخة 5.0.22 عام 2006

http://dev.mysql.com/doc/refman/5.0/en/news-5-0-22.html

ال sql injection يتم بشكل أساسي على لغة ال sql وهي اللغة الرئيسية للتعامل مع قاعدة البيانات و هي تتكون أساسا من ANSI SQL و هي معتمدة بشكل كامل فى قواعد البيانات كلها بنفس الطريقة مثال SELECT , UPDATE , DELETE و غيرها و هناك بعض الإضافات التى تضيفها محركات قواعد البيانات إلى لغة ال sql و لكن لا يمكن إستعمالها بنفس الطريقة مع كل محركات البحث ك stored procedure أو بعض ال SQL Functions

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

sql_injection.gif

1- تخطي حمايات الدخول

تأمل معي الكود التالي :-



sql = “SELECT * FROM `users` WHERE `username` = ‘$username’ AND `password` = ‘$password’” ;
Mysql_query($sql);
If(mysql_num_rows($result)){
Echo ‘logged’;
}else{
Echo ‘failed’;
}

الكود السابق سليم من الناحية التقنية ولكنه غير سليم إطلاقا من الناحية الأمنية حيث ببساطة يمكن إدخال اليوزر نيم أى شئ ثم إدخال

‘or 1=1;--

تخيل معي الكود السابق بعض وضع المدخلات

$sql = “SELECT * FROM `users` WHERE `username` = ‘admin’ AND `password` = ” or 1=1;--’” ;

هل لاحظت ؟؟ نعم لقد دخلت بالفعل و ما أدخلته كمدخلات تم تنفيذه كجزء من جملة ال sql وهذا أدى إلى تجاوز الحماية بسهولة حيث بعد الكلمة or تم وضع شرط يتحقق دائما وهو 1=1 و وضع ; و التى تعني نهاية جملة الإستعلام و – لتجاهل ما بعدها

2- عرض البيانات :-

من الأهداف الرئيسية للsql injection عرض بيانات من داخل قواعد البيانات مثل عرض محتويات جدول ال users مثلا

و يتم هذا عبر حقن جملة select فى جملة select أخرى عن طريق Union

مثلا

Select * From `news` WHERE `news_id` = ‘.$_GET['id']

فإذا قمنا بإدخال كالآتي

site.com/news.php?id=1 union select 1,2,3 from users;

سيكون شكل جملة sql كالتالي

Select * From `news` WHERE `news_id` = 1 union select 1,2,3 from `users`;

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

site.com/news.php?id=1 union select 1,2,3 from users WHERE id = 1;

هناك عدة تحديات تواجه المخترق فى ال sql injection أقواهم هو أسماء الجداول و الحقول و هو ما يمكن تخمينه فى البداية بعدة طرق فى حالة أن مدير الموقع يتيح للبرنامج إظهار الأخطاء أو فى حالة عدم ظهور الأخطاء مما يؤدي بنا إلى blind sql injection ( سيتم شرح هذه التقطة بالتفصيل فيما بعد )

3- التلاعب بالبيانات :-

أحد أخطر الأشياء التى يمكن فعلها بال sql injection هي التلاعب بالبيانات سواء عن طريق insert أو Update أو Delete أو حتى Drop table

مثال :-

فى مثالنا السابق يمكن إدخال الآتي

site.com/news.php?id=1;INSERT INTO users VALUES (NULL,’netcode’,'netcode’);

هل يمكنك تخمين ماذا سيحدث ؟؟ ;)

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

site.com/news.php?id=1;DROP TABLE users

و لكن :-

هذه الطريقة تعتمد على دعم multiple sql statements execution و بالفعل هي مدعمة فى قواعد البيانات و لكن أغلب لغات البرمجة تحمي هذه النقطة فمثلا Mysql_query() لا يمكن تنفيذ أكثر من جملة sql عليها فى نفس الوقت

فن المعرفة فى sql injection :-

ال sql injection يعتمد على المعرفة بدرجة أولى من أول نوع و إصدار قاعدة البيانات ( نوع قاعدة البيانات يفيدك من حيث ال syntax فهي تختلف من نوع قاعدة بيانات و أخرى و إصدارها يفيد فى معرفة إذا كان هذا الإصدار مصاب بثغرة معينة مثل ثغرة mysql_real_escape_string فى mysql ) و أسماء الجداول و الحقول

و تنقسم المعرفة فى sql injection إلى نوعين النوع العادي – حيث أن مدير الموقع يتيح إظهار الأخطاء – و blind sql injection

أ – النوع العادي :-

فى البداية نريد أن نعرف أسماء الجداول و يمكنك هذا بسهوله إذا كان السكريبت يسمح ب multiple sql statements execution عن طريق show tables

و لكن إذا كان السكريبت لا يسمح يمكن ذلك عن طريق بعض التخمينات

site.com/news.php?id=1 AND 1=(SELECT COUNT(*) FROM tablename); --

حيث tablename هو تخمينك ففي هذه الجمله ستعود بالقيمة 1 فقط إذا كان الإسم صحيح فلن يظهر الخبر إلا إذا كان الإسم صحيح

معرفة أسماء الحقول :-

يمكنك معرفة أسماء الحقول عن طريق الأخطاء التى تظهر عن طريق الجملة

HAVING وهي جملة تستخدم فى تنفيذ الشروط على ال functions

فيمكنك إستخدام الترتيب التالي

‘ HAVING 1=1 --

سيظهر لك أحد الحقول كخطأ

‘ GROUP BY table.columnfromerror1 HAVING 1=1 --

سيظهر لك خطأ ثان

‘ GROUP BY table.columnfromerror1, columnfromerror2 HAVING 1=1 --

و هكذا حتى ينتهي ظهور الأخطاء و هنا تكون قد حصلت على أسماء الحقول كلها

ويمكن الحصول على عدد الحقول لإستخدامها فى جملة select عن طريق نفس الفكرة

ORDER BY 1--
ORDER BY 2--
ORDER BY 3--

و هكذا حتى تحصل على خطأ و هنا تعلم عدد الحقول الحقيقية

ب- blind sql injection :-

و هنا تكون مهمة المخترق إزدادت صعوبة و لكنها ليست مستحيلة حيث أن المطور أغلق إظهار الأخطاء error reporting و هنا تكون عمليات ال finger prints لقاعدة البيانات بالطريقة العادية شبة مستحيلة و هنا يتم عمل بعض التجارب للوصول للنتائج

و تنقسم إلى ثلاث حيل

Conditional responses

هذه الحيلة تعتمد على التلاعب بالمتغيرات لتغيير الإستجابة الخاصة بالsql

فلمعرفة هل البرنامج مصاب بثغرة sql injection أم لا يمكنك إستخدام الآتي

http://site.com/news.php?id=2 and 1=2

إذا كان البرنامج مصاب بثغرة ستتغير الإستجابة و ستظهر الصفحة بدون أى بيانات و للتأكد من هذا يمكنك تغيير الشرط إلى 1=1

و إذا ظهرت بيانات هنا تتأكد أن التطبيق مصاب ب sql injection

Conditional errors

و هذه الحيلة تعتمد على توليد خطأ عندما يكون الشرط صحيحا مثلا

SELECT 1/0 FROM users WHERE username=’netcode’;

فإذا كان هناك بالفعل مستخدم بالإسم netcode فسيتم توليد الخطأ Division By Zero كنتيجة ل 1/0

Time delays

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

مثال :-

إستخدام ال sql injection فى عمل brute force للباسوورد

سنستخدم هنا الدالة benchmark و لتنفيذ الدالة encode عدد كبير من المرات لتأخير تنفيذ ال sql إذا كان الشرط صحيح

UNION SELECT IF(SUBSTRING(user_password,1,1) = CHAR(50),BENCHMARK(5000000,ENCODE(‘MSG’,'by 5 seconds’)),null) FROM users WHERE id = 1;

هنا إستخدمنا الدالة if كشرط و قارنا أول حرف من الباسوورد بأنه يساوي char(50)أي الرقم 2

إذا تم تحميل الصفحة ببطء إذا الشرط صحيح و أول حرف من الباسسورد 2

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

إستغلال ال database stored procedure

أشهر إستغلال لهذا النوع هو إستغلال xp_cmdshell لتنفيذ أمر على السيرفر dir مثلا أو ping

EXEC master.dbo.xp_cmdshell ‘cmd.exe dir c:’

و لكن تنفيذ الأوامر غير مفعل إفتراضيا فى Sql Server 2005 للحماية بالإضافة إلى أنه يحتاج صلاحيات ال admin

هناك العديد من ال stored procedure التى يمكن إستغلالها

Google it ;)

الحماية .. الحل ؟؟

بعد هذا الموضوع أعتفد أننا متفقين الآن أن ال sql injection من أخطر الهجمات التى تتم على ال web application لما يمكنها فعله فماذا يمكن فعله لصد هذه الهجمات

1- كن شكاكا :- لا بد من فلترة جميع المدخلات بلا إستثناء سواء من get أو post أو ajax أو أى مدخل آخر

2- إغلق تقرير الأخطاء :- قم بتصعيب الأمور على المخترق و إجعله يلجأ دائما إلى blind sql injection

3- قم بتغيير ال table prefix لجداول قاعدة البيانات بأسماء غير مفهومة

4- لا تقم بإعطاء صلاحية المدير لمستخدم قاعدة البيانات الحالي إذا كنت لا تحتاج هذه الصلاحياة

5- قم بتعطيل خاصية multiple statement sql execution إذا كانت لغة البرمجة التى تستخدمها أو قاعدة البيانات لم تقم بتعطيلها

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

هذا و الله أعلم

باب الأسئلة مفتوح للجميع فى هذا الموضوع

روابط للأستزادة

http://en.wikipedia.org/wiki/SQL_injection

http://www.owasp.org/index.php/SQL_Injection

http://www.owasp.org/index.php/Blind_SQL_Injection

http://unixwiz.net/techtips/sql-injection.html

http://ferruh.mavituna.com/sql-injection-cheatsheet-oku/

تم تعديل بواسطه net_code
4

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

4 إجابة على هذا السؤال .

  • 0

موضوع جميل الله يجزيك كل خير

ساقوم باضافة بعض خطوات الحماية بالا asp.net

1- تحديد الطول الاعظمي للحقول

2- عمل تحقق validation على الحقول بالجافا سكريبت قبل الارسال

3-لا يجوز ولا باي شكل استخدام الطريقة


string="select * from users where id="+Textbox.Text

وانما يجب استخدام ال

sql parameters+


Server.HtmlEncode(TextBox1.Text);

4- يجب استخدام ال server.htmlencode

طبعا هذه الملاحظة تطبق على url and input

5- التعامل مع الاجرائيات المخزنة والمناظير وليس استعلامات ضمن الكود

6- استخدام توجيه لصفحات الاخطاء عن طريق ملف webconfig لصفحات اخطاء

بالتوفيق وجزاك الله وجزاكم كل خير

2

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

إضافة جميلة يا X-FIle

و لكن لدي إضافة بسيط على

2- عمل تحقق validation على الحقول بالجافا سكريبت قبل الارسال

حيث أنه يمكن التلاعب بالجافاسكريبت بسهوله لتجاوز ال validation بإستخدام javascript injection لذلك لا يجب إستخدامها كخط دفاع رئيسي لأنه سرعان ما سينهار و يجب أن يكون خط دفاعك الأساسي validation & filtering على مستوى التطبيق ال server side و ليس ال client side

2

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

اكيد كلامك ولكن انا استخدمت Server.HtmlEncode لهذا الغرض طبعا ال javascript injection هنا تم تخطيه بالدالة السابقة

ويبقى كخط اساسي تحديد طول الحقل اي لا اتوقع حقل ادخال اسم ان يكون طوله 100 محرف :)

طبعا بالتاكيد يجب ان يكون ال validation موجود بشكل متوازي على طرف الزبون وطرف المخدم

جزاك الله كل خير

1

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

جزاكم الله كل الخير

ناهيكم عن التوابع التي توفرها معظم قواعد البيانات قد تستخدم لأغراض الاختراق

كهذه :


*mysql
select @@version //get database version
select user(); //get database username
select database()//get database name
.......others

*Microsoft sql server
select @@version
select @@servername
select @@microsoftversion
.......others

*Oracle
select version()
select current_database()
select current_user
select session_user
.......others

http://michaeldaw.or...ion-cheat-sheet

بالاضافة إلى توابع قراءة الملفات


select LOAD_FILE('/etc/passwd') into outfile('/tmp/test.txt')

وهذا إن لم نتحدث عن الوصول إلى اسماء الجداول و القيود و تفاصيل قاعدة البيانات عن طريق الـ Information_schema wink.gif

على الرغم من أن بعض هذه الأفكار تم معالجتها في اصدارات حديثة من قواعد البيانات

كل هذا يفرض على المبرمج دراسة أي استعلام ضمن برنامجه قبل تنفيذه (دراسة المدخلات على أي استعلام)

بارك الله بكم مقالة رائعة :)

تم تعديل بواسطه MoHaMMaD Pro
2

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

من فضلك سجل دخول لتتمكن من التعليق

ستتمكن من اضافه تعليقات بعد التسجيل



سجل دخولك الان

  • يستعرض القسم حالياً   0 members

    لا يوجد أعضاء مسجلين يشاهدون هذه الصفحة .