تعداد بازدید: 3393

نکات امنیتی وردپرس

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

Your code works, but is it safe ?

نکات امنیتی که در این مقاله بررسی خواهیم کرد به شرح زیر است :

  • Checking User Capabilities
  • Data Validation
  • Securing Input
  • Securing output
  • Nonce

بررسی سطح دسترسی کاربران (Checking User Capabilities)

اگر قرار باشد کاربر Action خاصی را روی وب سایت پیاده سازی کند ( چه در پنل ادمین یا فرانت اند ) قبل از هر چیز باید چک کنیم این کاربر مجوز این کار را دارد یا خیر. به این عمل authorization می گوییم.

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

User →  AccessGroup → ModulesList
User →  Roles → Capabilities

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

برای این کار باید ابتدا بفهمید که این عملی که قراره انجام بشه در کدوم دسته از Capabilities های وردپرس قرار داره. بعد با تابع current_user_can چک می کنید که این عمل (capabilities) برای کاربر جاری مجازه یا خیر. به طور مثال برای اعمال تغییر روی جدول option یا همون تنظیمات سطح دسترسی manage_options رو چک می کنیم:

<?php
if(!current_user_can("manage_options")){
    return;
}

نکته : لیست سطوح دسترسی وردپرس رو می تونید از این لینک پیدا کنید.

نکته : در زمان ساخت پست تایپ پارامتری به نام capabilities داشتیم که اگر اون پارامتر رو خالی بزاریم سطوح دسترسی پست به اون تعلق می گیره . حال اگر سطح دسترسی جدیدی برای اون action خاص مثلا ویرایش پست (edit_post) تعیین می کردیم در اینجا باید اون مقدار رو برای چک کردن به تابع current_user_can می دادیم.

نکته : این تابع رو به صورت شرطی قبل از اعمال add_action ها یا داخل تابعی که داره به یه hook خاص قلاب میشه بزارید.

معتبر بودن ورودی ها (Data Validation)

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

نمونه هایی از اعتبار سنجی داده ها :

  • چک کردن این موضوع که ورودی کاربر خالی نباشد.
  • چک کردن شماره تلفن ورودی که تنها شامل اعداد باشد.
  • چک کردن کد پستی وارد شده از سمت کاربر (با توجه به قوانینی که کدهای پستی ایجاد می شوند).
  • چک کردن تعداد که از عدد صفر باید بیشتر باشد (مثلا تعداد محصول سفارش داده شده).

نکته : اعتبار سنجی داده ها قبل از هر عملی.

نکته : اعتبار سنجی داده می تواند قبل توسط جاوا اسکریپت یا پی اچ پی در فرانت اند یا بک اند وب سایت اتفاق بیفتد.

اعتبار سنجی توسط توابع پیش فرض php:

  • is_set و empty برای این که بفهمیم ورودی هست یا خیر.
  • strlen برای فهمیدن تعداد کاراکترهای رشته – نوع mb_strlen برای کاراکتر های فارسی به کار میره. در رابطه با خالی بودن یا نبودن یک آرایه می تونید از تابع count استفاده کنید و تعداد اعضای اون رو در بیارید.
  • strpos برای این که بفهمیم کاراکتری خاص در رشته ما هست یا خیر (این تابع position کاراکتری که بهش دادیم رو به ما میده و اگر وجود نداشت صفر بر میگردونه)
  • in_array مثلا میتونید لیستی از موارد معتبر در یک آرایه داشته باشید بعد نگاه کنید که آیا این مورد در اون آرایه هست یا خیر.
  • با استفاده از تابع preg_match قالب یا pattern رو تعریف کنید تا معتبر یا غیر معتبر بودن ورودی رو تعیین کنه.

اعتبار سنجی توسط توابع وردپرس

وردپرس هم با استفاده از توابع پیش فرض php و عبارات منظم (Regular Expression) توابعی رو در رابطه با اعتبار سنجی داده ها ساخته است:

  •  is_email که مشخص می کند آیا ایمیل معتبر است یا خیر.
  • username_exists نام کاربری وجود داره یا خیر
  • validate_file برای اعتبار سنجی این که فایل وجود داره یا خیر (file_exisists)

نکته : توابع زیادی در رابطه با اعتبار سنجی داده ها در وردپرس وجود داره برای پیدا کردن اون ها کافیه به reference توابع و کلاس های وردپرس برید و عباراتی نظیر *_exists , *_validate , is_* را جستجو کنید.

نکته : از Attribute های html هم می تونید برای فیلتر ورودی کابران استفاده کنید (مثلا maxlength).

ایمن سازی ورودی ها (Securing Input)

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

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

توابع پاکسازی داده ها به دو دسته تقسیم می شوند . پاکسازی ورودی ها (sanitizing is cleaning user input) و پاکسازی خروجی (escaping is securing output) . توابع پاکسازی ورودی با sanitize_* شروع می شوند و توابع پاکسازی خروجی با esc_* .

