VIEW ها و حملات SQL Injection

21 فروردین 1398
درسنامه درس 27 از سری آموزش زبان SQL
SQL-Language-sql-injection-create-view

با سلام خدمت شما همراهان روکسو، در این قسمت از سری آموزشی زبان SQL می خواهیم در رابطه با دو مبحث کلی صحبت کنیم:

  • دستور CREATE VIEW و کاربرد آن
  • مبحث SQL Injection و یا تزریق SQL

CREATE VIEW چیست؟

در زبان SQL مبحثی به نام view وجود دارد. view ها جدول های مجازی (virtual) هستند که بر اساس نتایج برگشتی (result-set) یک دستور SQL به وجود می آیند. view ها دقیقا مانند جدول های واقعی دارای ردیف و ستون هستند و از آنجایی که نتایج برگشتی یک دستور SQL حساب می شوند، فیلد های یک view فیلد های یک یا چند جدول دیگر در پایگاه داده هستند. همچنین اگر داده های یک view از یک جدول آمده باشند، می توانید با استفاده از توابع مختلف، WHERE و JOIN داده ها را به نمایش بگذارید.

ساختار کلی برای ساختن یک view از این قرار است:

CREATE VIEW view_name AS
SELECT column1, column2, ...
FROM table_name
WHERE condition;

نکته: view ها همیشه داده های بروز شده را نمایش می دهند چرا که با هر بار درخواست یک کاربر برای ساخت view، موتور پایگاه داده تمام داده ها را دوباره می سازد.

مثال هایی از کار با view

به مثال زیر توجه کنید؛ در این مثال می خواهیم یک view را ایجاد کنیم که تمام مشتریان برزیلی ما را نمایش دهد:

CREATE VIEW [Brazil Customers] AS
SELECT CustomerName, ContactName
FROM Customers
WHERE Country = "Brazil";

اجرای این دستور در پایگاه داده ی Northwind

با اجرای این دستور یک view از مشتریان برزیلی ساخته اید اما برای نمایش دادن این view باید از دستور زیر استفاده کنید:

SELECT * FROM [Brazil Customers];

اجرای این دستور در پایگاه داده ی Northwind

در مثال بعدی می خواهیم view ای ایجاد کنیم که تمام محصولات جدول Products را که قیمتشان بیشتر از قیمت میانگین باشد انتخاب کند:

CREATE VIEW [Products Above Average Price] AS
SELECT ProductName, Price
FROM Products
WHERE Price > (SELECT AVG(Price) FROM Products);

اجرای این دستور در پایگاه داده ی Northwind

حالا برای نمایش این view می توانیم بگوییم:

SELECT * FROM [Products Above Average Price];

اجرای این دستور در پایگاه داده ی Northwind

بروزرسانی یا حذف view

شما می توانید با استفاده از دستور CREATE OR REPLACE VIEW اقدام به بروزرسانی view های خود کنید:

CREATE OR REPLACE VIEW view_name AS
SELECT column1, column2, ...
FROM table_name
WHERE condition;

به طور مثال، کد زیر ستون City را به جدول مشتریان برزیلی که قبلا ساخته ایم، اضافه می کند:

CREATE OR REPLACE VIEW [Brazil Customers] AS
SELECT CustomerName, ContactName, City
FROM Customers
WHERE Country = "Brazil";

اجرای این دستور در پایگاه داده ی Northwind

همچنین برای حذف view ها از دستور زیر استفاده می شود:

DROP VIEW view_name;

به طور مثال کد زیر جدول Brazil Customers را حذف می کند:

DROP VIEW [Brazil Customers];

اجرای این دستور در پایگاه داده ی Northwind

SQL Injection چیست؟

تزریق SQL یا SQL Injection تکنیکی برای حمله به پایگاه های داده است و می تواند پایگاه داده ی شما را نابود کند. متاسفانه این نوع حملات از شایع ترین حملات دنیای وب هستند که از طریق تزریق کدهای SQL خرابکارانه به پایگاه داده انجام می شوند.

حتما با خودتان می گویید کاربران که به محیط ادمین دسترسی ندارند پس چطور کدهای SQL را در سایت ما اجرا می کنند؟ از قسمت input یا ورودی داده های کاربران غافل شده اید!

حملات SQL Injection معمولا زمانی رخ می دهند که شما از کاربر می خواهید username یا email یا اطلاعاتی را در فرمی وارد کند و کاربر به جای وارد کردن آن اطلاعات، کدهای SQL ای را وارد می کند که شما ندانسته در سیستم خود اجرا خواهید کرد.

به طور مثال کد زیر یک دستور SELECT است که یک متغیر (txtUserId) را به کد SQL اضافه می کند. این متغیر را از طریق تابع getRequestString و  از کاربر دریافت کرده ایم:

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

تا اینجای کار این کد کاملا صحیح است و کار هم می کند؛ به کاربر می گوید ID اش را وارد کند و سپس آن ID را وارد کد SQL می کند تا عملیات خاصی را انجام دهد.

