«SQL Injection» یا «اسکیوال اینجکشن» یا «تزریق SQL»، یکی از روشهای وارد کردن آسیب و هک کردن سایتهای اینترنتی میباشد. به این صورت که در این روش، به دلیل رعایت نشدن اصول امنیتی در بررسی مقادیر ارسالی از سمت کلاینت، هکر به جای ارسال مقدار مورد انتظار ما، یک مقدار دیگری را ارسال میکند! برای مثال، از کلاینت انتظار داریم تا یک شماره تلفن ارسال کند و سپس این شماره تلفن را در یک کوئری قرار داده و اجرا کنیم، اما اگر بررسی نکنیم که واقعا مقدار دریافتی یک شماره تلفن است یا خیر، ممکن است مقدار دیگری مثل یک دستور SQL دیگر ارسال شده و با قرار گرفتن در کوئری ما، فجایع بزرگی را به وجود آورد!
همچنین هکر از اینکه چنین باگی در سمت ما وجود دارد یا خیر مطمئن نیست و با تزریق مقادیر مختلف بررسی میکند که آیا سرور نسبت به آن حساس است یا خیر و سپس فاجعه رخ میدهد!
برخی از وبسرورها، برخی از فریمورکها، برخی فایروالها و برخی دیگر از لایههای واسط بین درخواست کاربر و کدهای برنامهنویسی نیز ممکن است بتوانند مانع انجام این نوع حمله شوند.
بررسی روند SQL Injection
همانطور که میدانید، بخش زیادی از فعالیتهای انجام شده در سمت سرور، مربوط به خواندن و نوشتن اطلاعات در دیتابیس یا پایگاه داده میباشد. ارتباط با دیتابیس معمولا با دستورات SQL انجام میگیرد که دستوراتی متنی هستند. حالا در مواقعی ممکن است قسمتهایی از این دستورات، از کاربر گرفته شوند (یا به عبارتی توسط کاربر تعیین شده و به سرور ارسال شوند)؛ و تصور کنید برای مثال، بخواهیم یک عبارتی را جهت جستجو در لیست مطالب سایت از کاربر گرفته و داخل دستور SQL قرار دهیم:
SELECT * FROM posts WHERE title LIKE '%عبارت جستجو%';
در این کوئری، بخش «عبارت جستجو»، چیزی است که قرار است از کاربر گرفته و جایگزرین آن شود؛ اما فرض کنید کاربر، عبارت زیر را ارسال کنید:
%'; DELETE * FROM posts; --
که باعث میشود کوئری SQL ما به صورت زیر در بیاید:
SELECT * FROM posts WHERE title LIKE '%%'; DELETE * FROM posts; -- %';
اما کوئری بالا، تمامی مطالب موجود در سایت (یا به عبارتی داخل جدول posts) را حذف کرده و مقداری را نیز برنمیگرداند! فاجعه است! در حالی که میخواستیم عبارتی جستجو شود، اما یک باگ امنیتی بزرگی پیش آمد و تمامی مطالبمان از دیتابیس حذف شد!
روش مقابله با این باگ
بایستی قبل از اعمال ورودیهای کاربر در دستورات SQL، آنها را اعتبارسنجی کنید و سپس بقیه مراحل را طی کنید! به عنوان مثال اگر قرار است کاربر یک شماره تلفن ارسال کند، بنابراین باید بررسی کنید که آیا ورودی کاربر شماره تلفن است یا خیر!
البته همانطور که در ابتدا نیز گفته شد، لایههای محافظتی متعددی میتوانند مانع سوء استفاده از این باگ شوند. در فریمورکهای مدرن برنامهنویسی وب، معمولا این حفاظتها به صورت خودکار انجام میشوند و اگر برنامهنویس از دستورالعملهای توصیه شده پیروی کند، احتمال روی دادن این گونه آسیبپذیریها وجود ندارد.
درواقع اشکال معمولا زمانی رخ میدهد که برنامهنویس کار ساخت کوئریها را خود انجام دهد یا در محیطهایی مانند وردپرس افزونههایی نوشته شود که نکات امنیتی لازم در آن پیشبینی نشوند. و اگر قصد دارید کوئریهای ارسالی به پایگاه داده را خودتان ایجاد کنید، میبایست عبارتهای دریافت شده از کاربر را با توابعی که کدهای مخرب را پاکسازی میکنند، ایمنسازی نمایید. برای مثال، دستوری که برای انجام این کار در وردپرس تعبیه شده است، تابع esc_sql نام دارد.
و همچنین میتوان از Prepared Statements نیز استفاده نمود. در یک Prepared Statement، کوئری با بخشهایی متغیر تعریف میشود. سپس عبارتهای دریافت شده از کاربر به این متغیرها تخصیص پیدا میکنند. در نتیجه امکان خارج شدن محتوای کاربر از محدودهی متغیر ناممکن خواهد بود. برای مثال، کوئری زیر در بخش «?» یک متغیر تعریف کرده است:
SELECT * FROM news WHERE title = ?;
سیستمهای ORM در فریمورکهای برنامهنویسی هم از بهترین روشها برای مقابله با SQL Injection به شمار میروند. اغلب فریمورکهای PHP نیز مانند لاراول هم به خوبی با این تهدید مقابله میکنند.
نظرات ثبت شده بدون دیدگاه