سایت نوین دولوپرز غیر فعال شد . پلیر آموزش ها تا پایان سال ۱۴۰۲ فعال است در صورتی که با پلیرتان مشکل داشتید از طریق حساب کاربری تیکت ثبت کنید
سایت نوین دولوپرز غیر فعال شد . پلیر آموزش ها تا پایان سال ۱۴۰۲ فعال است در صورتی که با پلیرتان مشکل داشتید از طریق حساب کاربری تیکت ثبت کنید
0
0

امنیت در php

180 بازدید
امنیت در php

برقراری امنیت در php :

آموزش امنیت در php . امنیت ،  آزادی از ریسک یا خطر است !!

نیاز به ایمنی برای طبیعت انسان ضروری است . در تمام زندگی ما از جمله زمانی که در خانه و  درمحل کار   سپری می کنیم.

 یک عارضه جانبی ناگوار درا ستفاده از اینترنت ، که به سرعت در حال رشد است ،  به خطر افتادن ایمنی زندگی شخصی و حرفه ای ما است .

استفاده از اینترنت شامل  بسیاری از جنبه ها مانند ، افرادی است که اطلاعات شخصی را در فروشگاه‌ های آنلاین پست می‌کنند ، 

 کسب‌وکارهایی که میلیون‌ها دلار تراکنش را از طریق وب انجام می‌دهند، و شبکه‌های خدمات وب که امکان تراکنش‌های بین کسب‌وکار را فراهم می‌کنند ، است .  

هرچه جهان بیشتر به هم متصل شود  اهمیت امنیت بیشتر مطرح می شود.

شکی نیست که مهم ترین بخش ها در پازل امنیت اینترنت، خود سرورهای وب واقعی هستند که مستقیماً با توده کاربران اینترنت تعامل دارند.

Php از مجموعه ای از ابزارها برای توسعه صفحات به محبوب ترین زبان برنامه نویسی وب تبدیل شده است.

همراه با چنین محبوبیتی نگرانی های جدیدی درباره عملکرد، قابلیت نگهداری، مقیاس پذیری، قابلیت اطمینان و (مهمتر از همه) امنیت به وجود می آید.

محبوب ترین زبان توسعه وب php  ، داده ها را مبادله می کند ، تراکنش های مالی انجام می دهند و غیره.

 اخیراً هشدارهای امنیتی متعددی در مورد امنیت مطرح شده است . اما در واقع، اکثریت آنها نقص در php نیست ، بلکه به دلیل استفاده نادرست و نا امن  کدها توسط توسعه دهندگان برنامه هاست .

متاسفانه زمانی که در بسیاری در پروژه ها از کلمه php  استفاده می شود ، این باعث می شود که اشکالات امنیتی در آن برنامه ها به اشتباه با خود فناوری اشتباه گرفته شود.

همانطور که گفته شد، بیشتر این مشکلات امنیتی در سطح برنامه ها نتیجه نوشتن کدهای ناامن توسط توسعه دهندگان است .

امنیت به همان اندازه که ویژگی یک توسعه دهنده است، ویژگی یک زبان نیست. هیچ زبانی نمی‌تواند از کد ناامن جلوگیری کند، اگرچه ویژگی‌ هایی وجود دارد که می‌تواند به توسعه‌دهنده آگاه از امنیت ،کمک کند یا مانع  از خطرات شود .

 

راه حل اول  : گزارش خطا

هر توسعه دهنده ای مرتکب خطا می شود .  ویژگی php برای گزارش خطا می تواند به شناسایی و یافتن این خطاها کمک کند . 

با این حال این گزارش خطا با اطلاعات دقیقی که ارائه می دهد می تواند به یک مهاجم و هکر نیز نمایش داده شود که بسیار خطرناک است!

 پس مهم است که اطمینان حاصل شود که این اطلاعات هرگز به عموم مردم نشان داده نمی شود  .

برای این منظور تنها کافی است display_errors را در کدها در حالت off تنظیم کنیم .

اما قطعا شما می خواهید به عنوان توسعه دهنده از این ارور ها مطلع شوید !

پسlog_errors  را روشن یا on کنید .

در نتیجه ارورها در فایلی جداگانه در هاست شما با نام error_log ذخیره می شوند که برای رفع مشکلات می توانید به این فایل مراجعه کنید .

اما به عموم افراد عادی یا هکرها نمایش داده نمی شوند.

برای این منظور اگر در هاست خودبه php.ini دسترسی دارید  ini_set(‘display_errors’, FALSE);   را به آن بیافزایید .

 

    <?php

 

    ini_set(‘error_reporting’, E_ALL | E_STRICT);

    ini_set(‘display_errors’, ‘Off’);

    ini_set(‘log_errors’, ‘On’);

    ini_set(‘error_log’, ‘/usr/local/apache/logs/error_log’);

 

    ?>

اگر از یک هاست اشتراکی استفاده می کنید احتمالا به php.ini  یا  httpd.conf دسترسی نخواهید داشت . (  در صورتی که درباره انواع هاست ها اطلاعاتی ندارید نگران نباشید در آموزش های نوین دولوپرز مفصلا درباره آنها صحبت کرده ایم ) 

