logo

حقن SQL

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

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



حقن SQL' title=

مثال من العالم الحقيقي:

في عام 2019، حدث خرق بيانات Capital One بسبب تطبيق ويب تمت تهيئته بشكل خاطئ مما سمح للمهاجم باستغلال ثغرة أمنية في إدخال SQL. وأدى ذلك إلى تسرب البيانات الشخصية لأكثر من 100 مليون عميل بما في ذلك الأسماء والعناوين ودرجات الائتمان.

مستوى أمان حقن SQL

يوفر DVWA أربعة مستويات أمان لحقن SQL لمساعدة المتعلمين على معرفة مدى تأثير وسائل الحماية المختلفة على الهجمات:



1. أمان منخفض

يأخذ التطبيق مدخلاتك ويضعها مباشرة في استعلام SQL دون أي تصفية.

$id = $_GET['id'];$query = 'SELECT first_name last_name FROM users WHERE user_id = '$id';';
  • الدخول ': يكسر الاستعلام ويجعل قاعدة البيانات ترمي خطأً يكشف أنها معرضة للخطر.
  • الدخول 1' OR '1'='1: يخدع الاستعلام ليصبح صحيحًا دائمًا حتى يتم إرجاع جميع المستخدمين.
  • الدخول 1' UNION SELECT user password FROM users--: ينضم إلى استعلام آخر لجلب البيانات المخفية مثل أسماء المستخدمين وكلمات المرور.

2. الأمن المتوسط

يطبق التطبيق تعقيم الإدخال الأساسي باستخدام وظائف مثلaddslashes()للهروب'.

$id = addslashes($_GET['id']);$query = 'SELECT first_name last_name FROM users WHERE user_id = '$id';';

كيف يمكن الهجوم:



بسيطة'لن يعمل الحقن بعد الآن (لأنه يصبح').

لكن لا يزال بإمكان المهاجمين التجاوز باستخدام الحقن الرقمي (نظرًا لأن الأرقام لا تحتاج إلى علامات اقتباس).
مثال:

مصفوفة إرجاع جافا
1 OR 1=1

لا يزال هذا يُرجع كافة السجلات.

3. إجراءات أمنية مشددة

يستخدم التطبيق عبارات معدة (استعلامات ذات معلمات) للتعامل بأمان مع مدخلات المستخدم.

$stmt = $pdo->prepare('SELECT first_name last_name FROM users WHERE user_id = ?');$stmt->execute([$id]);

هجوم:

محاولات مثل' OR 1=1أوUNION SELECTلم تعد تعمل.

يعامل الاستعلام كافة المدخلات كبيانات وليس كود SQL.

أنواع حقن SQL

هناك أنواع مختلفة من حقن SQL

1. حقن SQL القائم على الأخطاء

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

كيف يعمل

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

راخي سوانت
  1. تحديد المدخلات الضعيفة: يعثر المهاجم على حقل إدخال مثل شريط البحث أو معلمة URL التي تتفاعل مباشرة مع قاعدة البيانات دون إجراء عملية معالجة مناسبة للإدخال.
  2. إدخال حمولة ضارة: يقوم المهاجم بإدخال حرف خاص (مثل اقتباس واحد') أو دالة معروفة بأنها تسبب خطأ في قاعدة البيانات.
  3. تحليل الخطأ: تقوم قاعدة البيانات غير القادرة على معالجة الاستعلام التالف بإرجاع رسالة خطأ مفصلة. يمكن أن تكشف هذه الرسالة معلومات مهمة مثل:
    • نظام قاعدة البيانات (مثل MySQL Oracle SQL Server).
    • نسخة قاعدة البيانات.
    • يتم تنفيذ استعلام SQL الكامل.
    • أخطاء بناء الجملة المحددة التي يمكن استخدامها لفهم أسماء الجداول أو الأعمدة.
  4. تحسين الهجوم: باستخدام المعلومات التي تم جمعها من رسالة الخطأ، يمكن للمهاجم تحسين حمولته لاستخراج المزيد من البيانات مثل أسماء المستخدمين وكلمات المرور.

مثال:

الخطوة 1: إعداد بيئتك

  • قم بتشغيل DVWA. يتم الوصول إليه عادةً عن طريق الانتقال إلى عنوان URL مثلhttp://localhost/dvwaفي المتصفح الخاص بك.
ملف' loading='lazy' title=
  • قم بتسجيل الدخول إلى DVWA باستخدام بيانات الاعتماد الافتراضية:admin/password.
ملف' loading='lazy' title=
  • انتقل إلى علامة التبويب DVWA Security واضبط مستوى الأمان على مستوى منخفض. وهذا سيضمن سهولة استغلال الثغرات الأمنية.
ملف' loading='lazy' title=

الخطوة 2: تحديد الثغرة الأمنية

تحتوي صفحة حقن SQL على مربع إدخال بسيط يمكنك من خلاله إدخال معرف المستخدم. من المحتمل أن يكون استعلام الواجهة الخلفية شيئًا من هذا القبيلSELECT * FROM users WHERE id = 'user_input'

  • أدخل معرفًا صالحًا مثل1في مربع الإدخال وانقر فوق "إرسال". يجب أن تشاهد تفاصيل المستخدم بالمعرف 1.
ملف' loading='lazy' title=

مصدر حقن SQL

PHP
 $id = $_REQUEST[ 'id' ]; switch ($_DVWA['SQLI_DB']) { case MYSQL: // Check database $query = 'SELECT first_name last_name FROM users WHERE user_id = '$id';'; $result = mysqli_query($GLOBALS['___mysqli_ston'] $query ) or die( '
' . ((is_object($GLOBALS['___mysqli_ston'])) ? mysqli_error($GLOBALS['___mysqli_ston']) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '
'
); // Get results while( $row = mysqli_fetch_assoc( $result ) ) { // Get values $first = $row['first_name']; $last = $row['last_name']; // Feedback for end user echo '
ID: {$id}  
First name:
{$first}
Surname:
{$last}
'
; } mysqli_close($GLOBALS['___mysqli_ston']); break; case SQLITE: global $sqlite_db_connection; #$sqlite_db_connection = new SQLite3($_DVWA['SQLITE_DB']); #$sqlite_db_connection->enableExceptions(true); $query = 'SELECT first_name last_name FROM users WHERE user_id = '$id';'; #print $query; try { $results = $sqlite_db_connection->query($query); } catch (Exception $e) { echo 'Caught exception: ' . $e->getMessage(); exit(); } if ($results) { while ($row = $results->fetchArray()) { // Get values $first = $row['first_name']; $last = $row['last_name']; // Feedback for end user echo '
ID: {$id}  
First name:
{$first}
Surname:
{$last}
'
; } } else { echo 'Error in fetch '.$sqlite_db->lastErrorMsg(); } break; } } ode ?>
  • حاول الآن قطع الاستعلام. أدخل اقتباس واحد'في مربع الإدخال وتقديم.