برخی مقادیر پاکسازی ورودی نیاز دارند . مثلا ایمیل اگر کاراکتر غیر مجاز داشت باید حذف بشه ولی اگر قرار باشه ایمیل چاپ بشه خروجیش از نظر رشته ای باید پاکسازی بشه.

تعدادی از توابع پاکسازی ورودی :

sanitize_email : این تابع خروجی ایمیل را اگر معتبر باشد پاکسازی و برمی گرداند و اگر غیر معتبر باشد خالی برمی گرداند.
<?php sanitize_email("fsaffsa@fsd.as<br>d") //fsaffsa@fsd.asbrd ?>

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

sanitize_file_name : این نام فایل رو معتبر می کنه . اگر دقت داشته باشید یه سری کاراکتر ها در نام فایل ها غیر مجاز است. مثلا فاصله.
<?php sanitize_file_name("forbidden char.php"); //forbidden-char.php ?>

فاصله رو تبدیل به – کرد.

sanitize_html_class : کاراکتر های غیر مجاز رو برای کلاس از رشته حذف می کنه . (مثلا برای کلاس ها تنها کاراکتر های a-z , A-Z , 0-1 مجاز هستند اگر فارسی هم بنویسید حذف می کنه).

<?php echo sanitize_html_class("col-md 6 + *&^ dsf@#$%^&*()"); //col-md6dsf ?>

sanitize_text_field : رشته های متنی رو پاکسازی می کنه. (چون فیلدهای متنی استفاده زیادی دارند تابع پر کاربرید به شمار میره)

<?php echo sanitize_text_field("1f<form>fad</form>dfs?a"); //1ffaddfs?a  ?>

تگ های html حذف شدند. به این ترتیب اگر ورودی کد جاوا اسکریپت وارد کنند خنثی می شود چون در هیچ تگی نیست توسط مرورگر کد رشته شناخته می شود.

sanitize_option : این تابع در ابتدا چک می کند کلیدی ($option) که برای option_name انتخاب کردید جزو کلید های پیش فرض وردپرس است یا خیر . در صورت بله باید برای کلید مورد نظر مقدار درستی داشته باشد . به طور مثال برای option_name = 'new_admin_email' حتما باید ایمیل معتبر وارد کنید. (برای مقادیر غیر مجاز در کلید های پیش فرض وردپرس مقدار 0 به عنوان false بر میگرداند).
<?php
 echo sanitize_option( 'thumbnail_size_w', 'fsdfas' ); //0
 echo sanitize_option('new_admin_email' , 'info@asabagh.ir!'); //ifno@asabagh.ir 
?>

مورد اول باید عدد وارد می کرد نکرد صفر برگردوند و مورد دوم رو هم اصلاح کرد(علامت ! در ایمیل نباید باشد)

sanitize_key : کلیدها در جداول postmeta , commentmeta , option استفاده میشن که شامل یه سری کاراکتر های مجازه . اگر کاربر قراره کلید رو هم خودش تعیین کنه از این تابع استفاده کنید.

نکته : توابعی که در بالا برای شما توضیح دادیم یک مقدار ورودی میگیره و یک مقدار fallback که اگر پس از پاکسازی رشته خالی ماند از اون مقدار fallback استفاده بشه.

ایمن سازی خروجی ها (Securing output)

گاهی ما از ورودی های کاربران به عنوان خروجی استفاده می کنیم . (به طور مثال در دیدگاه ها) در این زمان برنامه ما در معرض خطر حملات XSS  قرار خواهد گرفت. پس باید ورودی هایی که قرار چاپ بشه رو ایمن کنیم که هکر ها نتونن از طریق وب سایت ما به کاربران تزریق کد داشته باشند.

پس پاکسازی داده ها برای چاپ برای محافظت از کاربران وب سایت می باشد  پاکسازی خروجی برای جلوگیری از حملات XSS.

تعدادی از توابع وردپرس برای پاکسازی خروجی :

esc_html : در این تابع هر چی که بنویسید در خروجی چاپ میشه ، این کار به وسیله تبدیل کردن کدها به مقدار encode شده اون ها اتقاق می افته به طور مثال < تبدیل به &gt چه می خواد تگ باشه یا کد های استایل.(پس هر وقت خواستید خروجی تون خام باشه و هیچ گونه تگی نداشته باشه از این تابع استفاده کنید.)

<?php echo esc_html( '<a href="http://www.example.com/">A link</a>' );  ?>

خروجی کد بالا به شکل زیر خواهد بود.

<a href=”http://www.example.com/”>A link</a>

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

<?php echo esc_url("https://website.&com<script>alert('this page hacked');</script>"); ?>

خروجی کد بالا به شکل زیر خواهد بود:

https://website.&comscriptalert(‘this%20page%20hacked’);/script

نکته : زمانی که دارید src و href رو به صورت داینامیک از ورودی های کاربر وارد می کنید از این تابع استفاده کنید.

esc_attr : این تابع برای پاکسازی خروجی ها در زمان وارد کردن ویژگی به تگ ها است (Attributes includes : class , name , value , data)