در این صورت در فایل اصلی صفحات خود که در تمام صفحات دیگر استفاده و include می شود ( مثلا connection ) یا در index.php  از کدهای ذیل می توانید استفاده کنید :

 

<?php

display_errors(false);

log_errors(true);

 

// Turn off all error reporting  خاموش کردن تمامی گزارشات خطاها 
error_reporting(0);

 

// Report simple running errors نمایش گزارشات خطاهای ساده 
error_reporting(E_ERROR | E_WARNING | E_PARSE);

 

// Reporting E_NOTICE can be good too (to report uninitialized
// variables or catch variable name misspellings …) نمایش هشدارها  
error_reporting(E_ERROR | E_WARNING | E_PARSE | E_NOTICE);

 

// Report all errors except E_NOTICE نمایش همه خطاها به جز هشدار ها  
error_reporting(E_ALL & ~E_NOTICE);

 

// Report all PHP errors نمایش تمامی خطاها 
error_reporting(E_ALL);

 

// Report all PHP errors
error_reporting(-1);

 

// Same as error_reporting(E_ALL);
ini_set(‘error_reporting’, E_ALL);

 

?>

E_ALL تمام سطوح خطا را نشان می دهد.

E_STRICT که در PHP 5.0 معرفی شده است، پیشنهاد یا اخطار استاندارد کدگذاری به عنوان بهترین عمل را نشان می دهد.

E_STRICT  از نسخه  PHP 5.4  در E_ALL گنجانده شده است.

 

همچنین php  به شما اجازه می دهد که ارور ها را در فایلی به صورت دلخواه نیز مدیریت کنید ، به طور مثال

set_error_handler(‘my_error_handler’);

 

می توانید تابع خود را به شکل زیر تعریف کنید :

<?php

function my_error_handler ($number، $string، $file، $line، $context){

      $error = “=  ==  ==  ==  ==\nPHP ERROR\n=  ==  ==  ==  ==\n”;

      $error .= “Number: [$number]\n”;

      $error .= “String: [$string]\n”;

      $error .= “File:   [$file]\n”;

      $error .= “Line:   [$line]\n”;

      $error .= “Context:\n” . print_r($context, TRUE) . “\n\n”;

 

      error_log($error, 3, ‘/usr/local/apache/logs/error_log’);

    }

?>

 

به عنوان مثال، می توانید تابعی ایجاد کنید که فقط هشدارها را کنترل کند:

<?phpset_error_handler(‘my_warning_handler’, E_WARNING);?>

 

راه حل دوم  :  سادگی 

 

پیچیدگی باعث ایجاد اشتباه می شود و اشتباهات می توانند آسیب پذیری های امنیتی ایجاد کنند.

این یک حقیقت ساده است ! به همین دلیل است که سادگی از ویژگی های مهم یک برنامه کاربردی امن است .

پیچیدگی غیر ضروری به همان اندازه بد است که یک ریسک غیرضروری .

به عنوان مثال، کد زیر را در نظر بگیرید:

<?php

$search = (isset($_GET[‘search’]) ? $_GET[‘search’] : ”);

?>

 

این روش می تواند آلوده بودن search$  به یک خطا یا عامل مخرب را ، به ویژه برای توسعه دهندگان بی تجربه پنهان کند !

سادگی به معنی یک خط کد کمتر نیست !

این روش را با روش ذیل مقایسه کنید :

 

<?php 

 

   $search =” ”;  

  if (isset($_GET[‘search’]))    {     

          $search = $_GET[‘search’]; 

   }  

 

?>

رویکرد یکسان است، اما یک خط ، به ویژه اکنون ، توجه زیادی را به خود جلب می کند.

$search = $_GET[‘search’];

بدون تغییر منطق ، اکنون  بروز مشکلات آشکارتر  است .

هیچ گاه هر داده ای را مستقیما و بدون اعتبار سنجی بلافاصله مورد استفاده قرار ندهید . 

 

راه حل سوم  : ssl  و cdn 

ماشین ها معمولا یک کلید زاپاس دارند .  این کلید فقط  برای روشن کردن ماشین  کار می کند . 

بنابراین نمی توان از آن برای باز کردن قفل کنسول، صندوق عقب یا حتی درها استفاده کرد . ممکن است شما بخواهید اشیای با ارزش خود را در این مکان ها قرار دهید !

شما  می توانید این کلید را به کسی که ماشین را پارک می‌کند ، بدهید .

یکی از دلایلی که کلید زاپاس نمی تواند درب صندوق عقب را باز کند این است که این کلید را می توان کپی کرد!

از چنین کپی می توان برای سرقت ماشین در تاریخ های بعدی استفاده کرد. 

این موضوع نشان می دهد که چطور اعطای یک امتیاز غیرضروری می‌تواند شما را  به خطر بیاندازد !!

به حداقل رساندن ریسک یک اصل  کلیدی در توسعه برنامه هاست .

لزومی ندارد که بتوانید به همه راه هایی فکر کنید که از یک امتیاز خاص می توان سو استفاده کرد.