ملف' loading='lazy' title=

يصبح الاستعلام:

SELECT * FROM users WHERE id = ''';

هنا ترى قاعدة البيانات عرض أسعار إضافيًا ولا تعرف كيفية إكمال الاستعلام.

أنواع الصلات في rdbms

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

وهذا ما يسمى حقن SQL القائم على الأخطاء للأسباب التالية:

  • يرسل المهاجم إدخالاً غير صالح (')
  • قاعدة البيانات يلقي خطأ
  • يؤدي هذا الخطأ إلى تسرب معلومات مفيدة حول قاعدة البيانات (مثل نوع عدد قاعدة بيانات بنية الأعمدة وما إلى ذلك)

2. حقن SQL القائم على الاتحاد

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

  • يحتوي كلا الاستعلامين على نفس عدد الأعمدة
  • تحتوي الأعمدة على أنواع بيانات متشابهة
  • الأعمدة بنفس الترتيب

مشغل الاتحاد : الUNIONيتم استخدام عامل التشغيل لدمج مجموعة النتائج المكونة من اثنين أو أكثرSELECTالبيانات.

  • كلSELECTبيان داخلUNIONيجب أن يكون لها نفس عدد الأعمدة
  • يجب أن تحتوي الأعمدة على أنواع بيانات متشابهة
  • يجب أن تكون الأعمدة بنفس الترتيب
SELECT column_name(s) FROM table1UNIONSELECT column_name(s) FROM table2

مثال:

الخطوة 1: أولاً علينا العثور على عدد أعمدة الجدول الموجود في موقع الويب لحقن حقن SQL المستندة إلى UNION:

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

 SELECT * FROM users WHERE id = 'user_input'

حاول الآن قطع الاستعلام. أدخل اقتباس واحد'في مربع الإدخال وتقديم.

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

You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''' at line 1

الخطوة 2: استخدمUNIONالكلمة الأساسية لاكتشاف عدد الأعمدة

لاستخدامUNIONالكلمة الأساسية (الخطوة التالية الشائعة) تحتاج إلى معرفة عدد الأعمدة في الاستعلام الأصلي. يمكنك معرفة ذلك باستخدامORDER BYبند

"اي بي سي" بالأرقام
  • حاول فرز النتائج حسب العمود
1: 1 ORDER BY 1. 
  • يُقدِّم. يجب أن تعمل.
ملف' loading='lazy' title=

مصدر حقن SQL

