تقييم الموضوع :
  • 0 أصوات - بمعدل 0
  • 1
  • 2
  • 3
  • 4
  • 5
خطورة ال Sql Injection ولماذا يجب عليك استخدام Parameters لبناء الاستعلامات
#1
Bug 
بسم الله الرحمن الرحيم 
السلام عليكم ورحمة الله وبركاتة 

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


تقديم : 

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

واحدة من اكبر نقط الضعف vulnerability عند بناء استعلامات في الكود هو تمرير بيانات من المستخدم مباشرة الى نص الاستعلام ، يجب ان تستحضر دائما ان نص الاستعلام ما هو الا نص String ، اذا اُدخل فيه نص استعلام اخر صالح سيقبله محرك قاعدة البيانات ايضا 


حينما تضع مربع نص في البرنامج ، تأخذ منه المدخل ، وتضعه مباشرة في الاستعلام ، فانت فعليا فتحت نافذه من مربع النص هذا الى قاعدة البيانات ، اذا كان المستخدم جيدا بما فيه الكفاية يمكنه بخطوات غاية البساطة كما سأشرح في هذا الموضوع فعل كل شيء بقاعدة بياناتك ، بما يتضمنه سرقة البيانات او حتى ضياعها


كود :
Dim CommandString As String = "SELECT [Name] FROM [Users] WHERE [Name]='" & txtName.Text & "'"

اذا كنت لازلت تبني نص الاستعلام بهذه الطريقة فانت بحاجة الى ان تتوقف عن ذلك فورا ،

للتجربة ، سنحاكي نظام حسابات بسيط به فورم تسجيل دخول وفورم الحسابات وقاعدة بيانات بها جدول للمستخدمين وجدول للحسابات

 انشأ مشروع جديد ، عدل فورم تسجيل الدخول الى الشكل التالي :


   


وفورم الحسابات :


   


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


   


وضعنا به بيانات مستخدمين للتجربة :



   


جدول الحسابات :


   


تصميم برنامج ضعيف ضد SQL INJECTION : 

حقن الاستعلامات او Sql Injection هي طريقة لمهاجمة قواعد البيانات عن طريق استغلال المدخلات الغير محمية ، بحيث تقوم بادخال في نص الاستعلام ما يقوم بتغير وظيفته او اضافة وظيفة جديده له تخدم المهاجم

في برنامجنا البسيط نريد ان نتأكد من ان المستخدم الذي يحاول تسجيل الدخول موجود فعلا في جدول المستخدمين ، وربما ايضا التأكد من صلاحياته

لفعل ذلك نقوم بعمل استعلام يعود باسم المستخدم في حال تطابق اسم المستخدم المدخل مع احد اعمدة جدول المستخدمين وكذلك كلمة السر المدخلة مع نفس العمود

(وجب ان انبه مرة اخرى ان هذه هي الطريقة الخاطئة ، للتجربة فقط)

يكون نص الاستعلام :

كود :
       Dim CommandString As String = "SELECT [Name] FROM [Users] WHERE [Name]='" & txtName.Text & "' AND [Password]='" & txtPassword.Text & "'"

ثم نكمل باقي الكود لاتمام العملية ، ExecuteScalar تعود باول خلية في اول صف وهذا ما نريده :

كود :
       Dim conn As New SqlConnection(ConnectionString)
       Dim Command As New SqlCommand(CommandString, conn)


       conn.Open()
       Dim UserName As String = Command.ExecuteScalar()
       conn.Close()

الان نختبر اذا كان UserName يحمل قيمة هذا معناه ان المستخدم موجود فعلا ، وبالتالي نفتح الفورم الرئيسي ونمرر له اسم المستخدم :

كود :
       If UserName IsNot Nothing Then

           Dim frm As New MainForm
           frm.lblUserName.Text = UserName
           frm.Show()

           Close()

       Else
           MsgBox("اسم المستخدم او كلمة المرور غير صحيحة")
       End If

كود بسيط جدا ،

الان شغل البرنامج واكتب اسم مستخدم خاطيء :

   

الان اكتب اسم مستخدم وكلمة سر من جدول المستخدمين فعلا :

   
   

ممتاز جدا الى الان لا مشاكل ولكن انتظر


مهاجمة البرنامج باستخدام SQL INJECTION: 


تعطيل العمل:

طيب جرب افتح البرنامج من جديد وادخل الرمز ' فقط في اسم المستخدم واضغط تسجيل الدخول :

   
   

ينهار البرنامج ويعطيك الخطأ التالي : 

إقتباس :
Unclosed quotation mark after the character string '' AND [Password]=''.

Incorrect syntax near '' AND [Password]=''.