در واقع، عملاً غیرممکن است که بتوانید اقدامات هر مهاجم بالقوه ای را پیش بینی کنید.

آنچه مهم است این است که شما کمترین امتیاز را اعطا کنید!!

این امر خطر را به حداقل می رساند و امنیت را افزایش می دهد.

 

از کاربر بخواهید قبل از انجام برخی اقدامات مهم احراز هویت مجدد کند.

حتی اگر هیچ نقص شناخته شده ای در منطق احراز هویت شما وجود نداشته باشد.

 

اگر یک کاربر احراز هویت نشده به نحوی  بخواهد با جعل هویت کاربر دیگری  عملیاتی انجام دهد، درخواست رمز عبور مجدد ، می تواند از انجام این عمل توسط کاربر غیرمجاز جلوگیری کند.

این یک دردسر جزئی برای کاربران قانونی است ، اما یک مانع اساسی برای یک مهاجم است.

 

قرار گرفتن در معرض داده ها همیشه یک خطر امنیتی نیست.

با این حال، قرار گرفتن در معرض داده های حساس باید تا حد امکان به حداقل برسد.

 

به طور مثال برای لینک ها باید از ssl استفاده کنید .

همچنین اگر کاربر اطلاعات خود را برای پرداخت وارد می کند ، باید از ssl برای حفاظت از اطلاعات مشتری در هنگام انتقال اطلاعات به درگاه بانکی استفاده کرد .

قبل از اینکه کاربر به درگاه بانکی منتقل شود امنیت اطلاعات او با شماست ! 

 

 

 

Ssl یک گواهینامه امنیتی است که آدرس لینک ها  را از http به https تبدیل می کند .

برای فعال کردن این گواهی نامه و تبدیل لینکها به https چند راه وجود دارد .

اکثر شرکت های ارائه دهنده هاست و دامین این سرویس را به صورت رایگان ارائه می دهند و برای فعال کردن آن تنها کافی است که به آن ها درخواست دهید  .

توجه داشته باشید گوگل لینک های بدون ssl را ناامن می شناسد لذا از ورود کاربران به این لینک ها جلوگیری می کند .

 

بحث ssl در اپلیکیشن ها داغ تر است !! چون در صورتی که اپلیکیشن شما آنلاین باشد و لینک ها بدون ssl استفاده شده باشند گوگلی پلی اجازه استفاده از ان ها را به کاربر نمی دهد و اپلیکیشن شما را ناامن معرفی می کند .

چطور احتمال دارد کاربران حاضر به نصب این اپلیکیشن شوند ؟!

 

راه حل این است که حتما این گواهینامه را فعال کنید .

اما مشکل زمانی اتفاق می افتد که شما این گواهینامه را به صورت رایگان فعال کرده اید اما همچنان ارور برطرف نشده است !

 

شما به عنوان برنامه نویس باید بدانید گواهی نامه امنیتی ssl تیپ های مختلفی دارد که معمولا شرکت های سرویس دهنده هاست و دامین تنها یک نوع آن را ارئه و به صورت رایگان فعال می کنند!!

 

  1. در این صورت شما دو مسیر دارید ، مسیر اول آن است که هزینه کنید و این گواهی نامه را بخرید !
  2. و مسیر دوم آن است که از cdn استفاده کنید .

سرویس cdn یک دروازه امنیتی است که بین درخواست های ارسال شده و سرور یا هاست شما قرار می گیرد ، ( دقیقا مانند فایر وال یا آنتی ویروس برای سیستم )  تا تشخیص دهد که آیا واقعا این درخواست از طرف یک کاربر و به صورت امن ارسال شده است یا یک هکر یا ربات مخرب این درخواست را برای مقاصد خرابکاری ارسال می کند ؟

 

بسیاری از حملات توسط این سرویس ها قابل دفع است .

برای فعال سازی  این سرویس ها می توانید با پرداخت هزینه از شرکت ایرانی ابرآروان یا بدون پرداخت هزینه از سرویس خارجی cloudflar استفاده کنید . 

 

تنها کافی است در این سایت ثبت نام کنید ، دامنه سایت خود را ثبت کنید و سپس nameserver های دامنه خود را با نیم سرورهای اعلامی از سوی این سرویس دهنده ها جایگزین کنید . تا خدمات ssl تیپ یک و دو بر سر مسیردرخواستها قرار بگیرند . 

آموزش نحوه فعال سازی cloudflare 

nameserver همان شناسه ای است که هاست و دامنه را به هم متصل می کند .

دامنه نام اینترنتی یا آدرس پستی فضای اجاره شده توسط شما در محیط اینترنت و هاست فضای فیزیکی شما در محیط اینترنت است !

 

 

 

 

راه حل چهارم : روش ارسال و دریافت اطلاعات

Php  به ما کمک می کند منشا اکثر داده ها را شناسایی کنیم.

متغیرهای عمومی مانند POST  ، $_GET_$ و  COOKIE_$ به وضوح می توانند ورودی ها را شناسایی کنند .

