SQL Injection یا تزریق SQL چیست؟

09 اسفند 1397
درسنامه درس 1 از سری مقابله با SQL Injection
SQL-Injection-what-is-sql-injection

سلام به شما همراهان همیشگی روکسو! با یک دوره ی جدید در خدمت شما هستیم؛ مبارزه با SQL Injection. در این دوره قصد دارم به بررسی حملاتی به نام حملات تزریق SQL یا SQL Injection بپردازم؛ ما در این دوره ابتدا با مفهوم SQL Injection آشنا خواهیم شد، سپس یاد خواهیم گرفت که چطور کوئری های خود را 100 درصد ایمن کنیم و در آخر برخی از شایعات، اشتباهات و خرافات مربوط به این بحث را رد خواهیم کرد. امیدوارم تا پایان این دوره همراه ما باشید.

SQL Injection یا تزریق SQL چیست؟

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

متاسفانه با اینکه پیشگیری از SQL Injection بسیار ساده است اما باز هم در دنیا یکی از دلایل بسیار شایع و مهم هک وب سایت ها می باشد. بخشی از تقصیر به گردن مدیران وب سایت ها است که برنامه نویسانی را استخدام می کنند که حقوق کمتری بخواهند نه کسانی که تخصص شان بیشتر است. بخش دیگری از تقصیر به گردن برنامه نویسان است که تصور می کنند با یادگرفتن دستورات برنامه نویسی، برنامه نویس می شوند و هیچ تلاشی برای حفظ امنیت یک وب سایت نمی کنند بلکه حقوقشان را گرفته و سریعا وب سایت را تحویل می دهند. سعی کنید اخلاق مدار باشید و در شغل خود بساز و بفروشی عمل نکنید.

از نظر فنی SQL Injection عبارت است از:

SQL injection is a code injection technique, used to attack data-driven applications, in which nefarious SQL statements are inserted into an entry field for execution (e.g. to dump the database contents to the attacker)

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

اما اگر بخواهیم به زبان ساده تر بگوییم:

SQL Injection یک سوء استفاده از کوئری های SQL ای است که به درستی فرمت بندی نشده اند. ریشه ی این نوع حملات در ترکیب کد و داده است.

در واقع کوئری های SQL درست مانند اسکریپت های PHP، یک برنامه هستند اما تفاوت شان اینجاست که ما این برنامه را به صورت پویا ساخته و همانطور که جلو میرویم چیز هایی به آن اضافه می کنیم (که معمولا از سمت کاربر است). در چنین وضعیتی طبیعی است که برخی از کدها ساختار برنامه ی ما را تغییر دهند یا اخلالی در اجرای آن ایجاد کنند. چنین حالتی تنها زمانی رخ می دهد که ما کوئری خود را به طور صحیح فرمت بندی نکرده باشیم.

تصویر زیر یکی از شوخی های کاربران و برنامه نویسان در رابطه با SQL Injection است که در فضای مجازی پخش شده است:

یکی از شوخی های برنامه نویسان در مورد اهمیت ایمن سازی ارتباط با پایگاه داده
یکی از شوخی های برنامه نویسان در مورد اهمیت ایمن سازی ارتباط با پایگاه داده

تصویر را از سمت چپ به راست ترجمه می کنم:

1- سلام، از مدرسه ی پسرتون تماس می گیرم. مشکلی برای سیستم های مدرسه پیش اومده.

2- وای! چیزی رو خراب کرده؟

3- آیا شما واقعا اسم پسرتون رو گذاشتین  ;Robert'); Drop the table students
- بله ما صداش میزنیم Bobby tables کوچولو!

4- خانم ما تمام اطلاعات دانش آموزان امسال رو از دست دادیم. امیدوارم از کارتون راضی باشین!
- منم امیدوارم یاد گرفته باشین که ورودی های پایگاه داده رو پاک سازی کنید!

اگر آشنایی مختصری با SQL Injection داشته باشید متوجه شوخی این تصویر می شوید اما اگر چیزی نمی فهمید، مشکلی نیست. می خواهیم بر اساس همین شوخی یک مثال در مورد SQL Injection بزنیم! برای درک این شوخی باید بدانید که حملات SQL Injection از سمت کاربر و با داده های کاربر رخ میدهند. به طور مثال شما از کاربر می خواهید مقداری را به شما بدهد. مثلا در فرمی از کاربر سن او یا نامش را میپرسید، یا در فرم login از او حساب کاربری و رمز عبور می خواهید، یا حتی در کامنت ها از کاربران نظرشان را می پرسید. حالا فرض کنید یکی از کوئری های ما به شکل زیر باشد:

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

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

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

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

در تصویر بالا نیز همین اتفاق افتاده است و در فرم آنلاین به جای وارد کردن نام دانش آموز، دستور ;Bobby';DROP TABLE users وارد فرم شده است. این دستور باعث حذف جدول users و از دست رفتن اطلاعات تمام دانش آموزان می شود! مثال زیر همان تصویر بالاست:

$name  = "Bobby';DROP TABLE users; -- ";
$query = "SELECT * FROM users WHERE name='$name'";

متغیر name را مستقیما وارد کوئری کرده ایم بنابراین این کوئری تبدیل به کد مخرب زیر می شود:

SELECT * FROM users WHERE name='Bobby';DROP TABLE users; -- '

با اینکه این وضعیت بین برنامه نویسان SQL Injection نام دارد اما واقعیت عملی آن یک رشته ی قالب بندی نشده است. کوئری ما ساختار و فرمت صحیحی ندارد و دلیل حذف تمام جدول و این SQL Injection نیز همین است.

بیایید به سراغ یک مثال دیگر برویم:

$id    = "1; DROP TABLE users;"
$id    = mysqli_real_escape_string($link, $id);
$query = "SELECT * FROM users where id = $id";

در این مثال از کاربر خواسته ایم ID یا username خود را به ما بدهد و آن را در متغیر id قرار داده ایم. سپس با استفاده از تابع mysqli_real_escape_string آن را پاک سازی کرده ایم و در آخر نیز اجرا شده است. این کوئری تبدیل به کوئری بی خطر زیر می شود:

SELECT * FROM users WHERE id =1;DROP TABLE users; -- '

گرچه کد بالا خطری ایجاد نمی کند اما اینجا بحث تنها بر سر خطرناک بودن یا نبودن نیست. تصور کنید نام دختری Sarah O'Hara باشد و بخواهد در سیستم مدرسه ثبت نام کند. اگر فرمت و قالب کوئری خود را درست نکنیم با کد زیر روبرو می شویم:

INSERT INTO users SET name='Sarah O'Hara'

, به خاطر علامت ' در فامیلی این دختر به یک خطای دستوری بر میخوریم.

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

تمام فصل‌های سری ترتیبی که روکسو برای مطالعه‌ی دروس سری مقابله با SQL Injection توصیه می‌کند:
نویسنده شوید
دیدگاه‌های شما

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