تزریق به دیتابیس (SQL Injection) چیست؟
تزریق به دیتابیس (SQL Injection) چیست؟
*این پست تنها با هدف افزایش اطلاعات منتشر شده است. هر گونه سوء استفاده از گفته های این پست بر عهده کاربر است.*
اگر اهل مباحث امنیت وب یا برنامه نویسی تحت وب باشید، حتما با نامهای SQL و SQL Injection آشنا هستید. در این پست خواهید دانست که اس کیو ال اینجکشن چیست و چگونه عمل میکند.
تزریق به دیتابیس (SQL Injection) چیست؟
تزریق به پایگاه داده یا دیتابیس (SQL Injection) نوعی از حملات وب است که در آن فرد حمله کننده یا هکر میتواند اقدام به اجرا کردن دستورات دلخواه و مخرب خود بر روی پایگاه داده وب سایت مورد هدف کند. در این حمله، حمله کننده با استفاده از دانش خود (یا تنها با استفاده از یک برنامه ساده!) میتواند از نقضهای امنیتی موجود در کدهای نوشته شده توسط برنامه نویس سایت استفاده کرده و به اصطلاح آنها را اکسپلویت کند. چون در این حمله هکر درواقع به کد اسکیوال، کد دلخواه خود را اضافه میکند، تزریق SQL نام گرفته است.
یک حمله موفق اس کیو ال اینجکشن میتواند به راحتی سبب افشای دادههای مهم در دیتابیس (ازجمله رمزهای عبور، اطلاعات فردی کاربران و ...)، اضافه کردن دادههای دلخواه حمله کننده به دیتابیس یا حذف کردن دادههای خاص از دیتابیس گردد.
چگونه از باگ SQL Injection جلوگیری کنیم؟
نحوه جلوگیری از باگ SQL Injection نیاز به آگاهی برنامه نویس تحت وب از نحوه عملکرد این باگ دارد و جلوگیری از آن بسیار ساده تر از چیزی است که معمولاً تصور میشود. به همین دلیل یک پست جداگانه با عنوان نحوه جلوگیری از باگ تزریق به دیتابیس یا SQL Injection منتشر کرده ایم و در آن نحوه جلوگیری از این باگ را بررسی کرده ایم. برای جلوگیری از باگ، به پست زیر مراجعه کنید:
اصلاح و جلوگیری از باگ SQL Injection
حمله SQL Injection چگونه کار میکند؟
فرض کنید شما یک برنامه نویس سمت وب هستید و قصد دارید با دیتابیس از طریق دستورات SQL ارتباط برقرار کنید. چون همانطور که میدانید استفاده از زبان SQL برای برقراری ارتباط با دیتابیس ضروری است. کد زیر را فرض کنید که در زبان PHP نوشته شده است:
$sql_statement = "SELECT * FROM users WHERE name = '" . $_GET["name"] . "'";
دستور بالا مقدار فیلد یا همان پارامتر username که توسط متد GET، متدی که پارامترها در مسیر URL مشخص میشوند، از طرف کاربر به سرور ارسال شده را در بین دو علامت ' قرار میدهد (تا توسط سرور SQL به عنوان رشته حروفی شناخته شود) و پس از آن فرض کنید که مقدار موجود در متغیر $sql_statement قرار است اجرا شود.
فرض کنید که کاربر فیلد name را به صورت عادی مثل مقدار زیر پر کند. مسیر از طریق متد GET به این شکل خواهد شد:
http://example.com/vul.php?name=Amirreza
در این صورت Query موجود در متغیر sql_statement به این صورت خواهد بود:
$sql_statement = "SELECT * FROM users WHERE name = 'Amirreza'";
و کوئری (حرف همزه به دلیل فونت سایت مانند ن نشان داده میشود) بدون مشکل اجرا خواهد شد. در دیتابیس فیلد name با رشته Amirreza مقایسه خواهد شد و در جایی که نتیجه یافت شد، همه فیلدها (*) برای بقیه کدها در دسترس خواهد بود.
حال فرض کنید که کاربر (در اینجا، حمله کننده) فیلد name را به صورت زیر پر کند:
http://example.com/vul.php?name=' UNION UPDATE users SET email = 'hacker@example.com' WHERE name = 'admin'
به یک نام کاربری شبیه نیست، درست است؟ خب حال این مقدار را جایگزین پارامتر username متد POST میکنیم. متغیر کوئری ما به این شکل خواهد بود:
$sql_statement = "SELECT * FROM users WHERE name = '' UNION UPDATE users SET email = 'hacker@example.com' WHERE name = 'admin'";
خب کوئری بالا هم اجرا خواهد شد ولی با این تفاوت که در واقع هکر کوئری دلخواه خود را اجرا کرده است! در دیتابیس فیلد name با رشته خالی جستجو خواهد شد ولی چیزی پیدا نخواهد شد، تا اینجا برای هکر مهم نیست. اما هکر با استفاده از دستور UNION، کوئری دوم خود را نیز اجرا میکند و در کوئری دوم، ایمیل کاربر admin (که به احتمال زیاد تمامی دسترسیهای موجود را دارد) را به ایمیل دلخواه تغییر (UPDATE) میدهد.
یک مثال دیگر:
فرض کنید در یک صفحه Login (ورود)، کاربر یوزرنیم و پسورد را به وبسایت ارسال میکند. در سمت سرور، یک کوئری با شرط وجود و برابری یوزرنیم و پسورد در دیتابیس اجرا میشود. اگر کوئری خروجی داشت، یک نشست (Session) ایجاد شده و به کاربر دسترسی ورود میدهد اما اگر هیچ خروجی ای نبود، یعنی یوزر پیدا نشده یا رمز برابر نبوده، در این صورت از ورود کاربر جلوگیری میشود. فرض کنیم کد کوئری ما به این صورت باشد:
$query = "SELECT name, phone FROM users WHERE username='" . $_POST["username"] . "' AND passwd = '" . $_POST["password"] . '";
فرض کنید کاربر به صورت عادی یوزرنیم و پسورد خود را وارد میکند. در نتیجه پارامترهای زیر با متد POST (چون از فرم استفاده شده) ارسال میشوند:
username = administrator
password = MyP@$SW0Rd
کوئری به صورت زیر خواهد بود:
$query = "SELECT name, phone FROM users WHERE username='administrator' AND passwd = 'MyP@$SW0Rd'";
چون یک رکورد با شرط برابر بودن فیلدهای username و passwd با مقادیر دریافت شده وجود دارد، کاربر به داخل پنل هدایت خواهد شد.
حال فرض کنید یک هکر یا حمله کننده مقادیر پارامترها را به صورت زیر ارسال کند:
username = ' OR '1' = '1
password = ' OR '1' = '1
کوئری به صورت زیر خواهد بود:
$query = "SELECT name, phone FROM users WHERE username='' OR '1' = '1' AND passwd = '' OR '1' = '1'";
عملگر OR یک کار بسیار مهم انجام خواهد داد. در کوئری بالا برنامه به این صورت عمل میکند:
فیلدهای name و phone را از تیبل users بگیر به شرط این که در یکی از رکوردها، مقدار username برابر {خالی} باشد یا اگر ۱ برابر ۱ باشد و شرط دوم هم این که مقدار passwd برابر {خالی} باشد یا اگر ۱ برابر ۱ باشد.
خب میدانیم که همیشه مقدار ۱ برابر ۱ است پس هر دو شرط همیشه درست خواهند بود و در خروجی این کوئری، همه رکوردهای موجود بیرون داده خواهد شد. و چون رکوردی با شرط کوئری (درواقع شرط تقلبی ما) پیدا شد، حمله کننده به پنل منتقل خواهد شد!
- ۹۴/۱۱/۳۰
اگر قبلا در بیان ثبت نام کرده اید لطفا ابتدا وارد شوید، در غیر این صورت می توانید ثبت نام کنید.