یک قانون واحد می تواند به شما برای نوشتن کدهای ایمن تر کمک کند .

 

شناسایی داده هایی که از سمت کاربر ارسال می شوند اغلب ساده است . که PHP این داده ها را در آرایه های سراسری POST و GET نگه داری می کند .

تشخیص بقیه ورودی ها می تواند کمی سخت تر باشد .

به طور مثال SERVER_$ طیف وسیعی از اطلاعات را در بر می گیرد و می تواند دریافت کند .

پس بهترین روش آن است که دقیقا مشخص کنیم چه نوع داده ای از طرف چه کسی و به چه صورت قرار است ارسال یا دریافت شود .

 

روش‌های مختلفی برای فیلتر کردن داده‌ها استفاده می‌شود که برخی از آنها امن‌تر از بقیه هستند.

بهترین رویکرد این است که فیلترینگ را به عنوان یک فرآیند بازرسی تلقی کنیم.

 

اولین نکته در فیلتر کردن این داده ها و تشخیص صحت آن ها آن است که داده‌های نامعتبر را برای سازگاری با قوانین شما ریال تصحیح نکنید !

کاربران خود را مجبور کنید طبق قوانین شما بازی کنند!

 

 تاریخ نشان داده است که تلاش برای تصحیح داده های نامعتبر اغلب ، آسیب پذیری ایجاد می کند.

 مثال زیر را در نظر بگیرید . کارکترهای مقدار ورودی با مقادیر صحیح جایگزین می شوند که اشتباه است . کاربر را وادار کنید مقادیر صحیح را خودش وارد کند ! 

 

<?php

$filename = str_replace(‘..’, ‘.’, $_POST[‘filename’]);

?>

 

 

تابع ()basename برای دریافت فایل از فرم ورودی می تواند به طور کلی جایگزین این متد شود.

اما در کل هر تلاشی برای تصحیح داده های ورودی نامعتبر می تواند یک خطرباشد ! و اجازه ورود داده های نامعتبر را بدهد .

بهتر است به جای تصحیح اطلاعات ورودی با نمایش یک پیام به کاربر از او بخواهیم خودش طبق قوانین اعلام شده عمل کند و داده ها را ارسال کند .

 

 یک فرم ساده را در نظر بگیرید که به کاربر اجازه می دهد از بین سه رنگ انتخاب کند :

<form action=”process.php” method=”POST”>  

  Please select a color: 

   <select name=”color”> 

     <option value=”red”>red</option> 

     <option value=”green”>green</option>     

     <option value=”blue”>blue</option>   

</select>  

  <input type=”submit” />  

  </form>

 

در منطق برنامه نویسی که این فرم را پردازش می کند، به راحتی می توان این اشتباه را مرتکب شد که فرض کنیم فقط یکی از سه گزینه قابل ارائه است!

 

هکر می تواند هر داده ای را به عنوان مقدار POST[‘color’] ارسال کند !

 

بهتر است برای فیلتر کردن این مورد از تابع switch  استفاده کنیم . به این صورت تنها اگر داده ورودی برابر با یکی از سه مقدار تعریف شده با فرمت ما و دقیقا حروف نوشتاری ما باشند پذیرفته می شوند !

و در غیر این صورت مقدار ورودی پذیرفته نمی شود و از حلقه خارج می شویم .

به همین راحتی با تغییرتنها یک تابع می توان امنیت بیشتری برای برنامه به ارمغان آورد !

<?php   

$clean = array();   

switch($_POST[‘color’])    { 

     case ‘red’: 

     case ‘green’: 

     case ‘blue’: 

       $clean[‘color’] = $_POST[‘color’]; 

       break;   

}  

  ?>

 

البته برای هر نوع داده ای یک روش برای اعتبار سنجی یا فیلتر کردن اطلاعات دریافتی وجود دارد .

با اطمینان از اینکه تمام داده‌ها به درستی در ورودی فیلتر شده‌اند، می‌توانید خطر اینکه داده‌های آلوده (فیلتر نشده) به اشتباه مورد اعتماد یا سوء استفاده در برنامه شما قرار گیرند را از بین ببرید.

 

نکته دوم : به عنوان مثال، ممکن است بخواهید که نام کاربری فقط شامل کاراکترهای الفبایی باشد.

در نتیجه باید حتما داده های ورودی را در بک اند موردبررسی قرار دهیم . آیا کاراکترهای ورودی به عنوان نام با قوانین شما ارسال شده اند ؟

آیا تنها شامل حروف هستند ؟ یا اعداد یا کارکتر های خاص که برای php  معنی خاصی دارند در بین آن ها وجود دارد ؟ 

آدرس ایمیل به درستی و با کراکترهای صحیح وارد شده ؟ برای هر کدام از این ورودی ها قوانین مشخصی برای اعتبار سنجی تعریف شده است .

قبل از اینکه از آن ها استفاده کنید و آن ها را در دیتابیس وارد کنیدحتما باید آن ها را اعتبار سنجی کنید .

در غیر اینصورت ممکن است داده هایی مخرب را با دستان خودتان به دیتابیس وارد کرده باشید !

