با سلام خدمت شما همراهان روکسو، در این قسمت از سری آموزشی زبان SQL می خواهیم در رابطه با دو مبحث کلی صحبت کنیم:
در زبان 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 را ایجاد کنیم که تمام مشتریان برزیلی ما را نمایش دهد:
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
شما می توانید با استفاده از دستور 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 یا 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» محسوب می شود بنابراین پیشنهاد بنده این است که ابتدا «آموزش PDO» را مطالعه کنید.
به هر حال امیدوارم از این قسمت لذت برده باشید.
در این قسمت، به پرسشهای تخصصی شما دربارهی محتوای مقاله پاسخ داده نمیشود. سوالات خود را اینجا بپرسید.
در این قسمت، به پرسشهای تخصصی شما دربارهی محتوای مقاله پاسخ داده نمیشود. سوالات خود را اینجا بپرسید.
در این قسمت، به پرسشهای تخصصی شما دربارهی محتوای مقاله پاسخ داده نمیشود. سوالات خود را اینجا بپرسید.