درس یازدهم- امنیت تارنما از نگاه پیاچپی
مقدمه
تا به این درس تکنیکهای زیادی از پیاچپی یاد گرفتیم که براحتی توسط آنها میتوانیم یک تارنما با قابلیت پذیرش کاربر بنا کنیم. یکی از نکات مهمی که بحثی از آن در طول دوره نشده است٬ امنیت سیستم ساخته شده است. در این درس به توانمندی سیستم از نظر امنیتی میپردازیم٬ چرا که هر چقدر سیستم شما خوب کار کند٬ اگر امنیت لازم را فراهم نکرده باشید٬ براحتی قابل شکستن خواهد بود.
نکته بسیار مهم: در این دوره آموزشی٬ ما بحث امنیت را به عنوان یک یا چند درس بطور مجزا شرح میدهیم و تا قبل از این درسها برای سادهتر کردن آموزش، نکتههای امنیتی را برای درسهای آخر گذاشتیم. حال ما بر آنیم که بحث امنیت را آغاز کنیم و به سراغ کدهایمان میرویم تا از نظر امنیتی آنها را مسلح کنیم. برای شما در زمان ساخت یک تارنما٬ به این شکل عمل کردن یک اشتباه محض است٬ یعنی نباید ابتدا تارنما را ساخته و بعد به فکر امن کردن آن باشید. کار امنیت برای تارنما باید از همان ابتدا در ذهن و کدهای شما بیاید. یعنی با توسعه هر قسمت٬ هم زمان آن بخش را هم از نظر امنیتی تجهیز کنید.
امنیت تارنما
برای شرح هر چه بیشتر این درس ما بحث امنیت را به بخشهای مجزا تقسیم میکنیم و بعد بر اساس هر بخش نکات امنیتی آن را بررسی میکنیم.
غیر فعال کردن phpinfo()
همانطور که میدانید این تابع مشخصات کاملی از پیاچپی نصب شده در سرور را به ما میدهد که در زمان توسعه بسیار مفید است٬ اما بعد از کامل کردن سیستم باید این تابع از کار بیافتد. البته اگر شما سرور خود را داشته باشید و یا در حالت «محلی» تارنمای خود را توسعه دادهاید٬ شما توانایی از کار انداختن این تابع را دارید. در غیر اینصورت با مدیر سرور تماس بگیرید. به احتمال زیاد این تابع قبلا از کار افتاده اما کار از محکم کاری عیب نمیکند. این تابع در فایل php.ini قرار دارد٬ پس در صورت دسترس به این فایل رفته و با جستجوی عبارت disable_functions با کمکctrl + F مقدار روبروی این عبارت را با نام تابع پر کنید.
disable_functions = phpinfo
عدم نمایش ایرادهای اتفاق افتاده در سیستم
در زمان توسعه تارنما دیدیم که میتوانیم با دیدن خطاها به رفع آنها بپردازیم٬ بطور کلی یکی از تکنیکهای ابتدایی ساخت سیستم همین نمایش خطاها و بر طرف کردن آنها است. اما آیا بعد از اتمام کار هنوز باید این اخطارها در سیستم نمایش داده شود؟ پاسخ این پرسش خیر است. یعنی بعد از اتمام کار باید سیستم نمایش خودکار اخطارها را از کار بیاندازیم٬ میتوانیم تابعی بنویسیم که بررسی «محلی» بودن و یا «روی خط» بودن سیستم را انجام دهد و بر اساس آن اخطارها را نمایش یا پنهان کند.
$state == "local" ;
if( $state == "local")
{
ini_set( "display_errors", "1" );
error_reporting( E_ALL & ~E_NOTICE );
}
else
{
error_reporting( 0 );
}
حال با تغییر مقدار متغییر $state براحتی و در یک لحظه سیستم نمایش را فعال یا غیر فعال میکنیم. این تابع را در فایل functions.php که در سیستم وارد میشود٬ بگذارید.
ارزیابی دادههای وارد شده توسط کاربران یا بازدیدکنندگان
همیشه این نکته را در نظر بگیرید که نباید به هیچ کس اعتماد کنید٬ با این فرضیه زمانی که دادهای را از کاربری دریافت میکنید باید قبل از هر کار این داده مورد بررسی قرار گیرد. بطور مثال برگه ثبت نام یادتان هست؟ در این برگه کاربران اطلاعاتی را وارد فرم کرده و به سیستم شما میفرستند٬ این اطلاعات وارد پایگاه دادهها شده و بعد از آنها استفاده میشود. بیاد داشته باشید که همیشه استفاده کنندگان تارنمای شما کاربران خوب شما نیستند. ممکن است افرادی با وارد کردن کدهایی به سیستم شما دسترسی پیدا کنند.
به این نوع حمله « نفوذ به پایگاه» یا SQL INJECTION میگویند. راه مقابله با این حمله هم بسیار ساده و با استفاده از یک تابع است. کافیست دادههای وارد شده را قبل از انتقال به پایگاه از یک تابعی بگذرانید و خروجی تابع را در یک متغییر قرار دهید.
$name = mysqli_real_escape_string($dbc, $_POST[‘first_name’]);
اگر به فایل «ثبت نام» مراجعه کنید٬ متوجه میشوید که تمام ورودیهای فرم از این تابع گذر میکنند. البته قبل از این تابع٬ از تابع دیگری بنامtrim() استفاده شده است که برای از بین بردن فاصله و بعضی کاراکترها از ابتدا و آخر هر رشته بکار رفته است.
$fname = $_POST['f_name'] ;
$fn = mysqli_real_escape_string($dbc , trim($fname));
همانطور که میبینید٬ ابتدا مقدار ورودی برای «نام» را در متغییری قرار دادهایم و بعد از trim کردن آن٬ متغییر را از تابع مورد نظر هم گذراندهایم.
جلوگیری از گرفتن هرزنامه در رایانامه سیستم Preventing Spam
برای جلوگیری از دریافت هرزنامه به رایانامهای که در سیستم قرار دادهاید میتوانیم از تابعهای استفاده کنیم که کلمات خطرناک را از دریافتیهای فرم پاک میکند. این استفاده در برگه تماس ما اتفاق میافتد٬ جایی که شما به بازدید کنندگان راهی برای ارسال رایانامه ایجاد کردیهاید.
تابع مورد استفاده در این موقعیت str_replace()است. همانطور که از نام تابع پیداست٬ این تابع توانایی تعویض کاراکترهای ارسالی را با هر کاراکتری که شما بدهید دارد.
ابتدا ما متغییری میسازیم و بعد تمام کاراکترها یا رشتههای خطرناک را درون آن قرار میدهیم. بعد با استفاده از تابعی دیگر تمام ورودیها را بررسی و در صورت وجود هر کدام از این کلمات خطرناک جای آنها را با جای خالی تعویض میکنیم؛ در اصل با این کار آنها را پاک میکنیم.
کافیست که تابعی بسازیم و در آن تابع از تابع str_replace() استفاده کنیم:
function spam_scrubber($value) { // تابعی که با گرفتن یک ورودی آن را با کلمات خطرناک مقایسه میکند
$very_bad = array('to:', 'cc:', 'bcc:', 'content-type:', 'mime-version:', 'multipart-mixed:', 'content-transfer-encoding:'); // کلمات خطرناک برای از بین بردن در بین کلمات فرستاده شده به عنوان رایانامه
foreach ($very_bad as $v) {// برای خواندن و مقایسه تمام خانههای آرایه حاوی کلمات خطرناک
if (stripos($value, $v) !== false) return ''; // تابع جابجا کننده کلمات خطرناک با جای خالی = پاک کردن
}
$value = str_replace(array( " ", " ", "%0a", "%0d"), ' ', $value);
return trim($value);
}
در درون تابع٬ متغییر$very_bad که آرایهای است٬ وجود دارد که شامل تمام کاراکترهای منفی و خطرناک در زمان ارسال رایانامه است. تابعspam_scrubber() یک مقدار به عنوان پارامتر دریافت میکند و بعد با استفاده ازforeach و تابع درون آن (str_replace()) تمام کاراکترهای ورودی را با کلمات خطرناک داخل آرایه$very_bad مقایسه میکند٬ در صورت برابری کلمات جای آنها را با جای خالی ‘ ‘ عوض میکند. حال تنها کاری که باید انجام شود استفاده از این تابع که خودمان ساختیم در ارزیابی تک تک ورودیها است.
$scrubbed = array_map('spam_scrubber', $_POST);
// این تابع تمام ورودیها را بطور یکجا از تابع ساخته شده توسط ما میگذراند.
بجای گذراندن تک تک ورودیها بطور مجزا (که کار بسیار زیادی از نظر کد نویسی است). با استفاده از تابع دیگری بنامarray_map() تمام ورودیها را بطور یکجا از تابع خود میگذرانیم و آنها را در آرایه دیگری بنام $scrubbed قرار میدهیم.
if (!empty($scrubbed['name']) && !empty($scrubbed['email']) && !empty($scrubbed['comments']) ) {
...
{
باقی ماجرا هم که دیگر مشخص است؛ باید رایانامه را بفرستیم. حال به سراغ فایل تماس خود رفته و تغییرات را انجام دهید. کافیست که تابع spam_scrubber را قبل از ارسال رایانامه بگذارید و رایانامه را با خروجیهای توابع یاد شده بفرستید.
ارزیابی دادهها با توجه به نوع آنها
تا به اینجا ارزیابی ورودیها بر اساس این بود که نخست٬ آیا کاربر دادهای را وارد کرده یا نه و بعد گذراندن آن داده از توابع ذکر شده. یک راه دیگر که میتوانیم از آن بهره ببریم این است که بررسی کنیم٬ آیا نوع داده ورودی با نوع دادهای که سیستم از کادر فرم انتظار دارد همخوانی دارد یا نه!
پیاچپی توابعای برای بررسی هر نوع داده دارد٬ توابعی مانند:
Is_numeric(): برای بررسی شماره بودن داده
Is_array(): بررسی آرایه بودن ورودی
Is_float(): بررسی اعشاری بودن یا فلوت بودن نوع داده
Is_string(): بررسی رشته بودن داده
Is_null(): بررسی نال بودن دادهی ورودی٬ فراموش نکنیم کهNULL با خالی فرق دارد.
Is_integer(): بررسی عدد صحیح بودن داده
اما ما میتوانیم نوع متغییر ورودی را هم تغییر بدهیم (البته بعد از وارد شدن داده در آن). این کار براحتی قابل اجراست.
$variable = 20.5;
Echo (int) $variable ; // 20
Echo (float) $variable ; // 20.5
با این کار ما میتوانیم اطمینان پیدا کنیم که خروجی هر متغییر یا تابع٬ همان نوع مورد نیاز سیستم ماست. با این کار جلوی بعضی از ایرادها و منفذها گرفته میشود.
$var = “hello”;
Echo (int) $var ; // 0
همانطور که از مثال بالا مشخص است٬ خروجی متغییری حامل رشته در صورتی که به شماره تبدیل شده باشد٬ صفر میشود. با این کار اجازه ورود رشته را به داخل پایگاه یا کد برنامه نمیدهیم.
فرض کنید که در تارنمای شما بخشی است که کاربر با وارد کردن سن و قد خود مناسبترین وزن را برای آن سن و قد دریافت میکند. حال تابع شما دو ورودی شماره دارد و یک خروجی که آن هم شماره است. اگر کاربر بجای عدد٬ متنی را وارد سیستم شما کند٬ چه اتفاقی رخ میدهد؟ کمترین احتمال بروز خطا است٬ خوب اگر خطای سیستم هم چاپ شده باشد٬ با این حساب کاربر مورد نظر به یکسری از موارد استفاده شده در سیستم شما براحتی دسترسی پیدا میکند. این یک مثال بسیار ساده برای استفاده از این دست تکنیکها برای محافظت از سیستم است.
در درس بعدی با مباحث دیگری از امنیت در پیاچپی آشنا میشویم.
اگر قبلا در بیان ثبت نام کرده اید لطفا ابتدا وارد شوید، در غیر این صورت می توانید ثبت نام کنید.