حفاظت از وبسایت PHP در برابر حملههای تزریق SQL


اگر یک توسعهدهنده وب باشید احتمالاً گاهبهگاه خبرهایی در مورد حملههای هکرهای مختلف به وبسایتها را از طریق روش «تزریق اسکیواِل» و گرفتن کنترل کامل آن، تغییر دادن، کسب دسترسی یا تخریب دادههای آن را شنیدهاید. مسلماً به عنوان یک برنامهنویس وب میخواهید در مورد روشهای جلوگیری از چنین نفوذها آگاه باشید. در این نوشته به معرفی مفهوم تزریق اسکیواِل و کارهایی که میتوان در برابر آن انجام داد خواهیم پرداخت. همچنین توصیههایی در مورد روشهای آسان امن سازی دادهها ارائه خواهیم نمود.
لطفاً توجه داشته باشید که این نوشته یک راهنمای پیشرفته محسوب نمیشود؛ اما اگر در این زمینه مبتدی هستید، اطلاعات خوبی در اختیار شما قرار خواهد داد.
تزریق اسکیواِل چیست و چگونه مورد استفاده قرار میگیرد؟
تزریق اسکیواِل اساساً روشی است که علیه وبسایتها و برنامههای مختلف جهت کسب دسترسی به دادههای آن که در پایگاه داده اسکیواِل ذخیره شدهاند، صورت میگیرد. تزریق اسکیواِل برای دسترسی به اطلاعات پایگاه داده، تخریب اطلاعات یا دستکاری آنها انجام مییابد. این روش برای سوءاستفاده از آسیبپذیری امنیتی یک برنامه یا وبسایت صورت میپذیرد. روشهای مختلفی برای تزریق اسکیواِل وجود دارند؛ اما در این نوشته تنها انواع ساده را بررسی میکنیم.
در ادامه شیوه استفاده از روش تزریق اسکیواِل را برای درک بهتر نحوه عملکرد آن بررسی میکنیم. ما از PHP به عنوان زبان اسکریپت نویسی در مثالهای خود استفاده میکنیم. البته شما میتوانید از هر زبان دیگری نیز استفاده کنید، چون نقطه توجه اصلی ما بر روی دستورهای اسکیواِل است.
مثال
فرض کنید شما کسی هستید که کسبوکاری برای خود راهاندازی کردهاید. یک پایگاه داده اسکیواِل دارید که در آن جدولی وجود دارد که شامل همه اطلاعات مشتریهای شما است. شما از این جدول برای ارسال اعلانهای مهم، صدور صورتحساب و موارد دیگر استفاده میکنید. یک سال طول کشیده است تا 50،000 کاربر مهم را جمع بکنید. شما از طریق ورود آنلاین پایگاه داده خود را مدیریت میکنید، چون بدین ترتیب میتوانید درزمان مسافرت و یا اشتغال به کارهای دیگر مستقیماً از طریق وبسایت وارد پایگاه داده خود شوید.
کوئری اسکیواِل شما در اسکریپت ورود به پایگاه داده در زبان پیاچپی به صورت زیر خواهد بود:
<? $q = "SELECT `id` FROM `users` WHERE `username`= ' ".$_GET['username']. " ' AND `password`= ' ".$_GET['password']. " ' "; ?>
تصور کنید روزی فرا میرسد که یک هکر به سراغ وبسایت شما میآید. او بر روی دکمه ورود به وبسایت کلیک میکند و در فیلد نام کاربری عبارت زیر را وارد میکند:
'; SHOW TABLES;
بدین ترتیب همه جداولی که در وبسایت وجود دارند در معرض دید هکر قرار میگیرند. از آنجا که او نام جدول شما را میداند دستور زیر را وارد میکند:
'; DROP TABLE [your table's name];
و همه اطلاعات شما نابود شدهاند.
توجه کنید که تلاشهایی وجود دارند که بسیار پیچیدهتر از این هستند و فرد ممکن است زمان بسیار زیادی را جهت ورود به وبسایت شما صرف کند و یا حتی از یک برنامه در جهت سوءاستفاده از آسیبپذیری وبسایت، پایگاه داده یا برنامهتان بهرهبرداری کند.
مرحله 1: استفاده از ()mysql_real_escape_string
این تابع پیاچپی کاراکترهای خاصی که برای کوئری های SQL استفاده میشود را از مقادیر وارد شده در وبسایت حذف میکند و بدین ترتیب شما را در برابر حمله هکرها حافظت میکند.
این کوئری چیزی شبیه زیر خواهد بود:
<? $q = "SELECT `id` FROM `users` WHERE `username`= ' ".mysql_real_escape_string($_GET['username']). " ' AND `password`= ' ".mysql_real_escape_string($_GET['password']). " ' "; ?>
مرحله 2» استفاده از ()mysql_query
استفاده از ()mysql_query حفاظت مضاعفی در برابر حملههای تزریق اسکیواِل ایجاد میکند. یک کوئری که درون لفافه ()mysql_query پیچیده نشده باشد؛ به هکر اجازه میدهد که به جای یک مورد، چند دستور مختلف اسکیواِل را از فیلد نام کاربری اجرا کند که آسیبپذیری دیگری محسوب میشود. ()mysql_query تنها اجازه میدهد که هر بار یک دستور اسکیواِل اجرا شود.
بدین ترتیب کوئری به صورت زیر خواهد بود:
<? //connection $database = mysql_connect("localhost", "username","password"); //db selection mysql_select_db("database", $database); $q = mysql_query("SELECT `id` FROM `users` WHERE `username`= ' ".mysql_real_escape_string($_GET['username']). " ' AND `password`= ' ".mysql_real_escape_string($_GET['password']). " ' ", $database); ?>
اتصالهای خود را متمرکز کنید
شما در اسکریپتهای خود باید اتصالها را در یک صفحه جمع کنید.
در هر صفحه دیگری که به این اتصالها نیاز داشتید میتوانید از تابع ()include استفاده کنید تا صفحهای که اطلاعات اتصال پایگاه داده اسکیواِل را ذخیره کرده است مورد استفاده قرار دهید. با این روش مجبور خواهید بود تا کوئریهایی که در هر صفحه میسازید را با یک فرمت خاص تولید کنید و احتمال این که بر حسب تصادف راه را برای یک آسیبپذیری باز کنید کاهش مییابد.
بنابراین فرض کنید صفحهای به نام «connections.php» ایجاد کرده و دستورهای زیر را در آن وارد کردهایم:
<? //connection $database = mysql_connect("localhost", "username","password"); //db selection mysql_select_db("database", $database) ?>
میتوانیم کوئریهای خود را با استفاده از این تنظیمات اصلاح کنیم. بدین ترتیب صفحه ورود ما چیزی شبیه کد زیر خواهد بود:
<? include("connections.php"); $q = mysql_query("SELECT `id` FROM `users` WHERE `username`= ' ".mysql_real_escape_string($_GET['username']). " ' AND `password`= ' ".mysql_real_escape_string($_GET['password']). " ' ", $database); ?>
متغیرها را در آغاز صفحه اعلان کنید
در اغلب زبانهای برنامهنویسی از شما خواسته میشود که متغیرها را پیش از استفاده اعلان کنید تا بتوانید آنها را در سراسر اسکریپت استفاده نمایید. با این حال پیاچپی چنین الزامی ندارد، اما بهتر است خود را عادت بدهید که همه متغیرها را در ابتدای صفحه اعلان کنید.
ممکن است بپرسید که اعلان کردن متغیرها در ابتدای صفحه وقتی میتوان آنها را در هر جای صفحه اعلان کرد چه مزیتی دارد؟ آیا این وضعیت دوبارهکاری محسوب نمیشود؟
باید در پاسخ گفت که اعلان کردن همه متغیرها در ابتدای صفحه علاوه بر منابع قالببندی صفحه و خوانایی چند مزیت دارد:
- این کار مقدار کدی که باید بنویسید را کاهش میدهد.
- زمانی که متغیری در ابتدای صفحه اعلان میشود، میتوانید آن را در همه جای صفحه مورد استفاده قرار دهید و نگران آسیبپذیریها نباشید.
- این روش تمیزتر و سازمانیافتهتر است و باعث تسریع در کارها و کاهش خطاها میشود.
اگر متغیرها را در ابتدای صفحه اعلان کنیم، کد صفحه ورود ما به صورت زیر در میآید:
<? include("connections.php"); $username = mysql_real_escape_string($_GET['username']); $password = mysql_real_escape_string($_GET['password']); $q = mysql_query("SELECT `id` FROM `users` WHERE `username`= ' ".$username. " ' AND `password`= ' ".$password. " ' ", $database); ?>
حتی میتوانید از این هم فراتر رفته و تابعی تعریف کنید که کار اعلان متغیرها را برای شما انجام دهد و مقدار کدنویسی لازم را باز هم کاهش دهید. به مثال زیر نگاه کنید:
<? function cleaner($input){ //clean variable, including mysql_real_escape_string() } include("connections.php"); $username = cleaner($_GET['username']); $password = cleaner($_GET['password']); $q = mysql_query("SELECT `id` FROM `users` WHERE `username`= ' ".$username. " ' AND `password`= ' ".$password. " ' ", $database); ?>
حتی پس از پاکسازی نیز کد خود را بررسی کنید
شما میتوانید از بررسیهای مختلف استفاده کنید تا مطمئن شوید که پردازشهای ناخواستهای روی سرور شما انجام نمییابد. این کار از طریق بررسی اسکریپت تا پیش از مرحله اجرای کوئری امکانپذیر است؛ شما باید تنها زمانی کوئری را اجرا کنید که دادهها قابل قبول باشند.
<? function cleaner($input){ //پاکسازی ورودی شامل mysql_real_escape_string() } include("connections.php"); $username = cleaner($_GET['username']); $password = cleaner($_GET['password']); //بررسی کنید که ورودی خالی نباشد if(($password == '') || ($username == '')){ // اجازه عبور ندهید } //Check if they are putting in way too many characters than should be allowed. else if((strlen($username) > 20) || (strlen($password)> 20)){ //اجازه عبور ندهید } //اینک همه بررسیها انجام یافته و میتوان کوئری را اجرا کرد else { $q = mysql_query("SELECT `id` FROM `users` WHERE `username`= ' ".$username. " ' AND `password`= ' ".$password. " ' ", $database); } ?>
اینها مفاهیم مقدماتی بود که برای مقابله با تزریق اسکیواِل ضروری محسوب میشوند. اگر هر گونه دیدگاه یا پیشنهادی دارید میتوانید در بخش نظرات با ما و دیگر خوانندگان فرادرس در میان بگذارید.
اگر این مطلب مورد توجه شما واقع شده است، احتمالاً آموزشهای زیر برای شما مفید خواهند بود:
- آموزش تست نفوذ در جهان واقعی - رایگان
- آموزش تست نفوذ وب - فرادرس
- آموزش کار با دستورات پایگاه داده در SQL Server
- اتصال رشتهها در SQL و روشهای استفاده هوشمند از آن
- آموزش امنیت شبکه های کامپیوتری
- آموزش SQL Server Management Studio | کامل، رایگان و گام به گام
==