تابع ()htmlentities یک رشته را می گیرد و نسخه اصلاح شده آن را بر می گرداند .

 

<?php   

  $html = array();   

  $html[‘username’] = htmlentities($clean[‘username’],   ENT_QUOTES, ‘UTF-8’);   

  echo “<p>Welcome back, {$html[‘username’]}.</p>”;  

?>

 

تابع   ()htmlspedialchar  نیز همان استدلال را دارد اما جامعیت کمتری دارد .

این توابع چک می کنند که آیا ورودی دقیقا با نوع درخواستی مطابقت دارد یا خیر ؟

 

نکته سوم : اگر نمی خواهید یک داده را تغییر دهید در معرفی آن ، به جای استفاده از متغیر از ثابت ها استفاده کنید .

ثابت (const) در طول برنامه تغییری نمی کند . اما متغیرها می توانند دچار تغییر شوند یا در محاسبات استفاده شوند .

 

اگرچه یک کاربر می تواند داده ها را به روش های مختلف ارسال کند، اکثر برنامه ها مهمترین اقدامات را در نتیجه ارسال فرم انجام می دهند.

علاوه بر این، از آنجایی که یک مهاجم تنها با دستکاری داده‌های پیش‌بینی‌شده (داده‌هایی که برنامه شما کاری با آن‌ها انجام می‌دهد) می‌تواند آسیب وارد کند، فرم‌ها یک روزنه راحت ارائه می‌کنند .

 به همین دلیل است که پردازش فرم یکی از دغدغه های اصلی امنیت برنامه های وب است.

یک کاربر می تواند داده ها را به سه روش غالب به برنامه شما ارسال کند:

  • در url ( مانند ارسال داده به روش $_GET )
  • در محتوای یک درخواست ( مانند ارسال داده به روش $_POST )
  • در header ( مانند کوکی ها یا SESSION یا $_SERVER)

البته با استفاده از تابع server[request_method]$ می توانیم تشخیص دهیم آیا داده ها با متد درخواستی ما به فرم ارسال شده اند یاخیر ؟ 

در تک فرم می توان روش دریافت و ارسال ( GET یا  POST ) را مشخص کرد. پس در هنگام دریافت یک داده اول از همه بررسی کنید که اگر شما روش ارسالی را به متد post محدود کرده اید این داده ها به روش get ، put یا هر روش دیگری ارسال نشده باشند . 

حتما در هنگام اعتبار سنجی اطلاعات و قبل از انجام محاسبات یا ثبت آن ها در دیتابیس یا استفاده از آن ها در کوئری ها بررسی کنیم که آیا اطلاعات به روش درخواستی ما ارسال شده اند یا خیر ؟

 

<form action=”http://example.org/register.php” method=”GET”>

 

مثلا اگر فرم ما به شکل ذیل باشد :

<form action=”http://example.org/login.php” method=”GET”>

     <p>نام کاربری: <input type=”text” name=”username” /></p>

     <p>گذرواژه: <input type=”password” name=”password” /></p>

     <p><input type=”submit” />ارسال</p>

</form>

 

زمانی که کاربر اطلاعات را وارد و روی دکمه ارسال کلیک می کند با توجه به اینکه روش ارسال اطلاعات GET بوده است همه اطلاعات در URL به نمایش گذاشته می شوند !!  

 

http://example.org/login.php?username=chris&password=mypass

 

اما همان طور که می دانید برای ورود هیچ نیازی به فرم نیست و تنها با نوشتن اطلاعات در URL در روش ارسال اطلاعات با GET می توان عملیات مربوط به ورود را انجام داد !

در واقع هیچ تفاوتی در نحوه ارسال اطلاعات با روش POST نیست !!

تنها تفاوت آن است که زمانی که method=POST است اطلاعات در url به نمایش گذاشته نمی شود که باعث ایجاد امنیت می شود .

در دریافت و ارسال اطلاعات ار متد post استفاده کنید ( متد فرم را روی POST قرار دهید ) . همچنین داده ها را در POST_$ ذخیره کنید . 

 

مثال زیر را در نظر بگیرید . در مثال زیر قبل از انجام عملیات ، مقدار ورودی با کاراکترهای مجاز برای آن فیلد مقایسه شده است .

از  رمزگذاری اطلاعات استفاده شده است . ( که در ادامه درباره آن ها بیشتر توضیح خواهیم داد )

 

    <?php

    session_start();

    $clean = array();

    $email_pattern = ‘/^[^@\s<&>]+@([-a-z0-9]+\.)+[a-z]{2,}$/i’;

    if (preg_match($email_pattern, $_POST[’email’]))

    {

      $clean[’email’] = $_POST[’email’];

      $user = $_SESSION[‘user’];

      $new_password = md5(uniqid(rand(), TRUE));

      if ($_SESSION[‘verified’])

      {

        /* Update Password */

        mail($clean[’email’], ‘Your New Password’, $new_password);

      }

    }

    ?>

 

