اگر شما هم کمی در فضای امنیت وب قرار گرفته باشید احتمالا با عبارت هایی مانند SQL Injection یا تزریق دستورات SQL برخورد کرده اید. در این مقاله با هم در مورد این آسیب پذیری صحبت خواهیم کرد.
آسیب پذیری SQL Injection از سالهای قبل جزء مهم ترین آسیب پذیری های فضای وب یا شاید مهم ترین آسیب پذیری فضای وب بوده و امروزه با وجود اینکه آسیب پذیری های بسیار متنوعتری ایجاد شدهاند با این حال در آخرین لیست Top 10 منتشر شده از سایت OWASP، که هر چند سال یکبار لیستی از 10 دسته بندی مهم آسیب پذیری های وب را منتشر میکند، در صدر لیست قرار گرفته است.
SQL Injection چیست؟
همانطور که می دانید اکثر سایت ها یا برنامه های تحت وب برای ذخیره اطلاعاتشان از پایگاه داده هایی نظیر SQL Server یا MySQL و ... استفاده میکنند که زبان تمامی آنها SQL است و اینجاست که تزریق SQL به سایت قربانی معنا پیدا میکند.
به طور خلاصه کل کاری که هکر در این حملات انجام میدهد تزریق یک قطعه کد SQL به برنامه یا سایت قربانی است که این کد در پایگاه داده اجرا شده و می تواند اطلاعات را تخریب، ویرایش یا افشا کند.
این اطلاعات میتواند شامل لیست نام کاربری و رمزعبور کاربران یا حتی اطلاعات بسیار حساستر و محرمانه تر از سایت قربانی باشد.
حملات SQL Injection از نگاه هکر
فرض کنید که ما به عنوان هکر با یک سایت روبرو می شویم و می خواهیم به پایگاه داده سایت دسترسی پیدا کنیم و بخشی از اطلاعاتی که نیاز داریم را از آن استخراج کنیم.
قطعاً راههای مختلف و زیادی برای دسترسی به پایگاه داده سایت هست اما ما میخواهیم از طریق تزریق کد SQL به سایت دسترسی لازم به پایگاه داده را به دست آوریم.
برای این منظور مراحل زیر را طی میکنیم که در تصویر بالا به طور کلی اشاره شده است.
1- ابتدا باید دنبال یک entry point یا نقطه ورود مناسب بگردیم؛ منظور از entry point هر چیزی در سایت قربانی که کاربر می تواند از طریق آن اطلاعاتی را به عنوان ورودی به سایت بدهد.
معمولاً این نقاط ورود یا فرمهای گوناگون هستند یا پارامتر هایی که از URL سایت مقدار دهی میشوند؛
مثلا در URL زیر، مقدار جلوی p_id
، پارامتر URL محسوب می شود که نقطه خوبی برای تزریق کد هست.
http://localhost:85/cms/post.php?p_id=5
از جمله فرمها هم میتوان به فرم لاگین یا فرم های ثبت اطلاعات اشاره کرد که در همه آن ها امکان تزریق کد وجود دارد؛ برای مثال فرم نظردهی زیر، یک نمونه از این فرم هاست که در آن امکان تزریق کد توسط هکر وجود دارد.
برای این کار نیاز داریم تا کل سایت را به صورت دستی یا با استفاده از یک ابزار برای دریافت ورودی بررسی کنیم.
2- قدم بعد شناسایی این است که آیا اصلاً ورودی های مورد نظر به SQL Injection آسیب پذیر هست یا خیر.
این مرحله به تنهایی توضیحات نسبتاً مفصلی را میطلبد که انشالله در مقالات بعدی توضیح خواهیم داد اما در این قسمت به یک مثال اکتفا میکنیم.
سایت زیر را در نظر بگیرید:
http://localhost:85/cms/post.php?p_id=5
با رفتن به آدرس بالا پست شماره 5 به شکل زیر برای ما نمایش داده می شود.
حال میخواهیم ببینیم که آیا پارامتر p_id
آسیب پذیر به SQL Injection هست یا خیر.
برای این کار کافی است مانند مثال زیر کاراکتر ‘
را بعد از عدد 5 قرار دهیم.
‘http://localhost:85/cms/post.php?p_id=5
همانطور که مشاهده میکنید با یک خطای SQL روبرو شدیم و از این خطا متوجه میشویم که احتمال دارد سایت بالا به حملات SQL Injection آسیب پذیر باشد.
3- قدم بعدی تزریق دستور مناسب و به دنبال آن استخراج اطلاعات مورد نیاز هست.
مثال بالا را در نظر بگیرید.
بعد از اینکه متوجه شدیم به احتمال زیاد به حملات SQL Injection آسیب پذیر هست، حال باید ورودی p_id
را در URL بالا به گونه ای تغییر دهیم که به یک نتیجه مطلوب برسیم.
برای درک بهتر ابتدا کد نوشته شده در این وبسایت را با هم بررسی می کنیم. قطعه کد زیر، کد مورد استفاده در سایت بالا است.
<?php
if (isset($_GET['p_id'])) {
$post_id = $_GET['p_id'];
}
$query = "SELECT * FROM posts WHERE post_id = $post_id";
$select_all_post_query = mysqli_query($connection,$query);
?>
در کد بالا p_id
از کاربر گرفته شده و سپس وارد Query میشود؛ در Query بالا عملیات SELECT
صورت میگیرد و با اعمال شرط WHERE
، تنها اطلاعات پستی که p_id
آن مطابق پارامتر p_id
است، نمایش داده میشود.
پس عملاً هر چیزی که ما به عنوان id
وارد کنیم وارد Query بالا شده و مطابق دستورهای بالا اجرا میشود.
حال فرض کنید به جای یک عدد تنها مقدار زیر را وارد کنیم.
http://localhost:85/cms/post.php?p_id=5 or true
همان طور که خودتان هم متوجه شدید در این حالت عبارت 5 or true
وارد Query بالا میشود و در واقع Query به صورت زیر می شود:
$query = "SELECT * FROM posts WHERE post_id = 5 or true";
Query بالا در واقع دستور میدهد که همه پستها را از پایگاه داده انتخاب کن به شرط اینکه یا p_id
آنها برابر 5 باشد و یا true
؛ همانطور که می دانید or
شدن هر عبارت شرطی با true
، مقداری true
را برمی گرداند و به طور خلاصه یعنی کل پستها از پایگاه داده فراخوانی میشود. پس نتیجه زیر حاصل میشود:
یعنی سایر پستها هم برای ما نمایش داده میشوند.
مثال بالا یک نمونه بسیار ساده از حملات SQL Injection بود که منجر به استخراج اطلاعات مد نظر ما شد. اطلاعات استخراج شده در مثال بالا اطلاعات خیلی حساسی نبودند اما با دستکاری کردن بیشتر ورودی p_id
و وارد کردن Query ورودی های حساب شده میتوان اطلاعات بسیار حساس تری را هم استخراج کرد.