میخوای وارد بازار کار بشی و محصولات خودت رو بفرشی همین الان ثبت نام کن
0

اجرای کوئری ها و SQL Injection قسمت ۴

۷۳ / ۱۰۰

سلام به شما همراهان و دوستان محترم سایت آموزشی و فروشگاهی مدرسه کدنویسی به دوره ی آموزش PDO خوش آمدید.

در این دوره قصد داریم شما را با اجرای کوئری ها و SQL Injection قسمت ۴ به صورت کامل آشنا کرده و نحوه استفاده از آن را به شما آموزش دهیم پس با من همراه باشید

 


اجرای کوئری ها در PDO با ()PDO::query

دو راه برای اجرای کوئری ها در PDO وجود دارد؛ اگر قرار نیست هیچ متغیری به کوئری داده شود می توانید مستقیما از دستور ()PDO::query استفاده کنید که پس از اجرا به شما شیء خاص PDOStatement را برمی گرداند.

این شیء تقریبا شبیه به نتیجه ای است که از دستور ()mysql_query می گیرید، مخصوصا از آن جهت که می توانید به وسیله ی آن، ردیف ها (row) را دریافت کنید:

$stmt = $pdo->query('SELECT name FROM users');
while ($row = $stmt->fetch())
{
    echo $row['name'] . "\n";
}

همچنین باید گفت که دستور ()query به ما اجازه می دهد از method chaining (زنجیره سازی دستور ها) برای کوئری SELECT استفاده کنیم. البته در این مورد بعدا صحبت خواهیم کرد.


Prepared statements و جلوگیری از SQL Injection

ابتدا توضیحی کوتاه در رابطه با تزریق SQL یا همان SQL Injection ؛ باید بدانید که این حمله، از شایع ترین حملات به وب سایت ها است و ممکن است پایگاه داده و یا وب سایت شما یا هر دو را نابود کند!

این نوع حمله زمانی اتفاق می افتد که شما از کاربر می خواهید مقداری را به شما بدهد. مثلا در فرمی از کاربر سن او یا نامش را میپرسید، یا در فرم login از او حساب کاربری و رمز عبور می خواهید، یا حتی در کامنت ها از کاربران نظرشان را می پرسید! در تمامی این حالات شما در معرض این حملات قرار می گیرید.

مثالی کوتاه و ساده از این حملات را برای شما توضیح می دهم. فرض کنید یکی از کوئری های ما به شکل زیر باشد:

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

منطق برنامه نویسی در SQL به این شکل است که عبارت ۱=۱ همیشه صحیح یا true تلقی می شود. حالا فرض کنید از کاربر بخواهیم مقداری را (مثلا username اش را) به ما بدهد و کاربر به جای تایپ آن مقدار، عبارت ۱۰۵ OR 1=1 را در فرم وارد کند. در چنین حالتی کوئری ما به شکل زیر در خواهد آمد:

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

آیا می بینید چه اتفاقی افتاد؟ بنابر این فرض که ۱=۱ همیشه صحیح است، این کوئری نیز همیشه صحیح است و طبیعتا همیشه اجرا شده و تمام Row (ردیف) ها را از جدول “users” برمی گرداند!!! حالا اگر جدول users دارای نام کاربران و رمز عبورشان یا اطلاعات مهم دیگر بود چه؟

در واقع کوئری بالا، برای SQL دقیقا مساوی با کوئری پایین است:

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

به این ترتیب یک هکر مبتدی به تمام اطلاعات کاربران شما دست پیدا می کند!!

مسئله این جاست که اکثر کاربران یک رمز واحد را برای اکثر وب سایت ها و کارهایشان انتخاب می کنند (این کار اصلا توصیه نمی شود و شما باید رمز های متفاوتی داشته باشید)

بنابراین با اینکه ممکن است سایت شما، سایت لطیفه و جوک باشد اما رمز ایمیل یا رمز بانکی آن کاربر الان به دست هکر افتاده است چرا که رمز عبور آن کاربر در سایت شما با رمز عبورش در سایت بانک یکی بوده است!

 