راه حل پنجم :  بررسی اطلاعات فایل های ارسالی و محدود کردن نوع فایل و حجم آن ها 

 

 <form action=”upload.php” method=”POST” enctype=”multipart/form-data”>

    <p>Please choose a file to upload:

    <input type=”hidden” name=”MAX_FILE_SIZE” value=”1024″ />

    <input type=”file” name=”attachment” /><br />

    <input type=”submit” value=”Upload Attachment” /></p>

    </form>

 

Php  برای آپلود فایل ابتدا آن را در مکانی موقت ذخیره می کند .

در نتیجه برای انتقال آن به مکان اصلی مشخص شده و دائمی حتما باید بررسی کنیم آیا اصلا فایلی آپلود شده است و محتوایی وجود دارد یا خیر ؟

برای آپلود یک فایل یک قانون مهم آن است که حتما برای جلوگیری از حمله هکرها با دانستن نام فایل های آپلود شده ، در هنگام آپلود هر فایل ، نام موقت آن را به نام مشخصی با فرمت تعریف شده خودتان تغییر دهید .

یک مرحله که ممکن است خیلی ساده به نظر برسد می تواند از شما در برابر خطرات محافظت کند .

برای آنکه تشخیص دهیم آیا فایل مورد نظر آپلود شده است یا تنها برای ارسال یک کوئری بوده می توان از تابع    ()is_uploaded_file استفاده کرد .

 

<?php

$filename = $_FILES[‘attachment’][‘tmp_name’];

if (is_uploaded_file ($filename))

{

/* $_FILES[‘attachment’][‘tmp_name’] یک فایل آپلود شده است. */

}

?>

 

اگر می خواهید فایل را به مکان دائمی منتقل کنید، اما فقط در صورتی که فایل آپلود شده باشد ، می توانید از ()move_uploaded_file استفاده کنید :

 

<?php

    $old_filename = $_FILES[‘attachment’][‘tmp_name’];

    $new_filename = ‘/path/to/attachment.txt’;

 

    if (move_uploaded_file($old_filename, $new_filename))

    {

      /* $old_filename is an uploaded file, and the move was successful. */

    }

 

    ?>

همین یک تابع باعث می شود فایل آپلود شده به محل ذخیره سازی منتقل شود اما فراموش نکنید مطابق مطالب گفته شده در پکیج مقدماتی – تکمیلی اندروید در هنگام آپلود فایل نام آن را به نام یا توکن شخص آپلود کننده تغییر دهید .

و فایل را در پوشه ای جداگانه با همان نام شخص ذخیره کنید تا در ارجاع های بعدی بتوانید به راحتی فایل مورد نظر را با اسم شخص مذکور در هاست خود بیابید و در صورت نیاز آن را حذف کنید .

 

اگر نام فایل آپلود شده را تغییر ندهید هکر ها با صدا زدن نام آن می توانند فایل مذکور را اجرا کنند !

مهمتر از همه چیز آن است که در زمان آپلود فایل حتما بررسی کنید فایل های آپلودی دقیقا با فرمت های مجاز آپلود می شوند .

به طور مثال اگر قرار است کاربر تنها بتواند تصاویر را آپلود کند فرمت های مجاز شامل png , jpg , jpeg هستند و نه بیشتر .

اگر هکر بتواند هر نوع فایلی حتی .php راآپلود کند چقدر راحت میتواند کدهای مخرب خودرا به هاست شما انتقال دهد ؟!!

لذا ابتدا باید بررسی کنیم آیا فایل مورد نظر فرمت درستی دارد یا خیر ؟

 

در مرحله بعد باید حجم فایل مذکور را بسنجیم .

برای فایل های با فرمت های معقول قطعا بیش از یک مگابایت حجم پذیرفته و مورد نیاز نیست !!

لذا بررسی نکردن همین نکات کوچک در این مرحله باعث می شود فاجعه های بزرگی رخ دهد!!

 

برای آنکه بتوانید برای هر عملی در کدهای خود نیز ، محدودیت زمانی ایجاد کنید می توانید با تعیین زمان این عمل را انجام دهید :

<?php

$token_age = time() – $_SESSION[‘token_time’];

if ($token_age <= 300)

{

/* کمتر از پنج دقیقه گذشته است. */

}

?>

 

جالب است بدانید وقتی هکرها می توانند در صفحات html سورس صفحه را ببینند ، پس می توانند آن را کپی کرده و در جای دیگری ذخیره کنند ، مقادیر را تغییر دهند و مقدار دلخواه خود را با تغییر در ورودی های فرم بارگذاری کنند .

 

پس بسیار مهم است در پس کدهای فرم های خود ، برای دریافت اطلاعات از کاربران انواع احراز ها را بر روی داده ها انجام دهید.

تا مطمئن شوید دقیقا یک کاربر عادی بدون سو نیت آن ها را وراد کرده است .

فیلترینگ داده های یک فرم را می توان از طریق محدود کردن روش ارسال داده ها به فرم و بررسی آنکه آیا واقعا فرم با فرمت درخواستی شما ارسال شده است ، شروع کنید .

 

سپس تک به تک داده ها را احراز کنید . به طور مثال از نظر تعداد کاراکترها ، نوع آن ها و بسیاری موراد دیگر که باید براساس آن ها پس از ارسال فرم در BACKEND داده های ورودی را فیلتر کرد .