ما معنى ذلك ؟ يخبرك البرنامج ان هناك قوس نص ' غير مغلق ، ادركت حجم المصيبة ؟ قاعدة البيانات اعتبرت مدخل المستخدم جزء من الاستعلام وليس مجرد مدخل


تخطي التسجيل :

هل هذا اسوأ ما قد يحدث ؟

بالطبع لا ، من الممكن ببساطة في مثالنا ان نتخطى عملية التسجيل اصلا ، 

افتح البرنامج من جديد و ادخل الجملة التالية في مربع اسم المستخدم ، وهي الاشهر فيما يتعلق بال SQL INJECTION : 
PHP كود :
' OR 1=1 -- 

ثم اضغط تسجيل دخول


   
   

دخلنا فعلا دون اسم مستخدم او كلمة سر ! كيف حدث هذا 

دعنا نراجع نص الاستعلام الذي استخدمناه في حال ادخال اسم المستخدم : user1 وكلمة السر : 12345678

PHP كود :
SELECT [NameFROM [UsersWHERE [Name]='user1' AND [Password]='12345678' 

طبيعي جدا ، طيب ماذا يحدث في حالة ادخال :
' OR 1=1 -- 
يصبح شكل نص الاستعلام كالتالي :

PHP كود :
SELECT [NameFROM [UsersWHERE [Name]='' OR 1=-- ' AND [Password]='' 


' نغلق بها قوس النصوص المفتوح و OR 1=1 نجعل بها الشرط متحقق دائما و -- تقوم بتحويل باقي النص الى تعليق ، وبالتالي يقوم الاستعلام بجلب اول مستخدم في جدول المستخدمين وتسجيل الدخول على انه هو 

تسجيل الدخول كأدمن :

ليس هذا اسوأ كوابيسك بعد ،
يمكن ايضا تسخيل الدخول بصلاحيات الادمن ، شغل البرنامج وادخل التالي :

PHP كود :
admin' -- 


   
   


 الان نحن مسجلين كأدمن ، ما حدث هو ان نص الاستعلام اصبح :

كود :
SELECT [Name] FROM [Users] WHERE [Name]='admin' --' AND [Password]=''

نسجل باسم الادم ونلغي الجزء الخاص بالتحقق من كلمة السر عن طريق --



مسح جدول كامل :

اذا كنت تظن ان ما سبق هو اسوأ كوابيسك ، فانت مخطأ للغاية
العلامة ; تستخدم لانهاء سطر الاستعلام الحالي و بدأ سطر استعلام جديد ، مثل استعلام Drop فعلا لحذف جدول
شغل البرنامج وادخل في مربع اسم المستخدم :

PHP كود :
' ; DROP TABLE Accounts ; -- 

اضغط تسجيل دخول ، 

   

لم يتم تسجيل الدخول ولكن ليس هذا ما نبحث عنه 
اذهب لقائمة الجداول تجد جدول Accounts اختفى !


   


طيب ما الحل ؟

استخدام ال Parameters : 

الفكرة هنا هو حل المشكلة حلا جذريا ، وهو عن طريق عدم تمرير القيم وسط الاستعلام وانما تعريف بارمترات @ ومن ثم اضافتها بالطريقة التالية :



كود :
       Dim CommandString As String = "SELECT [Name] FROM [Users] WHERE [Name]=@Name AND [Password]=@Password"

       Dim conn As New SqlConnection(ConnectionString)
       Dim Command As New SqlCommand(CommandString, conn)

       Command.Parameters.AddWithValue("@Name", txtName.Text)
       Command.Parameters.AddWithValue("@Password", txtPassword.Text)

       conn.Open()
       Dim UserName As String = Command.ExecuteScalar()
       conn.Close()

       If UserName IsNot Nothing Then

           Dim frm As New MainForm
           frm.Show()

           frm.lblUserName.Text = UserName

           Close()
       Else
           MsgBox("اسم المستخدم او كلمة المرور غير صحيحة")
       End If

الان سيتم معاملة النصوص المدخلة من المستخدم حرفيا ،

اذا ادخل المستخدم مثلا ' Or 1=1 -- فهذا يعني انه يقصد مستخدم اسمه ' Or 1=1 -- وبالتالي عندما نبحث عنه لن نجد اي مستخدم بهذا الاسم ، فنصبح بامان من ال SQL INJECTION



   


الخلاصة : 

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


ملاحظات : 

يوجد طرق اضافية تقيك من هجمات ال SQL INJECTION التقليدية مثل :

1. استخدام ORM : Object-relational Mapper مثل Entity Framework او Linq to Sql او Dapper ، لانك لاتمرر قيم لاستعلامات اصلا بل تعتمد على الكائنات

2. تطهير المدخلات Input sanitization : يعتمد هذا الاسلوب على تنقية مدخلات المستخدم من الرموز التي يمكن ان تغير وظيفة الاستعلام


مراجع : 

مرجع لاساليب حقت الاستعلامات SQL INJECTION :

https://www.netsparker.com/blog/web-secu...eat-sheet/

هذا الموقع يشرح ال SQL INJECTION ويمكنك تجريبه عليه :

https://www.hacksplaining.com/exercises/sql-injection

هذا الموقع ايضا ليس محمي يمكنك تجريب تسجيل الدخول عليه :

https://demo.testfire.net/

تم اضافة ملف قاعدة البيانات
قم بعمل Attach لتجربة البرنامج ، او غير نص الاتصال


الملفات المرفقة
.zip   SqlInjectionDB.zip (الحجم : 424.44 ك ب / التحميلات : 18)
.zip   SqlInjectionExample.zip (الحجم : 61.92 ك ب / التحميلات : 20)
الرد
#2
بارك الله فيك و لك و جزاك خير الجزاء و زادك من علمه و فضله و نفع بك الأمة الإسلامية من محيطها إلى خليجها إن شاء الله
الرد
تم الشكر بواسطة: Anas Mahmoud , ابراهيم ايبو
#3
(22-09-20, 08:26 PM)عبد العزيز البسكري كتب :
بارك الله فيك و لك و جزاك خير الجزاء و زادك من علمه و فضله و نفع بك الأمة الإسلامية من محيطها إلى خليجها إن شاء الله

ولك بمثله ان شاء الله استاذي

تحياتي
الرد
#4
موضوع شيق شدني وأسر فؤادي، فجعل ما قدمت في ميزان حسناتك
إذا طُعِنتَ من الخلفِ فاعلمْ أنك في المقدمةِ
الرد
#5
(23-09-20, 03:42 AM)مصمم هاوي كتب : موضوع شيق شدني وأسر فؤادي، فجعل ما قدمت في ميزان حسناتك

ولك بمثله اخي الكريم
الرد
#6
السلام عليكم

كفييت ووفيت 

شرح مفصل  واثبات بالامثلة والتجرية 


الله يعطيك الصحة والعافية ويبارك لك في علمك ويكت اجرك
الرد
تم الشكر بواسطة: Anas Mahmoud
#7
(01-10-20, 11:12 PM)sendbad100 كتب :
السلام عليكم

كفييت ووفيت 

شرح مفصل  واثبات بالامثلة والتجرية 


الله يعطيك الصحة والعافية ويبارك لك في علمك ويكت اجرك

ولك بمثله اخي الكريم
الرد
تم الشكر بواسطة:


المواضيع المحتمل أن تكون متشابهة .
الموضوع : الكاتب الردود : المشاهدات : آخر رد
  [VB.NET] كيفية استخدام اداوات ديف اكسبريس devexpressلادخال السجلات الى قاعدة بيانات نوع اكسس 13adam123 0 400 29-03-20, 12:50 PM
آخر رد: 13adam123
  طريقة استخدام مكتبة internet download manager في برنامجك kslawy 3 2,356 30-07-19, 07:06 AM
آخر رد: سعود
  [درس فيديو] كيفية استخدام الجملة الشرطية if alims 1 771 22-07-19, 06:38 AM
آخر رد: سعود
  شرح بالصور لطريقة استخدام و كتابة قصاصات الكود Code Snippet المرفقة مع VB.Net Mohamad Anan 4 3,104 07-12-18, 08:45 AM
آخر رد: محمد خرد
  [مقال] لنعيد إجراءات وسهولة استخدام ADODB في ADO.NET ebrahem b alabdaly 5 3,254 13-03-15, 09:54 PM
آخر رد: abdala
  [مقال] كلام في استخدام الدوال والروتينات function and sub سعود 4 2,980 04-05-14, 11:06 PM
آخر رد: Ali Wisam
  انتبه ( لاتنسى الرموز فقد توفر عليك الكثير من العناء ) ali.alfoly 3 1,620 25-05-13, 01:08 PM
آخر رد: shaker.soft
  كيفية استخدام ملف التعريف الخاص بالتطبيق لاستهداف نسخة معينة من الفريموورك- ينطبق على RaggiTech 0 1,357 05-10-12, 01:46 AM
آخر رد: RaggiTech
  ملاحظة سريعة - تمكين برنامجك من استخدام صلاحيات مدير على فيستا RaggiTech 0 1,251 05-10-12, 01:31 AM
آخر رد: RaggiTech
  يمكننا استخدام فيجول بايزيك 2008 لإنشاء صفحات أشرطة إضافية لـ Excel 2007 RaggiTech 0 1,414 05-10-12, 01:14 AM
آخر رد: RaggiTech

التنقل السريع :


يقوم بقرائة الموضوع: بالاضافة الى ( 1 ) ضيف كريم