اما توجه کنید که کاربر می تواند هر مقدار که دوست داشت را وارد کند! به طور مثال اگر ID کاربر 105 باشد اما به جای وارد کردن 105 مقدار زیر را وارد کند چه می شود:

105 OR 1=1

در این صورت برنامه ی ما آن را وارد کد SQL می کند:

SELECT * FROM Users WHERE UserId = 105 OR 1=1;

در واقع این کد برابر با کد زیر است:

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

اینجا گفته ایم هر چیزی را از جدول Users انتخاب کن که UserId آن برابر با 105 باشد و یا (OR) یک مساوی یک باشد (1=1)!! واضح است که در منطق کامپیوتری یک همیشه مساوی با یک است. بنابراین این کد SQL همیشه درست خواهد بود و نتیجه اش این می شود که تمام ردیف های جدول users و تمام اطلاعات کاربران ما به فرد خاطی نمایش داده می شود! ممکن است کاربران ما اطلاعات مهمی در سایت ما داشته باشند!

یک روش دیگر برای انجام SQL Injection را مثال می زنم. تصور کنید فرم لاگینی داشته باشیم که کد زیر را داشته باشد:

uName = getRequestString("username");
uPass = getRequestString("userpassword");

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

حالا اگر کاربر ما صادقانه اسمش را وارد کند (مثلا John Doe) و سپس رمز عبور خود را نیز وارد کند (مثلا myPass) کد SQL بالا به این شکل در می آید:

SELECT * FROM Users WHERE Name ="John Doe" AND Pass ="myPass"

تا اینجا مشکلی نیست اما اگر هکر یا فرد خرابکار اطلاعات را به این شکل وارد کند چطور:

Username: " or ""="

Password: " or ""="

در این صورت کد SQL بالا می شود:

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

در زبان SQL عبارت ""="" OR همیشه صحیح است بنابراین تمام اطلاعات به هکر برگردانده می شود.

در مثال دیگر می توان اینطور تصور کرد که از کاربر یوزرنیم یا نام کاربری اش را بخواهیم و کد زیر را نوشته باشیم:

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

اگر کاربر به جای یوزرنیم عبارت زیر را وارد کرده باشد چطور؟

105; DROP TABLE Suppliers

در این صورت کد SQL ما تبدیل به کد زیر می شود:

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

این کد باعث می شود جدول Suppliers در پایگاه داده به طور کامل حذف شود! این مسئله می تواند تبعات بسیار سنگینی برای شرکت و کسب و کار شما داشته باشد. به طور مثال در سال 2018 شاهد خبری بودیم که یک هکر روسی به خاطر انجام حملات SQL Injection به 12 سال زندان محکوم شده است. حملات این هکر در مجموع 300 میلیون دلار برای شرکت های مربوطه هزینه داشته است و افراد قربانی ثروت خود را از دست داده بودند! لینک کامل خبر:

Hackers sentenced for SQL injections that cost $300 million

بنابراین نباید حملات SQL Injection را دست کم بگیرید.

سوال: چطور در برابر این حملات از خودمان دفاع کنیم؟

پاسخ: مبحث مبارزه با SQL Injection مبحثی طولانی است و نمی توان آن را در یک یا دو جلسه توضیح داد. شما می توانید با مطالعه ی دوره های آموزشی زیر از شر حملات SQL Injection در امان بمانید:

آموزش PDO

مقابله با SQL INJECTION

مقاله ی دوم در واقع یک مقاله ی کمکی برای «آموزش PDO» محسوب می شود بنابراین پیشنهاد بنده این است که ابتدا «آموزش PDO» را مطالعه کنید.

به هر حال امیدوارم از این قسمت لذت برده باشید.

تمام فصل‌های سری ترتیبی که روکسو برای مطالعه‌ی دروس سری آموزش زبان SQL توصیه می‌کند:
نویسنده شوید
دیدگاه‌های شما (1 دیدگاه)

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

نیما
05 دی 1398
سلام وقتتون بخیر یه سوال داشتم، استفاده از MYSQL تو PHP5.5 به بعد منسوخ شده؟ یعنی دیگه از این پایگاه داده دیگه استفاده نمیشه برای PHP؟ همچنین میخواستم نظرتون رو دربارهMYSQL i و sqlite بدونم ممنون میشم راهنماییم کنید

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

امیر زوارمی
06 دی 1398
سلام دوست عزیز، خود پایگاه داده ی MYSQL ربطی به زبان PHP نداره بنابراین نمیشه از طرف PHP منسوخ بشه اما رابط یا extension مربوط به mysql که معادل دستور mysql در PHP بود در نسخه ی 5.5 زبان PHP منسوخ اعلام شده و در نسخه ی 7 کاملا حذف شده. شما دو راه جلوتوی دارید: یا از mysqli استفاده کنید که نسخه ی بهینه شده ی mysql است و به خوبی کار میکنه. یا از PDO استفاده کنید که بهترین و جدید ترین گزینه هست. در مورد MySQL و sqlite هم بحث زیاده و نمیشه خلاصه گفت یکی بهتره. ان شاء الله در چند روز آینده یک مقاله در این مورد مینویسم تا منتشر بشه.

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.