در این پست آموزشی به زبان ساده در مورد SQL injection صحبت میکنم. مفهومی که شما به عنوان طراح سایت حتما باید بلد باشید و راههای مقابله با اون رو بدونید.
SQL Injection چیست؟
قبل از اینکه بحث رو شروع کنم بد نیست این تذکر رو بدم که همه مثالهای این پست با SQL و PHP مطرح شده ولی اگر شما آشنایی با این زبان ندارید جای نگرانی نیست چون مثالها ساده است و هدف من در این آموزش انتقال مفهوم SQL Injection به شماست.
خب بریم سراغ بحثمون. با یک مثال شروع میکنم. شما فرض کنید که همیچ کدی سمت سرور نوشتید:
در کد بالا قراره اطلاعات یک کاربر خاص رو از جدول users بیرون بکشیم. اما چه کاربری؟ کاربری که نام کاربری و پسوردش در متغیرهای username و password ذخیره شده. این اطلاعات از کجا میاد؟ طبیعتا از سایت یا اپلیکیشنی که طراحی کردیم. دقیق تر بخوام بگم کاربر اطلاعات کاربریش رو در سایت وارد میکنه و این اطلاعات از طریق دو متغیری که اسم بردیم وارد کدهای SQL میشه. واینجاست که ما داریم خطر رو به جون میخریم! چرا؟ چون کاربر هر چیزی که تو سایت به عنوان یوزر نیم و پسور وارد کنه عینا وارد کدهای SQL ما میشه. حالا اگه کاربر (که دیگه باید بهش بگیم هکر) یوزرنیمش رو اینجوری وارد کنه فاجعه به بار میاد:
Hamid'; DROP DATABASE xyz –
هکر با وارد کردن یوزرنیم بالا میتونه دیتابیسِ سایت شما رو پاک کنه (البته باید اسم دیتابیس رو درست وارد کنه) چرا؟ بیایم یوزرنیم رو جایگذاری کنیم در کد:
فکر کنم دیگه همه چیز روشنه! هکر با دستوراتی که وارد کرد به دستور select خاتمه میده ، دیتابیس رو پاک میکنه و با — (دو تا خط فاصله) همه دستورات بعدی رو کامنت میکنه.
حذف یک جدول خاص:
Hamid'; DROP TABLE xyz –
دسترسی به اطلاعات همه کاربران:
Hamid' OR 1=1 --
تغییر رمز عبور ادمین سایت
Hamid'; update users set password='hackShodiRaft' where user='administrator'--
البته باید تکرار کنم که اسم دیتابیس، جدول یا هر چیز دیگه ای که تو مثالها میبینید رو هکر یا باید حدس بزنه یا به طریقی باید به دستشون بیاره. اما اینو باید در نظر داشته باشیم که برنامه نویسی که به فکر جلوگیری از حمله های این شکلی به سایتش نیست احتمال داره از اسامی شناخته شده ای برای دیتابیس و جدولش استفاده کنه و اینجوری کار هکر رو راحت تر کنه
چگونه از SQL Injection در امان باشیم؟
1- input validation
شما به عنوان برنامه نویسی باید به همه داده هایی که از سمت سایت شما دریافت میشه شک کنید و فرض رو بر این بذارید که ممکنه هکر دستورات خطرناکی رو به سمت سرور میفرسته. پس باید هر داده ای که دریافت میشه اعتبارسنجی میشه. یعنی قبل از استفاده چک کنید که آیا داده ها، داده های معتبری هستند یا نه!
2- Escaping
در مثالهایی که برای هک شدن سایت زدم دیدید که کوتیشن نقش اساسی رو بازی میکرد. یعنی با استفاده از کوتیشن و سیمیکالون بود که دستور select تموم شد و دستور دلخواه هکر وارد کدهای sql شده بود. بنابراین یکی از روشهای مقابله با sql injection میتونه این باشه که کاراکترهایی که میتونند منجر به یک دستور ناخواسته در sql بشند رو حذف کنیم. در php این کار رو تابع mysqli_real_escape_string انجام میده:
3- Parametrized queries
از نظر من کاراترین روشی که میشه به کار برد همین روشه. در این روش یه جورایی مسولیت کنترل کدهای خطرناک رو میندازیم رو دوش php! چه جوری؟ کافیه متغیرهایی که از سایت دریافت میکنیم رو به php معرفی کنیم. یعنی کوئریمون رو جوری بنویسیم که اصطلاحا متغیرها به کوئری bind بشن. اینجوری مطمئن خواهیم بود که اگه دستورات خطرناکی از سمت هکر دریافت بشه در کوئری اجرا شده بی اثر خواهد شد.
در کوئری بالا نوشته شده id=:id و پایینتر عمل bind شدن (مقید کردن) انجام میشه و اونجا به php میگیم منظور ما از :id در کوئری متغیر $id است که دریافت کردیم. پس حواست باشه که دستورات خطرناکی داخلش نباشه!
4- stored procedures
من اینجا قصد آموزش stored procedures رو ندارم ولی اگه ساده بخوام بگم پروسیجرها در واقع توابعی هستند که در دیتابیس ذخیره میشن و یه میشه گفت سمت سرور اجرا میشن. دستورات و نحوه فراخوانی پروسیجر به صورتیه که شبیه به کوئریهای پارامتر شده است توضیح دادم و به این شکل میشه جلوی sql injection رو بگیریم
با روشهایی که گفتیم آیا سایت ما 100 درصد امن میشه؟
قطعا نه! sql injection یکی از روشهای متداول و در عین حال پیش و پا افتاده برای هک کردنه! یعنی شما به عنوان طراح سایت حتما، تاکید میکنم حتما باید لحاظ کنید ولی دلیل نمیشه که بعد از اینکه این مورد رو در نظر گرفتید خیالتون راحت باشه که سایت شما صد در صد امنه. همیشه حواستون باشه که دست بالای دست زیاده :دی
ولی با مواردیکه گفتم اگر در سایتتون لحاظ کنید میتونم بگه که حداقل جوجه هکرها نمیتونند به سایت شما آسیب برسونن 😉