شما هیچ وقت نباید مسئولیت اخلاقی خود را به عنوان یک توسعه دهنده و برنامه نویس از یاد ببرید. در واقع کاربران به شما اعتماد کرده اند و شما حافظ اطلاعات آن ها هستید.

 

یکی دیگر از روش های SQL Injection، بر این اساس است که در SQL عبارت “”=”” همیشه معادل true خواهد بود. حالا اگر یک کوئری به شکل زیر داشته باشیم:

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

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

نتیجه اش می شود:

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

تا اینجای کار مشکلی نیست اما اگر کاربر/هکر، به طور مثال، به جای موارد خواسته شده مقدار “=”” OR ” را وارد کند چه می شود؟

Username: ” or “”=”

Password: ” or “”=”

نتیجه ی این کد، کوئری زیر است:

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

این کوئری بنابر چیزی که گفتیم همیشه صحیح یا true است و اطلاعات جدول users را در اختیار کاربر/هکر قرار خواهد داد. روش های تزریق SQL  یا SQL Injection بسیار زیاد و بعضا پیچیده هستند. ما در اینجا تنها یک مثال ساده از آن را ذکر کردیم تا شما با این مبحث آشنا شوید.

خب برمی گردیم به اصل مطلب خودمان،

مبارزه با SQL Injection یا تزریق SQL از بزرگترین دلایلی است که ما می گوییم باید از PDO استفاده کرد. در واقع بسیاری از برنامه نویسان اعتقاد دارند مبارزه با تزریق SQL مهم ترین و تنها دلیل دور انداختن ()mysql_query و استفاده از PDO است.

PDO به طور پیش فرض از prepared statements (به معنی دستورات آماده) پشتیبانی می کند و قابل ذکر است که prepared statement ها تنها راه صحیح و اصولی اجرای کوئری ها هستند (در صورتی که کوئری ما دارای متغیر باشد).

بنابراین برای هر کوئری که دارای حتی یک متغیر است و شما می خواهید اجرایش کنید، باید ابتدا از یک placeholder (به معنی جا گیرنده – در قسمت های قبلی در مورد آن ها صحبت شد) استفاده کنید، سپس کوئری خود را prepare کرده و اجرا کنید.

خلاصه برایتان بگویم، کار خیلی سختی نیست. در اکثر مواقع تنها به دو تابع ()prepare و ()execute نیاز خواهید داشت.

قدم اول، تغییر کوئری و جاگذاری placeholder به جای متغیر هاست. برای مثال کوئری زیر:

$sql = "SELECT * FROM users WHERE email = '$email' AND status='$status'";

تبدیل به یکی از کوئری های زیر می شود:

حالت اول:

$sql = 'SELECT * FROM users WHERE email = ? AND status=?';

حالت دوم:

$sql = 'SELECT * FROM users WHERE email = :email AND status=:status';

اگر به مثال توجه کرده باشید، فهمیده اید که PDO از placeholder های موقعیتی یا positional (در مثال -> ?) و اسمی یا named (در مثال -> email:) پشتیبانی می کند.

برای استفاده از placeholder های اسمی از دو نقطه استفاده می کنید (مانند مثال). نامی که برای آن انتخاب می کنید باید از بین حروف، اعداد و آندرلاین انتخاب شده باشد. همچنین توجه داشته باشد که هیچ نوع quotation ای این نوع از placeholder ها را احاطه نکرده است.

خلاصه ی مقاله

تا اینجای کار با مفهوم prepared statement ها (به طور مبتدی و ساده) و آماده سازی و اجرای کوئری ها و SQL Injection ( قسمت ۴ )  آشنا شدیم و ادامه سری آموزش اتصال شیء گرا به پایگاه داده ( PDO ) را دنبال کنید . برای مطالعه پست‌ها بیشتر ، ما را در مدرسه کدنویسی تلگرام  و یا در تی جوان اینستاگرام دنبال کنید.

نظراتتون رو زیر همین پست با ما به اشتراک بگذارید.

 

ارسال دیدگاه

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

×

سلام کاربر عزیز

هر سوالی دارید در این بخش هستیم تا شما رو راهنمائی کنیم

روی لوگومون کلیک کنید

× چطور میتونم کمکتون کنم؟