تا زمانی که ورودی ها را به درستی فیلتر کنید، کاربران باید قوانین شما را رعایت کنند!!

 

یکی ازروش های محدود کردن اطلاعات ورودی استفاده از header  هاست .

به طور مثال هکرها می توانند اطلاعات url را دستکاری کنند برای جلوگیری از این موضوع می توانید از htmlspecialchars در هدر یا گرفتن اطلاعات استفاده کنید . 

در آموزش های نوین دولوپرز درباره انواع هدرها در api نویسی صحبت کرده ایم .

 

URL: http://example.com/search.php?search=<script>alert(‘test’)</script>

 

$search = $_GET[‘search’] ?? null;

 

echo ‘Search results for ‘.$search;

 

راه حل برای فرار از single  و double quotes در ارسال داده توسط هکر :

 

$search = htmlspecialchars($search, ENT_QUOTES, ‘UTF-8’);

 

echo ‘Search results for ‘.$search;

 

راه حل ششم ، رمز گذاری :

به خاطر داشته باشید که حتما رمز ها را با تابع های رمز گذاری ایمن کنید .

اما بهتر است بدانید تنها یک تابع کفایت نمی کند !

تحقیقات نشان داده استفاده از تنها یک تابع به طور مثال  MD5 برای رمز گذرای کفایت نمی کند .

سعی کنید علاوه بر آنکه حداقل از دو الگوریتم برای رمزگذاری یک رمز عبور استفاده می کند آن را با رشته های یکتا ( مانند تابع زمان ) یا تصادفی جمع کنید تا غیر قابل حدس زدن بشوند .

 

سعی کنید نام کاربری کاربر که با آن به همه اطلاعات خود دسترسی دارد را در سشن ذخیره نکنید و برای دریافت یا ارسال اطلاعات از/به دیتابیس ، از اطلاعات حساس کاربر مانند نام کاربری ، ایمیل یا شماره موبایل استفاده نکنید .

یک توکن برای کاربر بسازید و از توکن کاربر برای این منظور استفاده کنید .

همیشه سشن ها را در مدت زمان خاصی اکسپایر کنید تا به صورت خودکار از بین بروند. 

کد ناامن :

<?php

    session_start();

    if (isset($_SESSION[‘username’]))

    {

      #do something

    }

    ?>

 

ضمن آنکه می توان دسترسی ها را به فایل ها محدود کرد که احتمال در دسترس قرار گرفن سورس را کمتر می کند .

 

<Files ~ “\.inc$”>

        Order allow,deny

        Deny from all

</Files>

 

راه حل هفتم : دیتابیس

محبوب ترین زبان سمت سرور جهان با 79 درصد از وب سایت ها با تحقیقات w3techs زبان php  بوده است .

در میان این سایت ها فیسبوک ، یاهو و ویکی پدیا نیز قرار دارند.

 

از آنجایی که  قالبا سایت ها نیاز دارند داده های خود را به اشتراک بگذارند امنیت php  نیز اهمیت زیادی پیدا می کند .

همین به اشتراک گذاری منابع و داده ها باعث آسیب پذیری ما می شود .

بیشترین علت آسیب پذیری به خاطر عادات بد کدنویسی و عدم آگاهی از امنیت برنامه هاست .

هنگام نوشتن کد، باید دو روش کلیدی را اعمال کنید: اعتبار سنجی و پاکسازی .  (validation and sanitization  )

اگر هر دوی این رویه‌ها را برای داده‌های کاربر پیاده‌سازی کنید، مطمئن می‌شوید که آنچه پردازش و اجرا می‌شود معتبر است .

همچنین داده های خروجی معیارهای مشخصی را رعایت میکنند تا کد مخربی اجرا نشود .

 

اگر رویه های ساده و ابتدایی خاصی را برای هر صفحه وب دنبال کنید، احتمال قرار گرفتن در معرض یک مسئله امنیتی حیاتی را به میزان قابل توجهی به حداقل می رسانید.

 

اگر ورودی های کاربر را بدون اعتبار سنجی و یا تغییرات احتمالی در دیتابیس به صورت مستقیم وارد کنید هکر می تواند مستقیما اطلاعات را با دانش نسبت به ورودی های خود ، دستکاری کند !

 

نمونه کد ناامن :

در مثال زیر پارامتر article  به روشی ناامن استفاده شده است :

$articleid = $_GET[‘article’];

$query = “SELECT * FROM articles WHERE articleid = ‘$articleid'”;

 

می دانید که متغیر را مستقیما نباید درون کوئری قرار داد . از روش های  bind می توان برای این منظور استفاده کرد .

همچنین بهتر است از روش POST_$ برای دریافت و ارسال اطلاعات استفاده کنیم و قبل از بارگذاری مقادیر در دیتابیس حتما آن ها را اعتبار سنجی کنیم .

به این شکل از آلوده شدن دیتابیس می توان جلوگیری کرد . 

 