<?php $fname = ( isset( $_POST['fname'] ) ) ? $_POST['fname'] : ''; ?>
<input type="text" name="fname" value="<?php echo esc_attr( $fname ); ?>">

این تابع مختص Attribute هاست و علاوه بر جلوگیری از حملات XSS کارکتر های غیر مجاز برای Attribute را هم پاکسازی می کند.

esc_sql : زمانی که قراره از کاربر داده ای بگیری و اون داده رو در یک SQL Query قرار بدی و نتیجه رو بگیری این تابع خیلی به کار میاد. کمک می کنه که کاربر لای داده خودش کد sql تزریق نکنه :

<?php
$name   = esc_sql( $name );
$status = esc_sql( $status );
$wpdb->get_var( "SELECT something FROM table WHERE foo = '$name' and status = '$status'" );
?>

نکته : اگر از $wpdb->prepare() استفاده می کنید نیازی به استفاده از تابع esc_sql ندارید.

پاکسازی به همراه ترجمه :

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

  • esc_html__()
  • esc_html_e()
  • esc_attr__()
  • esc_attr_e()
  • esc_attr_x()

نحوه کار با اونها دقیقا مثل کار با توابع معمولی ترجمه است (در پشت کار پاسکازی هم انجام میشه)

Nonce

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

انتخاب رشته به عنوان nonce ⇐ رمز شدن این رشته ⇐ ارسال به سرور ⇐ رمزشکنی رشته ارسالی در سرور و چک کردن با مقدار اولیه

بدین ترتیب فردی که درخواست رو میده باید در فرم حضور داشته باشه . (منظورم مکان درخواسته)

در حالت کلی ما در دوجا از nonce ها استفاده می کنیم:

  • در زمانی که درخواستی قراره از طریق لینک و با پارامتر GET ارسال بشه(wp_create_nonce , wp_verify_nonce)
  • زمانی که قراره از طریق فرم با پارامتر POST یا GET درخواستی ارسال بشه. (wp_nonce_field , wp_verify_nonce)

دو تابع داریم یکی برای تولید nonce (گرفتن رشته و رمز کردن اون ) و دیگری برای تایید nonce (رمز شکنی رشته و مقایسه با مقدار اولیه)

تولید nonce با تابع wp_create_nonce

<?php wp_create_nonce( $action ); ?>

یک پارامتر می گیره ($action) و همون رشته ای هست که به عنوان کلید بهش میدید (هر چی تو حالتونه بدید ولی قابل تشخیص نباشه از مقادیر قابل حدس استفاده نکنید)

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

تولید nonce با تابع wp_nonce_field

<?php wp_nonce_field( $action, $name ) ?>

همون طور که از نام این تابع پیداست خروجی اون یک فیلد مخفی (input type hidden) است که حاوی نام ( name ) پارامتر $name و مقدار( value ) رمز شده پارامتر $action است.

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

<input type="hidden" name="<?php echo $name ?>" value="<?php echo wp_create_nonce($action);?>">

اعتبار سنجی nonce به وسیله تابع wp_verify_noce

<?php wp_verify_nonce( $nonce, $action ); ?>

پارامتر اول ( $nonce ) همون مقداریه که از طریق GET  یا POST اومده (nonce رمز نگاری شده) و پارامتر دوم ( $action ) همون رشته ایه که در تابع قبل در فرم جای دادید.

نکته : خروجی این تابع یک مقدار 0 یا 1 است که معتبر بودن یا نبودن nonce را تشخیص می دهد.

نکته : استفاده از nonce در در اعمال درخواست ها (چه از طریق لینک با تابع wp_create_nonce و یا چه از طریق   با تابع wp_nonce_field  باعث جلوگیری از حملات CSRF می شود)

 

مطالب مشابه

ftp-protocol-in-php

کار با پروتکل FTP در PHP

یکی دیگر قوانین حاکم بر دنیای وب ( از پروتکل های اینترنت لایه application ) پروتکل ftp است که با استفاده از آن می...

آموزش نکات و تکنیک های برنامه نویسی وردپرس

Rest API در وردپرس

سرور ها می توانند پاسخ مناسب به درخواست ها بدهند. درخواست ها و پاسخ یک سری ویژگی ها و داده همراه خود دارند. کدی که در...

ساخت REST API با PHP

API (Application Program Interface) یعنی یک واسط برای استفاده از امکانات نرم افزار. واسط های گرافیکی نرم افزار رو هم می...

امنیت و رمزنگاری در پی اچ پی

امنیت و رمزنگاری در php

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

اشتراک گذاری :

مدیر وب سایت گنوتک . برنامه نویسی رو با زبان C در هفده سالگی شروع کردم . در حال حاضر به برنامه نویسی php برپایه معماری MVC , HMVC و همچنین سیستم مدیریت محتوای WordPress و فریم ورک محبوب لاراول علاقه مند هستم و دوست دارم اطلاعاتم رو با شما به اشتراک بگذارم.

۰ دیدگاه برای نکات امنیتی وردپرس

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

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *