MySQL و تزریق SQL – راهنمای جامع


اگر شما ورودی کاربر را از طریق یک صفحه وب دریافت کرده و آن را در پایگاه داده MySQL درج کنید، این احتمال وجود دارد که در معرض مشکلات امنیتی گستردهای به صورت تزریق SQL یا (SQL Injection) قرار بگیرید. در این مطلب از سلسله مقالات راهنمای MySQL به شما کمک میکنیم تا از وقوع چنین حالتی جلوگیری کرده و اسکریپتها و گزارههای MySQL را امنتر بکنید.
تزریق MySQL
تزریق MySQL به طور معمول زمانی رخ میدهد که از کاربر چیزی مانند نام پرسیده میشود و او به جای نام خود یک عبارت MySQL ارائه کند که به صورت ناشناس روی پایگاه داده وبسایت اجرا میشود.
هرگز نباید به دادههای ارائه شده از سوی کاربر اعتماد کرد و تنها پس از اعتبارسنجی باید مورد پردازش قرار گیرند. این کار از طریق تطبیق الگو صورت میگیرد. در مثال زیر نام کاربری محدود به کاراکترهای حرفی و ارقام به علاوه زیرخط است و طولی بین 8 و 20 کاراکتر دارد. در صورت نیاز میتوان این قواعد را اصلاح کرد:
if (preg_match("/^\w{8,20}$/", $_GET['username'], $matches)) { $result = mysql_query("SELECT * FROM users WHERE username = $matches[0]"); } else { echo "username not accepted"; }
برای نمایش مشکل، اسکریپت زیر را در نظر بگیرید:
// supposed input $name = "Qadir'; DELETE FROM users;"; mysql_query("SELECT * FROM users WHERE name = '{$name}'");
فرض شده است که این فراخوانی تابع برای بازیابی رکوردی از جدول کاربران است که ستون نام با نام ذکر شده از سوی کاربر تطبیق مییابد. در شرایط معمول، name$ تنها میتواند شامل کاراکترهای حرفی و ارقام و احتمالاً فاصله باشد. اما در این جا با الحاق یک کوئری به متغیر name$، این فراخوانی به پایگاه داده تبدیل به یک فاجعه شده است. کوئری DELETE تزریق شده موجب پاک شدن همه رکوردها از جدول users میشود.
خوشبختانه اگر از MySQL استفاده میکنید، تابع name$ امکان پشته سازی کوئریها یا اجرای چندین کوئری در یک فراخوانی تابع را نمیدهد. اگر تلاش شود که کوئریها تجمیع شوند، فراخوانی ناموفق خواهد شد.
با این وجود، افزونههای دیگر پایگاه داده PHP مانند SQLite و PostgreSQL، کوئریهای پشته شده را به سادگی اجرا میکنند و همه کوئریهای ارائه شده را در یک رشته اجرا کرده و مشکل جدی امنیتی ایجاد میکنند.
جلوگیری از تزریق SQL
شما میتوانید همه کاراکترهای escape را به طرز هوشمندانهای در زبانهای برنامهنویسی مانند PERL و PHP مدیریت کنید. افزونه MySQL برای PHP تابع ()mysql_real_escape_string را برای escape کردن این کاراکترها که خاص MySQL هستند ارائه کرده است:
if (get_magic_quotes_gpc()) { $name = stripslashes($name); } $name = mysql_real_escape_string($name); mysql_query("SELECT * FROM users WHERE name = '{$name}'");
مشکل Like
برای حل مشکل Like در SQL یک مکانیسم escape کردن خاص باید کاراکترهای % و _ ارائه شده از سوی کاربر را به موارد متنی تبدیل کند. بدین منظور میتوان از تابع ()addcslashes استفاده کرد. این تابع امکان تعیین یک بازه کاراکتری برای escape شدن را میدهد.
$sub = addcslashes(mysql_real_escape_string("%something_"), "%_"); // $sub == \%something\_ mysql_query("SELECT * FROM messages WHERE subject LIKE '{$sub}%'");
اگر این نوشته برای شما مفید بوده است، آموزشهای زیر به شما پیشنهاد میشوند:
- مجموعه آموزشهای پایگاه داده و سیستم های مدیریت اطلاعات
- مجموعه آموزشهای طراحی و توسعه پروژههای وب
- مجموعه آموزشهای برنامهنویسی
- حفاظت از وبسایت PHP در برابر حملههای تزریق SQL
- تزریق SQL پیشرفته — انگشتنگاری پایگاه داده و شناسایی عمومی برای اجرای حملهای مؤثرتر
- اصول پایگاه داده و SQL — همه آن چه یک هکر باید بداند
- MongoDB چیست؟ — راهنمای شروع با دیتابیس مانگو دی بی
==