أحدث البرامج التعليمية وتطوير الشبكة
 

SQL حقنة


وحقن SQL يمكن أن تدمر قاعدة البيانات الخاصة بك.


SQL في صفحات الويب

في الفصول السابقة، كنت قد تعلمت لاسترداد البيانات قاعدة البيانات (والتحديث)، وذلك باستخدام SQL.

عندما يستخدم SQL لعرض البيانات على صفحة على شبكة الإنترنت، فإنه من الشائع للسماح للمستخدمين على شبكة الإنترنت مدخلاتها قيم البحث الخاصة.

منذ عبارات SQL هي النص فقط، فمن السهل، مع قطعة صغيرة من شفرة الحاسوب، لتغيير البيانات SQL حيوي لتوفير للمستخدم مع البيانات المختارة:

كود الخادم

txtUserId = getRequestString("UserId");
txtSQL = "SELECT * FROM Users WHERE UserId = " + txtUserId;

في المثال أعلاه، يخلق العبارة حدد بإضافة متغير (txtUserId) إلى سلسلة مختارة. المتغير يتم جلب من إدخال المستخدم (طلب) إلى الصفحة.

ما تبقى من هذا الفصل يصف المخاطر المحتملة لاستخدام مدخلات المستخدم في عبارات SQL.


حقن SQL

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

يمكن أن أوامر SQL حقن يغير عبارة SQL وتعرض أمن تطبيقات الويب.


حقن SQL مرتكز على 1 = 1 هو دائما صحيح

ننظر في المثال أعلاه، واحد مزيد من الوقت.

دعنا نقول أن الغرض الأصلي من قانون كان لإنشاء عبارة SQL لاختيار المستخدم مع معرف مستخدم معين.

إذا كان هناك أي شيء لمنع المستخدم من إدخال "wrong" المدخلات، ويمكن للمستخدم إدخال بعض "smart" المدخلات مثل هذا:

معرف المستخدم:

النتيجة الخادم

SELECT * FROM Users WHERE UserId = 105 or 1=1

وSQL أعلاه هو صالح. فإنه سيعود كافة الصفوف من الجدول المستخدمين، منذ حيث 1 = 1 غير صحيحا دائما.

هل المثال أعلاه يبدو خطيرا؟ ماذا لو كان الجدول يحتوي على المستخدمين أسماء وكلمات السر؟

عبارة SQL أعلاه هو إلى حد كبير نفس هذا:

SELECT UserId, Name, Password FROM Users WHERE UserId = 105 or 1=1

وقال القراصنة الذكية قد تحصل الوصول إلى جميع أسماء المستخدمين وكلمات السر في قاعدة بيانات ببساطة عن طريق إدخال 105 أو 1 = 1 في مربع الإدخال.


حقن SQL استنادا إلى ""="" هو دائما صحيح

هنا هو البناء المشترك، وتستخدم للتحقق من المستخدم تسجيل الدخول إلى موقع على شبكة الإنترنت:

اسم المستخدم:

كلمه السر:

كود الخادم

uName = getRequestString("UserName");
uPass = getRequestString("UserPass");

sql = "SELECT * FROM Users WHERE Name ='" + uName + "' AND Pass ='" + uPass + "'"

وقال القراصنة الذكية قد تحصل الحصول على أسماء المستخدمين وكلمات السر في قاعدة بيانات ببساطة عن طريق إدخال "أو ""=" في مربع النص اسم المستخدم أو كلمة المرور.

سوف رمز في الملقم إنشاء عبارة SQL صالح من هذا القبيل:

نتيجة

SELECT * FROM Users WHERE Name ="" or ""="" AND Pass ="" or ""=""

وSQL نتيجة غير صالح. فإنه سيعود كافة الصفوف من الجدول المستخدمين، منذ أين "" = "" هو دائما صحيحا.


حقن SQL استنادا إلى البيانات SQL دفعات

تدعم معظم قواعد البيانات SQL بيان المجمع لل، مفصولة بفاصلة منقوطة.

مثال

SELECT * FROM Users; DROP TABLE Suppliers

وSQL فوق سيعود كافة الصفوف في الجدول المستخدمين، ومن ثم حذف جدول يسمى الموردين.

لو كان لدينا رمز الخادم التالية:

كود الخادم

txtUserId = getRequestString("UserId");
txtSQL = "SELECT * FROM Users WHERE UserId = " + txtUserId;

والإدخال التالية:

معرف المستخدم:

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

نتيجة

SELECT * FROM Users WHERE UserId = 105; DROP TABLE Suppliers

المعلمات من أجل حماية

بعض مطوري الويب استخدام "blacklist" من كلمات أو أحرف للبحث عنها في SQL المدخلات، لمنع وقوع هجمات حقن SQL.

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

(في الواقع يجب أن يكون قانونيا تماما لإدخال عبارة SQL في حقل قاعدة البيانات.)

الطريقة المؤكدة الوحيدة لحماية موقع على شبكة الإنترنت من هجمات حقن SQL، هو استخدام معلمات SQL.

المعلمات SQL هي القيم التي تمت إضافتها إلى استعلام SQL في وقت التنفيذ، في الطريقة التي تسيطر عليها.

ASP.NET الشفرة مثال

txtUserId = getRequestString("UserId");
txtSQL = "SELECT * FROM Users WHERE UserId = @0";
db.Execute(txtSQL,txtUserId);

لاحظ أن المعلمات تتمثل في عبارة SQL التي كتبها a @ علامة.

محرك SQL يتحقق كل معلمة للتأكد من أنه هو الصحيح لعمود ويتم التعامل حرفيا، وليس كجزء من SQL ليتم تنفيذها.

مثال آخر

txtNam = getRequestString("CustomerName");
txtAdd = getRequestString("Address");
txtCit = getRequestString("City");
txtSQL = "INSERT INTO Customers (CustomerName,Address,City) Values(@0,@1,@2)";
db.Execute(txtSQL,txtNam,txtAdd,txtCit);

لقد علمت للتو لتجنب حقن SQL. واحدة من أهم نقاط الضعف الموقع.


أمثلة

الأمثلة التالية توضح كيفية بناء استعلامات بمعلمات في بعض لغات الويب المشتركة.

بيان SELECT في ASP.NET:

txtUserId = getRequestString("UserId");
sql = "SELECT * FROM Customers WHERE CustomerId = @0";
command = new SqlCommand(sql);
command.Parameters.AddWithValue("@0",txtUserID);
command.ExecuteReader();

INSERT INTO بيان في ASP.NET:

txtNam = getRequestString("CustomerName");
txtAdd = getRequestString("Address");
txtCit = getRequestString("City");
txtSQL = "INSERT INTO Customers (CustomerName,Address,City) Values(@0,@1,@2)";
command = new SqlCommand(txtSQL);
command.Parameters.AddWithValue("@0",txtNam);
command.Parameters.AddWithValue("@1",txtAdd);
command.Parameters.AddWithValue("@2",txtCit);
command.ExecuteNonQuery();

INSERT INTO بيان في PHP:

$stmt = $dbh->prepare("INSERT INTO Customers (CustomerName,Address,City)
VALUES (:nam, :add, :cit)");
$stmt->bindParam(':nam', $txtNam);
$stmt->bindParam(':add', $txtAdd);
$stmt->bindParam(':cit', $txtCit);
$stmt->execute();