SQL Injection (SQi) چیست؟
SQL Injection یک نوع حمله سایبری است که به مهاجم این امکان را میدهد تا با وارد کردن دستورات SQL مخرب در فیلدهای ورودی یک برنامه، به پایگاه داده دسترسی پیدا کند. این روش به مهاجم اجازه میدهد تا دادههای حساس را بازیابی یا تغییر دهد، اطلاعات موجود را تخریب کند و رفتارهایی مانند دستکاری دادهها را انجام دهد. در واقع، مهاجم میتواند با استفاده از یک سری دستورات SQL خاص، به طور غیرمجاز وارد سیستم شود و به آن آسیب برساند. با استفاده از SQL Injection، یک مهاجم قادر است هویت کاربران دارای دسترسیهای بالا را جعل کرده و خود را به عنوان مدیر پایگاه داده معرفی کند. این حمله همچنین به مهاجم امکان میدهد تراکنشها و ماندههای حساب را تغییر دهد یا حتی کل پایگاه داده را بازیابی یا تخریب کند. در نتیجه، SQL Injection میتواند تهدیدی جدی برای امنیت دادهها و یکپارچگی سیستمهای اطلاعاتی باشد.
در دنیای فناوری اطلاعات امروز، SQL Injection معمولاً از طریق اینترنت و با ارسال دستورات SQL مخرب به یک API یا نقطه پایانی (endpoint) که توسط وبسایتها یا سرویسها ارائه میشود، صورت میگیرد. این حمله به مهاجم این امکان را میدهد که با سوءاستفاده از ضعف در اعتبارسنجی ورودیها در کوئریهای SQL، دادههای حساس یا اطلاعات پایگاه داده را به دست آورد. در شرایط بحرانیتر، حمله SQL Injection میتواند به مهاجم اجازه دهد تا به سطح دسترسی root دست پیدا کند و کنترل کامل سیستم را در اختیار گیرد. حمله SQL Injection به طور خاص از ضعفهایی که در اعتبارسنجی ورودیهای کاربر وجود دارد، استفاده میکند. زمانی که یک برنامه از ورودیهای غیرقابل اعتماد برای ساختن کوئریهای SQL به پایگاه داده استفاده کند، مهاجم میتواند این ورودیها را دستکاری کرده و ساختار کوئریها را تغییر دهد. این تغییرات میتوانند به مهاجم اجازه دهند تا به دادههای پایگاه داده دسترسی پیدا کرده، آنها را تغییر دهد یا حتی حذف کند. این نوع حمله، تهدیدی جدی برای امنیت اطلاعات و یکپارچگی سیستمهای دادهای است.
انواع SQL Injections
SQL Injection معمولاً به سه دسته تقسیم میشود:
In-band SQLi (Classic) ، Inferential SQLi (Blind) و Out-of-band SQLi.
- In-band SQLi
در این روش، مهاجم از همان کانال ارتباطی برای انجام حملات و دریافت نتایج استفاده میکند. سادگی و کارایی in-band SQLi آن را به یکی از رایجترین انواع حملات SQLi تبدیل کرده است. این روش دو زیرشاخه دارد:
Error–based SQLi: در این روش، مهاجم اقداماتی انجام میدهد که باعث میشود پایگاه داده پیامهای خطا تولید کند. مهاجم میتواند از دادههایی که این پیامهای خطا فراهم میکنند برای جمعآوری اطلاعات در مورد ساختار پایگاه داده استفاده کند.
Union–based SQLi: این تکنیک از عملگر UNION SQL بهره میبرد که چندین عبارتSELECT تولید شده توسط پایگاه داده را به هم متصل میکند تا یک پاسخ HTTP واحد دریافت کند. این پاسخ ممکن است شامل دادههایی باشد که مهاجم میتواند از آنها استفاده کند.
- Inferential (Blind) SQLi
در این روش، مهاجم دادههایی را به سرور ارسال میکند و پاسخ و رفتار سرور را مشاهده میکند تا بیشتر در مورد ساختار آن اطلاعات کسب کند. این روش به blind SQLi معروف است زیرا دادهها از پایگاه داده وبسایت به مهاجم منتقل نمیشود و بنابراین مهاجم نمیتواند اطلاعات مربوط به حمله را به صورت in-band مشاهده کند. حملات Blind SQLi به الگوهای پاسخدهی و رفتاری سرور وابسته هستند، بنابراین معمولاً زمان بیشتری برای اجرا نیاز دارند، اما ممکن است به همان اندازه مخرب باشند. این نوع SQLi میتواند به دستههای زیر تقسیم شود:
Boolean: مهاجم یک پرسوجوی SQL به پایگاه داده ارسال میکند که برنامه را مجبور به بازگشت نتیجه میکند. نتیجه بستگی به این دارد که پرسوجو درست باشد یا غلط. بر اساس نتیجه، اطلاعات موجود در پاسخ HTTP تغییر میکند یا بدون تغییر میماند. مهاجم میتواند براساس این تغییرات بفهمد که پرسوجو درست بوده یا غلط.
Time–based: مهاجم یک پرسوجوی SQL به پایگاه داده ارسال میکند که باعث میشود پایگاه داده قبل از واکنش منتظر بماند (برای مدتی در ثانیه). مهاجم میتواند از مدت زمانی که پایگاه داده برای پاسخدهی نیاز دارد، متوجه شود که پرسوجو درست بوده یا غلط. بر اساس نتیجه، پاسخ HTTP فوراً یا پس از مدت زمانی ایجاد میشود. مهاجم میتواند متوجه شود که پیام استفاده شده نتیجه درست یا غلط داشته است، بدون اینکه به دادههای پایگاه داده وابسته باشد.
- Out-of-band SQLi
مهاجم میتواند این نوع حمله را تنها زمانی انجام دهد که ویژگیهای خاصی در سرور پایگاه داده استفاده شده توسط برنامه وب فعال شده باشد. این حمله عمدتاً به عنوان جایگزینی برای تکنیکهایIn-band SQLi و Inferential SQLi به کار میرود. Out-of-band SQLiزمانی انجام میشود که مهاجم نتواند از همان کانال برای انجام حمله و جمعآوری اطلاعات استفاده کند، یا زمانی که سرور به اندازه کافی کند یا ناپایدار است که این اقدامات را انجام دهد. این تکنیکها به قابلیت سرور برای ایجاد درخواستهای DNS یا HTTP بستگی دارند که دادهها را به مهاجم منتقل میکنند.
نحوه اجرای حمله SQL Injection
برنامههایی که کوئریهای SQL را بر اساس ورودی کاربران اجرا میکنند، ممکن است در برابر حملات SQL Injection آسیبپذیر باشند. به عنوان مثال، یک برنامه وب میتواند از کوئریهای SQL برای اجرای فرآیند احراز هویت استفاده کند. در این فرآیند، کاربر نام کاربری خود را وارد میکند و برنامه از این ورودی برای جستجوی هش رمز عبور مرتبط با آن حساب کاربری در پایگاه داده استفاده میکند. اگر هش رمز عبور ارائه شده توسط کاربر با هش ذخیره شده در پایگاه داده مطابقت داشته باشد، کاربر احراز هویت شده و به حساب خود دسترسی پیدا میکند .اگر برنامه وب ورودی نام کاربری را به درستی اعتبارسنجی نکند، یک مهاجم میتواند ورودی دستکاری شدهای ارائه دهد که توسط برنامه به اشتباه تفسیر شود. برای مثال، کوئریهای SQL معمولاً از کاراکترهایی مانند تککوتیشن (”) یا دابلکوتیشن (“”) برای تعریف دادهها در دستورات خود استفاده میکنند. یک کوئری ساده برای جستجوی رکورد مشتری بر اساس نام کاربری ممکن است به این شکل باشد:
SELECT * FROM customers WHERE username="user"
یک مهاجم میتواند با وارد کردن یک ورودی خاص، ساختار کوئری را تغییر دهد تا از آن سوءاستفاده کند. بهعنوان نمونه، اگر مهاجم نام کاربری زیر را وارد کند:
user" OR "1"="1
کوئری SQL به این شکل تغییر میکند:
SELECT * FROM customers WHERE username="user" OR "1"="1"SELECT * FROM customers WHERE username="user" OR "1"="1"
این کوئری به جای جستجوی رکوردهایی که فقط با نام کاربری “user” مطابقت دارند، به صورت زیر عمل میکند:
- شرط اول: تطابق نام کاربری با مقدار وارد شده توسط کاربر (username=”user”)، که رکورد کاربر را بازمیگرداند.
- شرط دوم: بررسی شرط “1”=”1″، که همواره درست است و تمام رکوردهای پایگاه داده را بازمیگرداند.
این تغییر به مهاجم اجازه میدهد به اطلاعات حساس سایر کاربران دسترسی پیدا کند. همچنین، در برخی موارد، ممکن است مهاجم بتواند فرآیند احراز هویت را دور بزند و به عنوان کاربر دیگری وارد سیستم شود یا به دادههای بیشتری دسترسی پیدا کند. این نوع آسیبپذیری میتواند پیامدهای جدی امنیتی داشته باشد.
پیشگیری و کاهش حملات SQL Injection:
برای جلوگیری از حملات SQL Injection و مقابله با آنها در صورت وقوع، روشهای مؤثری وجود دارد که میتوان به کار برد.
- اعتبارسنجی ورودیها (Input Validation)
اولین گام برای پیشگیری از حملات، اعتبارسنجی یا پاکسازی ورودیها است. این فرآیند شامل نوشتن کدی است که بتواند ورودیهای غیرمجاز کاربران را شناسایی کند. با وجود اینکه اعتبارسنجی ورودیها یکی از بهترین شیوههای امنیتی محسوب میشود، معمولاً به تنهایی کافی نیست. زیرا در بسیاری از موارد، امکان تعریف تمام ورودیهای مجاز و غیرمجاز به صورت جامع وجود ندارد و این کار ممکن است منجر به خطاهای اشتباه شود که تجربه کاربری و عملکرد برنامه را مختل میکند.
- استفاده از فایروال برنامه وب (WAF)
معمولاً از فایروال برنامه وب (WAF) برای فیلتر کردن حملات SQL Injection و سایر تهدیدات آنلاین استفاده میشود. فایروال برنامه وب با تکیه بر مجموعهای از امضاهای(Signatures) امنیتی که به صورت دقیق طراحی و مداوم به روزرسانی میشوند، توانایی شناسایی و مسدودسازی کوئریهای SQL مخرب را دارد. این امضاها برای شناسایی مسیرهای حمله خاص طراحی شدهاند و به طور منظم با قوانین جدید برای مسدودسازی آسیبپذیریهای تازه کشف شده به روزرسانی میشوند.
- یکپارچهسازی با سایر راهکارهای امنیتی
فایروالهای مدرن معمولاً با سایر سیستمهای امنیتی یکپارچه هستند و از این طریق اطلاعات بیشتری برای افزایش تواناییهای امنیتی خود دریافت میکنند.
به عنوان مثال، یک فایروال برنامه وب که با ورودی مشکوکی مواجه میشود، ممکن است قبل از مسدودسازی آن، دادههای IP مربوطه را بررسی کند.
بهترین روشها برای محافظت از پایگاه داده در برابر حملات SQL Injection:
هنگام توسعه وبسایت یا برنامه وب، میتوانید اقداماتی امنیتی را اعمال کنید که خطر حملات SQL Injection را به حداقل برساند. موارد زیر از مؤثرترین روشها برای پیشگیری از این حملات هستند:
- نصب به روزرسانیها و patch امنیتی
همواره جدیدترین نرمافزارها و patchهای امنیتی ارائه شده توسط فروشندگان را نصب کنید.
- حداقلسازی سطح دسترسی
حسابهای کاربری متصل به پایگاه داده را فقط با حداقل سطح دسترسی مورد نیاز پیکربندی کنید.
- عدم اشتراکگذاری حسابهای کاربری
از اشتراکگذاری حسابهای پایگاه داده بین وبسایتها و برنامههای مختلف خودداری کنید.
- اعتبارسنجی ورودیهای کاربر
برای تمامی انواع ورودیهای کاربر، از جمله فهرستهای کشویی (Drop-Down Menus)، اعتبارسنجی انجام دهید.
- پیکربندی گزارشدهی خطا
به جای ارسال پیامهای خطا به مرورگر کاربران، گزارشدهی خطا را به درستی پیکربندی کنید.
- استفاده از دستورات آماده و پارامترسازی شده
دستورات آماده (Prepared Statements) را همراه با کوئریهای پارامترسازی شده استفاده کنید تا تمامی کدهای SQL از قبل تعریف شوند و مقادیر پارامترها به صورت جداگانه ارسال شوند. این کار مانع از تغییر هدف کوئری توسط مهاجمان میشود.
- بهرهگیری از رویههای ذخیرهشده (Stored Procedures)
رویههای ذخیره شده را برای ساخت کوئریهای SQL با پارامترهای تعریف شده در پایگاه داده به کار بگیرید. این رویهها از طریق برنامه اجرا میشوند.
- استفاده از اعتبارسنجی ورودی allowlist
از اعتبارسنجی allowlist برای جلوگیری از ورود دادههای غیرمعتبر به کوئریها استفاده کنید.
- پردازش ورودیهای کاربر برای جلوگیری از حملات SQL Injection
تمام ورودیهایی که از کاربر دریافت میشود را قبل از استفاده در یک پرسوجو به طور مناسب پردازش کنید تا از تداخل آنها با کد SQL جلوگیری شود. این کار مانع از اجرای دستورات غیرمجاز و حملات SQL Injection میشود.
توصیههای کلی:
- از استفاده از حسابهای مشترک اجتناب کنید، زیرا در صورت نفوذ به یک حساب، مهاجمان میتوانند دسترسیهای بیشتری به دست آورند.
- از ارسال پیامهای خطای پایگاه داده به مرورگر کاربران خودداری کنید، زیرا مهاجمان میتوانند از این اطلاعات برای درک جزئیات فنی پایگاه داده سوءاستفاده کنند.
تأثیر حملات SQL Injection:
حمله موفقیتآمیز SQL Injection میتواند عواقب جدی برای یک کسبوکار داشته باشد. این حمله میتواند به موارد زیر منجر شود:
- افشای دادههای حساس
مهاجمان میتوانند دادههایی را بازیابی کنند که احتمالاً دادههای حساس ذخیره شده روی سرور SQL را افشا میکند.
- نقص در یکپارچگی دادهها
مهاجمان میتوانند اطلاعات موجود در سیستم شما را تغییر داده یا حذف کنند.
- نفوذ به حریم خصوصی کاربران
بسته به دادههای ذخیره شده روی سرور SQL، حمله میتواند اطلاعات حساس کاربران مانند آدرسها، شماره تلفنها و جزئیات کارتهای اعتباری را افشا کند.
- دسترسی مدیر سیستم برای مهاجم
اگر یک کاربر پایگاه داده دارای دسترسیهای مدیریتی باشد، مهاجم میتواند با استفاده از کد مخرب به سیستم دسترسی پیدا کند.
- دسترسی عمومی برای مهاجم
اگر از دستورات SQL ضعیف برای بررسی نام کاربری و رمز عبور استفاده کنید، مهاجم میتواند بدون دانستن اطلاعات کاربری وارد سیستم شما شود. از این مرحله به بعد، مهاجم میتواند با دسترسی و دستکاری اطلاعات حساس، آسیبهای بزرگی وارد کند.
هزینه حمله SQL Injection فقط مالی نیست و ممکن است شامل از دست دادن اعتماد مشتریان و آسیب به اعتبار شرکت نیز باشد. پس از شکسته شدن اعتماد مشتری، ترمیم آن بسیار دشوار خواهد بود.
چگونه سازمانها میتوانند حملات SQL Injection را کاهش دهند؟
- استفاده از دستورات آماده با کوئریهای پارامترسازی شده
این روش یکی از ابزارهای مؤثر برای کاهش حملات SQL Injection است. به جای نوشتن کوئریهای داینامیک که قادر به تمایز میان کد برنامه و دادهها نیستند، استفاده از دستورات آماده (Prepared Statements) باعث میشود تا توسعه دهندگان از کوئریهای ثابت SQL استفاده کنند و ورودیهای خارجی را به عنوان پارامتر به کوئری منتقل کنند. این رویکرد اطمینان میدهد که مفسر SQL همیشه قادر است کد برنامه را از دادهها جدا کند و مانع از اجرای دستورات مخرب شود. برای مثال، در اینجا روش authenticate()، پیادهسازی شده است:
در اینجا، صرفنظر از ورودی کاربر، متغیرهای زمان اجرا مانند نام کاربری و رمز عبور نمیتوانند بر رفتار کوئری تأثیر بگذارند. لازم به ذکر است که استفاده تنها از شیء PreparedStatement به تنهایی یک دفاع کافی نیست. برای جلوگیری از مشکلات امنیتی، باید این شیء به همراه ویژگی پارامترسازی (“?”) برای تمام مقادیر زمان اجرا استفاده شود. در غیر این صورت، استفاده از ترکیب رشتهها میتواند منجر به حمله SQL Injection شود، حتی اگر از شیء PreparedStatement نیز استفاده گردد.
- دستورهای ذخیرهشده
دستورهای ذخیرهشده، دستورات SQL هستند که در خود پایگاه داده تعریف و ذخیره میشوند و سپس از برنامه فراخوانی میشوند. معمولاً از توسعهدهندگان خواسته میشود که دستورات SQL را با پارامترهایی بسازند که به طور خودکار پارامترسازی میشوند. با این حال، ممکن است یک توسعهدهنده دستورات SQL داینامیک را داخل دستورهای ذخیرهشده ایجاد کند. دستورهای ذخیرهشده را به صورت ایمن پیادهسازی کنید و از تولید SQL داینامیک در داخل آنها خودداری کنید.
- اعتبارسنجی ورودی
یک منبع رایج حملات SQL Injection، ورودیهای خارجی با هدف خرابکارانه هستند. بنابراین، بهترین روش این است که فقط ورودیهای تأیید شده را بپذیرید که به آن اعتبارسنجی ورودی گفته میشود. برای محافظت در برابر این نوع حملات، دو روش اصلی اعتبارسنجی ورودی وجود دارد: اعتبارسنجی بر اساس لیست اجتناب(avoid list validation)، که در آن ورودیهای ناخواسته مسدود میشوند، و اعتبارسنجی بر اساس لیست ترجیحی(preferlist validation)، که فقط ورودیهای مجاز و مورد تأیید پذیرفته میشوند.
- لیست اجتناب (avoid list) ورودیهای خارجی را با مجموعهای از ورودیهای خرابکارانه شناختهشده مقایسه میکند. در این روش، برنامه یک لیست از تمام ورودیهای خرابکارانه تهیه کرده و ورودیهای دریافتی را با این لیست بررسی میکند. اما از آنجا که مهاجمان میتوانند انواع جدیدی از ورودیهای خرابکارانه را ایجاد کنند که ممکن است در لیست اجتناب نباشند، عبور از اعتبارسنجی با استفاده از این روش نسبتاً آسان است.
- لیست ترجیحی(preferlist) یک رویکرد بسیار بهتر برای کاهش خطر است. اعتبارسنجی لیست ترجیحی ورودی خارجی را با مجموعهای از ورودیهای شناختهشده و تأییدشده آزمایش میکند. با اعتبارسنجی ورودی از طریق لیست ترجیحی، برنامه دقیقاً میداند که چه ورودیهایی مورد نظر هستند و سایر مقادیر ورودی که با این ورودیهای تأیید شده تطابق ندارند، رد میشوند.
- اصول حداقل دسترسی
این یک کنترل امنیتی استاندارد است که به کاهش اثرات منفی یک حمله موفق کمک میکند. حسابهای برنامه نباید دسترسیهای ویژهای مانند دسترسیDBA یا مدیر به سرور پایگاه داده داشته باشند. علاوه بر این، دسترسیها باید طبق نیازهای واقعی محدود به کمترین سطح ممکن باشند. به عنوان مثال، حسابهایی که فقط به دسترسی خواندن نیاز دارند، فقط مجاز به دسترسی خواندن به جدولی هستند که نیاز به دسترسی دارند. این کار تضمین میکند که اگر برنامهای مورد حمله قرار گیرد، مهاجم نتواند از طریق برنامه آسیب دیده به پایگاه داده دسترسی پیدا کند.