اگر مقدار ورودی کاربر را به طور مستقیم در کوئری قرار دهید هکرها می توانند به جای مقدار ورودی یک رشته مخرب قرار دهند مثال :

 

1’+union+select+1,version(),3′

به جای article 

 

از این کد می توان برای شمارش تعداد جداول و ستون ها و سپس حدس زدن نام فیلدها استفاده کرد .

به همین دلیل است که برای جدا سازی کوئری و پارامترهای ارسالی کاربران توصیه می شود حتما از روش PDO استفاده کنند .

 

مثال امن :

 

// User ID must not be empty, must be numeric and must be less than 5 characters long

 

if((!empty($_GET[‘user_id’])) && (is_numeric($_GET[‘user_id’])) && (mb_strlen($_GET[‘user_id’])<5)) {  

$servername = “localhost”; 

$username = “username”; 

$password = “password”; 

$database = “dbname”;

 

   // Establish a new connection to the SQL server using PDO

 

  try {

    $conn = new PDO(“mysql:host=$servername;dbname=$database”, $username, $password);     

 

// Assign user input to the $user_id variable    

 

 $user_id = $_POST[‘user_id’];   

 

 // Prepare the query and set a placeholder for user_id    

 

 $sth = $conn->prepare(‘SELECT user_name, user_surname FROM users WHERE user_id=:user_id ‘);   

 

  // Execute the query 

  $sth->bindParam(‘:user_id ‘, $user_id, PDO::PARAM_INT);

   $sth->execute();  

 

  // Fetch all matching rows 

   $user = $sth->fetch();  

 

   // If there is a matching user, display their info 

   if(!empty($user)) { 

     echo “Welcome “.$user[‘user_name’].” “.$user[‘user_surname’];    

 }

else {   

   echo “No user found”;  

   }    

 

// Close the connection   

$dbh = null;  

 }

catch(PDOException $e) { 

   echo “Connection failed.”;   }

} else

echo “User ID not specified or invalid.”;

}

 

 

نکات تکمیلی :

Cms هایی همچون وردپرس ، مگنتو ، دروپال و جوملا نیز با زبان php  توسعه داده شده اند .

هر بار که php  به روز رسانی می شود قطعا متدهای جدیدی نیز به آن اضافه می شود .

به عنوان یک برنامه نویس خوب ، ما همیشه باید از متدهای جدید آگاه باشیم و سعی کنیم کد های خود را به جدید ترین نسخه ها به روز کنیم .

فیلتر ایمل : 

 

if(filter_var($address, FILTER_VALIDATE_EMAIL))

{

      echo “Email is valid.”;

} else {

      echo “Not valid.”;

}

 

کوئری زیر را در نظر بگیرید . یکی از ترسناک ترین زمینه ها برای برنامه نویسان همیشه بخش ورود به درگاه بانکی بوده است  .

 

GET http://bank.com/transfer.do?acct=TIM&amount=100 HTTP/1.1

 

اگر شخصی بخواهد با دستکاری این کوئری مبلغی را به حساب خود واریز کند به راحتی این امکان وجود دارد.

 

http://bank.com/transfer.do?acct=Sandy&amount=100000

 

  1. راه حل آن است که به راحتی اطلاعات را با روش get در کوئری در اختیار افراد قرار ندهیم .
  2. از کد و api های ارائه شده توسط بانک ها تبعیت کنیم .
  3. بر روی هر لینکی یا عکسی که برای ما ارسال شده است بدون دانستن مضمون آن و بدون اطلاع کلیک نکنیم .

این لینک می تواند به راحتی با یک عکس و با ایمیل به دیگران ارسال شود.

 

برای کوکی ها، بهترین روش این است که هرگز از داده های سریالی ذخیره شده در یک کوکی استفاده نکنید.

هکرها می توانند کوکی ها را به راحتی دستکاری کنند و در نتیجه متغیرهایی را به محدوده شما اضافه کنند.

با خیال راحت کوکی ها را مانند زیر حذف کنید:

setcookie ($name, “”, 1);

 

setcookie ($name, false);

 

unset($_COOKIE[$name]);

 

خط اول کد تضمین می کند که کوکی در مرورگر منقضی می شود.

خط دوم روش استاندارد حذف یک کوکی  را نشان می دهد و خط سوم کوکی را از اسکریپت شما حذف می کند .

 

اگر از  فریمورک های php  استفاده می کنید باید بدانید که این فریمورک ها یا معماری ها ساختار خاصی برای ساختن صفحات مختلف دارند.

با قرار دادن هر فایل در دایرکتوری به خصوص ، همه افراد به راحتی به فایل های شما دسترسی ندارند .

چون این فایل ها در پوشه های مجزا و با نام های خاص به صورت جداگانه ذخیره شده اند و دسترسی به آن ها محدود شده است .

در واقع ما نباید فایل های اصلی و حساس خود را در پوشه اصلی و اول سرور خود قرار دهیم .

 

 

آیا این مطلب را می پسندید؟
اشتراک گذاری:
زهرا فریدونی

نظرات

0 نظر در مورد امنیت در php

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد.

هیچ دیدگاهی نوشته نشده است.