SQL INJECTION چیست؟
injection به معنای تزریق و sql injection به معنای تزریق کد sql داخل پایگاه داده و بیرون کشیدن و دستکاری اطلاعات آن می باشد. اما...
کد sql از کجا تزریق می شود؟
از هرکجا که کاربر بتواند اطلاعات وارد سایت کند. معمول ترین راه ها textbox های درون سایت و address bar مرورگر می باشد. یعنی جایی که آدرس سایت را وارد می کنید.
کد sql چگونه inject می شود؟
با یک مثال توضیح می دهیم. فرض کنید شما یک مقدار را در سایت خود از یک textBox دریافت می کنید و آن را درون پایگاه داده پردازش می کنید:
مثلا تکس باکس از شما یک نام می خواهد تا آن را از پایگاه داده جستجو کند و شما داخل آن می نویسید Ali و روی جستجو کلیک می کنید. پشت پرده دستور زیر اجرا می شود:
mysql_query("select * from `UserTable` where `Name`='Ali'");
حال هکر وارد این صفحه می شود و به جای Ali می نویسد:
Ali' or 1=1--
حالا در پشت صحنه این کد اجرا می شود:
mysql_query("select * from `UserTable` where `Name`='Ali' or 1=1");
اگر کمی sql بدانید می توانید بفهمید دستور بالا تمام سطرهای جدول UserTable را بیرون میکشد. زیرا 1=1 همیشه درست است. علامت -- به این معناست که بقیه کد را نخوان. این علامت به این دلیل استفاده می شد که کوتیشن آخر را که به آن دسترسی نیست خنثی کند.
چه سایت هایی مساعد sql injection هستند؟
سایت هایی که موقع گرفتن ورودی از کاربران ورودی را ارزیابی نمی کنند که تزریق نباشد. این ارزیابی روش های مختلف دارد.
چند راه حل ساده برای جلوگیری از sql injection
ورودی های sql injection کجا هستند؟
ورودی اطلاعات به سایت شما معمولا کنترل هایی شبیه textBox , MemoBox , ComboBox و نظیر اینها هستند. ولی کنترلی که کاربر بتواند در آن کد بنویسد تکس باکس می باشد. همچنین خروجی برخی صفحات شما ورودی صفحه دیگریست که اطلاعات صفحه قبل را با queryString می گیرد.
- ورودی از تکس بامس textBox
- ورودی از آدرس بار QueryString
چطور از sql injection جلوگیری کنیم؟
با کنترل ورودی های سایت می توان این کار را انجام داد.
1- سعی کنید تا می توانید اطلاعات مهم را از طریق queryString پاس ندهید و از جایگزین هایی مانند Session، static variables , cooki و ... استفاده کنید. ولی آی دی ها را از طریق queryString بفرستید، چرا که در موتورهای جستجو صفحات جداکانه برای سایتتان محسوب شود.
2-حال فرض کنید مجبورید اطلاعات را از queryString پاس بدهید. در این صورت بهترین و مطمان ترین راه این است که داده ها را به صورت پارامتری در sql اجرا کنید تا مشکل هک بوجود نیاید. پارامتر مزیتی که دارد این است که هکر هرچقدر هم کد بنویسد و هر کدی بنویسد فقط به عنوان یک پارامتر ورودی در sql محسوب می شود و بخشی از دستور نمی شود. این موضوع در مورد تکس باکس ها هم وجود دارد.
3- باز هم فرض می کنیم مجبورید از روش غیر پارامتری استفاده کنید. در اینجا باید داده های ورودی را چک کنید که کد اینجکشن نباشد:
- روش اول اینست که آی دی ها را به نوع عدد صحیح تبدیل کنید تا هکر نتواند به جز ارقام وارد کند.
- روش دوم اینست که عبارات مشکوک که سایت شما را هک می کند فیلتر کنید. مانند: union select, Table_Name, Order by , -- و مانند اینها
- راه بعدی اینست که ورودی ها را انکد کنید.
البته بازهم راه های دیگر وجود دارد ولی شما با رعات موارد بالا به راحتی می توانید از هک شدن سایت و sql injection در امان بمانید.
اما راه حل عملی آن چیست؟
خوب در ادامه چندین مثال عملی جهت جلوگیری این باگ خطرناک را آموزش میدهیم.
اولین و ساده ترین راه حل که بسیار کار آمد می باشد استفاده از یک شرط if میباشد بدین صورت که شما شرط میکنید اگر مقدار وارد شده فقط عدد بود مقدار ارسال شده را در کد قرار بده در غیر این صورت پیغامی مبنی بر اشتباه بودن مقدار نمایش بده.
راه اول:
این شرط برای زمانی خوب است که شما میخواید اطلاعات یک رکورد را بر اساس id فراخوانی نماییدو یا کلیه مقادیر وارد شده بر اساس عدد فعال میشودند. در این متود از تابع preg_match() استفاده شده و در آن گفته شده کارکتر های وارد شده همگی از اعداد آن هم از 0 تا 9 می باشند و مقادیر ارسال شده از 1 رقم تا حداکثر 11 رقم میباشد. و تابع دیگری با نام is_numeric() که بسیار ساده تر از تابع preg_match() میباشد که خود فقط اعداد را قبود مینماید.
و اگر مقدار شما به صورت حروف باشد میتوانید به صورت زیر عمل نمایید.
اگر مقادیر شما ترکیبی از اعداد و یا حروف بود میتوانید به صورت زیر عمل کنید.
راه دوم:
اما برای افزایش سطح امنیت در ارسال مقادیر با متود GET بهتر از مقادیر ارسالی را کد کنیم یعنی انیکه قبل از ارسال مقدار، مقدار را کد کرده (incode)( ب صورت رمز در آورده ) و سپس به صفحه مورد نظر خود ارسال نمایییم و سپس در صفحه مورد نظر مقدار دریافتی را دی کد (decode) نماییم. این کار را با دو تابع urlencode() برای کد کردن و تابع urldecode() برای دی کد کردن انجام میدهیم.
توجه: برای استفاده از این دوتابع باید در نظر داشت که تنها مقادیری که به صورت عدد و حروف باهم یا حروف به تنهایی میباشند کد میشود و مقادیر عددی به تنهایی کد نمیشوند و باید مقادیر عددی را به صورت تغییر در مقدار اعداد کد شوند.
منظور از تغییر در مقدار اعداد این میباشد که بهتر است مثلا اگر شما عدد 66 را مد نظر شماست قبل از ارسال 66 را با مثلا یک عدد دیگر ابتدا ضرب و بعد جمع نمایید و سپس حاصل را ارسال نمایید و بعد در صفحه مورد نظر خود مقدار دریافتی را ابتدا منها و بعد تقسیم نمایید تا به عدد مورد نظر خود همان 66 برسید و بعد مقدار را استفاده نمایید.
برای استفاده از تابع urlencode() میبایست به صورت زیر عمل نمایید.
مقادیر به صورت زیر کد گذاری شده و ارسال میشوند و در url به صورت زیر نمایش داده می شوند.
و برای استفاده و دی کد کردن مقدار به صورت زیر استفاده میکنیم.
توجه: اگر در هنگام کد کردن مقدار از تابع تو در توی urlencode() استفاده کرده اید برای دی کد کردن آن فقط کافی است از یک بار تابع urldecode() این استفاده کنید.
راه سوم:
در روش استفاده از توابع urlencode() و urldecode() باید دقت کنید که امنیت مقادیر شما به صورت ظاهری انجام شده است و امکان دی کد نمودن مقادیر کار ساده ای برای هکر ها می باشد و لذا میبایستی برای افزایش هر چه بیشتر سطح امنیت در ارسال مقادیر با متود های GET و POST باید اقدامات دیگری را انجام داد یکی از پرکاربرد ترین و معروف ترین این کار ها استفاده از تابع mysql_real_escape_string() بوده که چیزی حدود 99% از کد های مخرب را غیر فعال میکند و تمام برنامه نویسان حرفه ای از این تابع برای افزایش سطح امنیت مقادیر دریافتی استفاده میکنند و به کد های سفید تبدیل میکند که جدیدا تابع mysqli_real_escape_string() معرفی شده و سطح امنیت بیشتری را ایجاد می کند.
ما توصیه میکنیم بهتر است شما هم زمان از توابع urlencode() و urldecode() با تابع mysql_real_escape_string() استفاده نمایید و امنیت پروژه های خود را بیشتر نمایید.
برای استفاده از mysql_real_escape_string() میتوان در هر دو صورت متود GET و POST به صورت زیر عمل کنید.
راه چهارم:
همیشه قبل از استفاده از مقادیر دریافتی چک نمایید که آیا مقداری وجود دارد یا خیر و پس از اینکه مقداری موجود بود اقدام به استفاده از مقادیر نمایید. برای این منظور شما می توانید از تو تابع isset() و empty() استفاده نمایید. کار با این توابع بسیار آسان است تایع issset در صورت وجود مقدار عمل میکند و تابع empty() برخلاف تابع isset در صورت نبود مقدار عمل میکند.
برای نمونه کد زیر را مشاهد نمایید.
راه پنجم:
بهتر است همیشه عمل چک نمودن مقادیر ارسالی را به صورت یک function نوشته و بعد از تائید صحت اطلاعات اقدام به استفاده از مقادیر نمایید. این عمل باعث مختصر شدن کد های شما و در نتیجه کم حجم شدن برنامه و کم شدن پردازش توسط سرور شده و همینطور عمل چک نمودن اطلاعات سریعتر و با میزان دقت بیشتری ( استفاده از توابع مختلف به صورت همزمان ) میگردد. و سطح امنیت به مراتب بیشتر میشود.
راه ششم:
پس از اینکه از صحت عملکرد کد های SELECT و UPDATE و DELETE و ... در کار با جداول و رکورد ها مطمئن شدید قسمتی از کد خود را که اقدام به نمایش Error های موجود می باشد را حذف نمایید تا اگر بر اثر تغییر در مقادیر موجود باعث شد تا کد درون کد شما دچار مشکلی شد خطای مربوط به آن نمایش داده نشود تا هکر ها بتوانند نسبت به آن خطا عمل خاصی را انجام دهند. برای نمونه به کد زیر دقت کنید.
راه هفتم:
همیشه اطلاعات مربوط به رمز عبور کاربران را میبایستی به صورت کد شده در دیتابیس زخیره نمود تا اگر زمانی هکر ها موفق به دستیابی به اطلاعات درون دیتابیس شدند کمترین استفاده را از اطلاعات موجود نمایند. برای این منظور توابع چندی وجود دارد که میتواند مقادیر را به صورت غیر قابل فهمی در آورند یکی از این توابع که مقادیر را به صورت کدهایی 32 رقمی (32 کارکتری) تبدیل می کند بابع بسیار معروف و پر کاربرد MD5() می باشد که اکثر برنامه نویسان چه مبتدی و چه حرفه ای از آن استفاده می کنند.
تابع md5() بدین صورت عمل می کند که وقتی شما مقداری را به آن می دهید این تابع مقدار دریافتی را به الگریتم های خاصی که محرمانه میباشد به صورت یک کد 32 رقمی تبدیل می کند. برای استفاده از این تابع به صورت زیر استفاده می شود.
راه هشتم:
اگر تا کنون به فکر طراحی فرمی جهت در یافت نظرات و یا پیام هایی از سمت کاربران نموده باشد حتما مشاهده نموده اید که کاربرانی هستند که همیشه قصد بهم ریختن قالب سایت شما و یا تغییر و به خیال خود هک نمودن سایت شما را دارند و با استفاده از کدهای HTML و یا JavaScript سعی در ایجاد مشکلاتی برای شما دارند. راه حل بسیار ساده ای وجود دارد که جلوی چنین کد هایی را به راحتی می گیرد. برای این منظور سه تابع بسیار پر کاربردی وجود دارد که با استفاده از آنها قادر خواهید بود اقدام به حذف و یا غیر فعال کردن و یا تغییر این کد ها نمایید. این توابع با نام های strip_tags() و htmlentities() و htmlspecialchars() میباشند.
تابع strip_tags() برای حذف کلیه کدهای HTML و برخی از کاراکتر های موجود در Javascript میباشد. برای استفاده از آن به صورت زیر عمل می شود.
تابع htmlentities() برای غیر فعال سازی کدهای HTML و برخی از کاراکتر های موجود در Javascript میباشد. برای استفاده از آن به صورت زیر عمل می شود.
تابع htmlspecialchars() برای تغییر و تبدیل سازی کدهای HTML و برخی از کاراکتر های موجود در Javascript میباشد. برای استفاده از آن به صورت زیر عمل می شود.
توجه: توابع strip_tags() و htmlentities() و htmlspecialchars() بر روی کد های HTML و Javascript اثر گذار هستند و بر روی کد های PHP اثری ندارند. برای فیلتر سازی مقادیر بایستی هم زمان با تابع mysql_real_escape_string() و یا ... استفاده شوند. همانند زیر:
راه نهم:
استفاده ساده از تابع str_replace() برای تغییر مقادیر موجود در یک مقدار دریافتی است. بدین صورت که مثلا می گوید اگر در مقدار دریافت شده حرف A وجود داشت آن را با حرف B یا عدد 2 عوض کن برای این منظور به صورت زیر عمل نمایید.
راه دهم:
در زیر توابع امنیتی دیگری را که جهت فیلتر سازی مقادیر کاربرد دارند را درج کرده ایم که هرکدام بر حسب نوع نیاز برنامه نویس عمل میکنند. که آن را به صورت یک function نوشته ایم.
توجه: دقت نمایید که در function بالا به دلیل استفاده از توابع مشابه ممکن است خروجی درست عمل نکند. لذا بر حسب نیاز خود اقدام به استفاده از توابع مورد نظر نمایید.
منبع: دنیای فناوری با حساس کامپیوتر