PHP
 if( isset( $_REQUEST[ 'Submit' ] ) ) { // Get input $id = $_REQUEST[ 'id' ]; switch ($_DVWA['SQLI_DB']) { case MYSQL: // Check database $query = 'SELECT first_name last_name FROM users WHERE user_id = '$id';'; $result = mysqli_query($GLOBALS['___mysqli_ston'] $query ) or die( '
' . ((is_object($GLOBALS['___mysqli_ston'])) ? mysqli_error($GLOBALS['___mysqli_ston']) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '
'
); // Get results while( $row = mysqli_fetch_assoc( $result ) ) { // Get values $first = $row['first_name']; $last = $row['last_name']; // Feedback for end user echo '
ID: {$id}  
First name:
{$first}
Surname:
{$last}
'
; } mysqli_close($GLOBALS['___mysqli_ston']); break; case SQLITE: global $sqlite_db_connection; #$sqlite_db_connection = new SQLite3($_DVWA['SQLITE_DB']); #$sqlite_db_connection->enableExceptions(true); $query = 'SELECT first_name last_name FROM users WHERE user_id = '$id';'; #print $query; try { $results = $sqlite_db_connection->query($query); } catch (Exception $e) { echo 'Caught exception: ' . $e->getMessage(); exit(); } if ($results) { while ($row = $results->fetchArray()) { // Get values $first = $row['first_name']; $last = $row['last_name']; // Feedback for end user echo '
ID: {$id}  
First name:
{$first}
Surname:
{$last}
'
; } } else { echo 'Error in fetch '.$sqlite_db->lastErrorMsg(); } break; } } ?>
  • زيادة الرقم:
 1 ORDER BY 2. 

يُقدِّم. يجب أن تعمل.

ملف' loading='lazy' title=
  • استمر في الزيادة حتى تحصل على خطأ. على سبيل المثال1 ORDER BY 4قد يعطيك:Unknown column '4' in 'order clause'
  • وهذا يعني أن الاستعلام يحتوي على 3 أعمدة.

3. حقن SQL المستند إلى الأعمى

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

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

  1. SQLi الأعمى القائم على المنطق: يقوم المهاجم بإدخال استعلام SQL يُرجع ملف حقيقي أو خطأ شنيع نتيجة. تتغير استجابة تطبيق الويب بناءً على ما إذا كان الاستعلام صحيحًا أم خطأ. على سبيل المثال، قد تعرض الصفحة رسالة مختلفة أو تعرض تخطيطًا مختلفًا.
  2. SQLi للمكفوفين على أساس الوقت: يقوم المهاجم بإدخال استعلام SQL يؤدي إلى قيام قاعدة البيانات بتنفيذ إجراء مستهلك للوقت (مثل ملفSLEEP()وظيفة) إذا تم استيفاء الشرط. يراقب المهاجم الوقت الذي يستغرقه تحميل الصفحة لتحديد ما إذا كان الشرط الذي تم إدخاله صحيحًا أم خطأ.

مثال:

تخيل صفحة تسجيل الدخول حيث تقوم بإدخال اسم المستخدم وكلمة المرور. يقوم التطبيق بإنشاء استعلام SQL مثل هذا:

SELECT * FROM users WHERE username = 'user_input' AND password = 'password_input'

قد يتضمن حقن SQL الأعمى معالجة ملفuser_inputالحقل لطرح سؤال على قاعدة البيانات.

بدلاً من الحصول على رد مباشر، قد يحاول المهاجم القيام بشيء مثل هذا:

user_input = 'admin' AND 1=1; --

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

user_input = 'admin' AND 1=2; --

إذا أظهرت الصفحة خطأ أو تتصرف بشكل مختلف، فإن المهاجم يعرف ذلك1=2هو أ خطأ شنيع إفادة.

ملف' loading='lazy' title=

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

تأثير هجمات حقن SQL

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

منع هجمات حقن SQL

هناك العديد من أفضل الممارسات لمنع هجمات حقن SQL:

1. استخدم البيانات المعدة والاستعلامات ذات المعلمات

تضمن البيانات المعدة والاستعلامات ذات المعلمات أن يتم التعامل مع مدخلات المستخدم كبيانات وليس كجزء من استعلام SQL. هذا الأسلوب يلغي مخاطر حقن SQL.

مثال في PHP (باستخدام MySQLi):

$stmt = $conn->prepare('SELECT * FROM users WHERE username = ? AND password = ?'); $stmt->bind_param('ss' $username $password); $stmt->execute();

2. توظيف الإجراءات المخزنة

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

سلسلة فيبوناتشي في ج

مثال:

CREATE PROCEDURE GetUserByUsername (IN username VARCHAR(50)) BEGIN SELECT * FROM users WHERE username = username; END;

3. التحقق من صحة إدخال القائمة البيضاء

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

4. استخدم أطر عمل ORM

أطر رسم الخرائط العلائقية للكائنات (ORM) مثل السبات أو إطار الكيان يمكن أن يساعد في منع حقن SQL عن طريق التعامل تلقائيًا مع إنشاء الاستعلام مما يمنع إنشاء الاستعلام الديناميكي.

5. تقييد امتيازات قاعدة البيانات

منح الحد الأدنى من أذونات قاعدة البيانات المطلوبة للمستخدمين. تأكد من أن التطبيقات يمكنها فقط تنفيذ الإجراءات الضرورية (مثل SELECT INSERT) وتقييد الأذونات مثل DROP TABLE أو ALTER.

6. معالجة الأخطاء

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