
در مهندسی امنیت، نانس عبارت است از تعدادی عدد دلخواه که تنها یکبار برای امضای یک ارتباط استفاده میشود.
پاراگراف بالا توضیح خلاصه ویکیپدیا از نانسه. کلمه Nonce در اصل از ترکیب کلمات یک جمله تولید شده که تو رفرنسهای مختلف جملهی که تشکیلدهنده رو چیزای مختلفی میگن:
همونطور که میبینید مفهوم این جملات یکیه و دارن میگن «عددی که فقط یکبار استفاده میشه».
نانس یه توکن یکتاست که برای اضافه کردن یک لایه امنیتی به اپلیکیشن استفاده میشه. کسایی که با مفهوم بلاکچین و ماینینگ آشنا باشن احتمالا نانس به گوششون خورده. امنیت بلاکچین رو نانس تامین میکنه.

عکس بالا یه مثال خوبه که بهتر متوجه بشین. پروسه فعالیت یک نانس اینجوری میشه:
شاید بدونین که وردپرس خودش یه سیستم نانس داره. اما این سیستم وردپرس نانس واقعی نیست و مفهوم Number Used Only Once (عددی که فقط یکبار استفاده میشه) رو محقق نمیکنه. چرا؟ چون مرحله ۴ام از پروسهای که بالاتر نوشتم رو رعایت نمیکنه و میتونه بیشتر از یک بار استفاده بشه.
وردپرس نانسی که میسازه رو حداقل ۱۲ ساعت معتبر نگه میداره (البته میتونه تا ۲۴ ساعت هم معتبر بمونه، بستگی به تیکش داره). در نتیجه میشه از یه نانس بیشمار مرتبه استفاده کرد و این مفهوم اصلی نانس رو نقض میکنه.
تیکها یا Ticks یکی از پارامترهایی هستن که وردپرس برای ساختن نانس ازشون استفاده میکنه که با فانکشن wp_nonce_tick در پروسه ساخته شدن نانس تعریف میشن.
تیک یک مقداریه که در هر نیمهروز (۱۲:۰۰:۰۰) و نیمهشب (۰۰:۰۰:۰۰) یک واحد تغییر میکنه، یعنی هر ۱۲ ساعت. تیک برای مشخص کردن لایفتایم هر نانس استفاده میشه. همونطور که گفتیم لایفتایم هر نانس تو وردپرس نهایتا تا ۲۴ ساعته. یا به عبارت درستتر، به انداره مقدار تیک حال حاضر و تیک قبلی اعتبار داره.
حالا چون تیک هر ۱۲ ساعت تغییر میکنه، تنها در صورتی یه نانس میتونه ۲۴ ساعت معتبر بمونه که ساعت ۰۰:۰۰:۰۱ یا ۱۲:۰۰:۰۱ ساخته شده باشه. جدول زیر رو ببینین بهتر متوجه میشین:

درسته که نانس وردپرس نانس واقعی نیست و این از نظر امنیتی کمی ضعیفش میکنه، ولی در هر صورت برای جلوگیری از CSRF خیلی بدرد میخوره. فقط حواستون باشه که فقط روی نانس برای امنیت حساب نکنین و فاکتورهای امنیتی دیگه هم حتما لحاظ کنین.
در کل یه نانس واقعی هم فقط به شما میگه که سورس رکوئستی که دارین به اصطلاح geniuinعه (اصیله، قابل اعتماده) و کاری با این نداره که اصلا آیا سورسِ رکوئست پرمیشنِ دادنِ این رکوئست رو داره یا نه!
چند تا فانکشن برای ساختن و چند تا فانکشن برای اعتبارسنجی نانس وجود داره که همه رو بررسی میکنیم:
وردپرس ۳ تا تابع برای ساختن نانس داره:
wp_create_nonce( string|int $action = -1 )
این تابع برای استفاده کلیه و شما هرجا که نیاز داشته باشین میتونین ازش استفاده کنین تا یه Nonce بسازین. یه ورودی اکشن میگیره که بهتره همیشه ازش استفاده کنین و اکشن رو تعریف کنین تا با یه نانس دیگه کانفلیکت نخوره. مثلا:
// create nonce $save_form_nonce = wp_create_nonce( 'save_form_' . $form_id ); // usage <a href="save.php?action=save_form&nonce_token=<?= esc_attr( $save_form_nonce ); ?>&form=<?= esc_attr( $form_id ); ?>"><?php esc_html_e( 'Save', 'textdomain' ); ?></a>
wp_nonce_field( int|string $action = -1, string $name = '_wpnonce', bool $referer = true, bool $echo = true )
این تابع برای توی فرمهای HTMLعه و خروجیش فیلد مخفیایه که نانس رو به عنوان مقدار داره. چهار تا ورودی میگیره که بهتره همیشه از اولی که اکشنه استفاده کنین و اکشن رو تعریف کنین تا با یه نانس دیگه کانفلیکت نخوره.
ورودی دوم اسم فیلد مخفیه و ورودی چهارم میگه که echo کنم یا نه.
ورودی سوم یک فیلد مخفی اضافه ایجاد میکنه به اسم _wp_http_referer که مقدارش URL رفرریه که از متغیر سوپرگلوبال _SERVER گرفته.
مثلا:
<form method="post" id="80"> <!-- some form fields --> <input type=hidden name="is_edit" value="<?php echo esc_attr( $is_edit ); ?>"> <?php wp_nonce_field( 'save_form_80', 'nonce_token' ); ?> </form>
wp_nonce_url( string $actionurl, int|string $action = -1, string $name = '_wpnonce' )
این تابع برای URL استفاده میشه که نانس رو به URL به عنوان یه کوئری استرینگ اضافه میکنه. سه تا ورودی میگیره که بهتره همیشه از دومی که اکشنه استفاده کنین و اکشن رو تعریف کنین تا با یه نانس دیگه کانفلیکت نخوره.
ورودی اول URLایه که میخواین نانس رو بهش اضافه کنین و ورودی سوم هم اسم متغیره.
مثلا:
<?php $url = wp_nonce_url( admin_url(), 'save_form_' . $form_id, 'nonce_token' ); ?> <a href="<?= $url; ?>"><?php esc_html_e( 'Save', 'textdomain' ); ?></a>
وردپرس ۳ تا تابع هم برای اعتبارسنجی نانس داره:
wp_verify_nonce( string $nonce, string|int $action = -1 )
این تابع مثل تابع اول ساختن نانس برای استفاده کلیه و شما هرجا که نیاز داشته باشین یه نانس رو استفاده کنین میتونین ازش استفاده کنین. ورودی اولش که مقدار خود نانسه و ورودی دومش هم اسم اکشنیه که تو فانکشن ساختن نانس استفاده کردین.
خروجی تابع اگه نانس معتبر نباشه falseعه و اگه معتبر باشه نسبت به این که تو این تیک ساخته شده یا تیک قبلی بین ۱ و ۲ متغیره. اگه تو این تیک ساخته شده باشه ۱ و اگه تو تیک قبلی باشه ۲ برمیگردونه. مثلا:
$nonce = $_REQUEST[ 'nonce_token' ]; $nonce = wp_verify_nonce( $nonce, 'save_form_' . $form_id ); switch ( $nonce ) { case 1: echo 'Nonce was generated in the current tick'; break; case 2: echo 'Nonce was generated in the previous tick'; break; default: exit( 'Nonce is invalid' ); }
check_admin_referer( int|string $action = -1, string $query_arg = '_wpnonce' )
برخلاف اسم غلطاندازش، این فانکشن با پرمیشنهای یوزر کاری نداره و دقیقا مثل فانکشن قبلیه. تنها تفاوتی که دارن اینه که این فانکشن در صورتی که نانس نامعتبر باشه، به صورت خودکار با صدا زدن فانکشن wp_nonce_ays که متن ?Are you sure رو نمایش میده، اسکریپت رو متوقف میکنه (die). مثلا:
$nonce = $_REQUEST[ 'nonce_token' ]; if ( check_admin_referer( $nonce, 'save_form_' . $form_id ) ) { // Nonce validated. }
check_ajax_referer( int|string $action = -1, false|string $query_arg = false, bool $die = true )
آخرین تابع اعتبارسنجی یه نانس برای رکوئستهای ایجکس استفاده میشه. این فانکشن ۳ تا ورودی میگیره که اولی اکشنه، دومی اسم متغیر در کوئریه و سومی هم میگه بمیرم یا نمیرم. :)
مثلا:
// Ajax Request <?php //Create your nonce $my_ajax_nonce = wp_create_nonce( 'save_form_' . $form_id ); ?> <script type="text/javascript"> jQuery(document).ready(function($){ var data = { action: 'save_form', form: '<?php echo $form_id; ?>', nonce_token: '<?php echo $my_ajax_nonce; ?>', }; $.post( ajaxurl, data, function(response) { console.log({response}); }); }); // Ajax Request callback add_action( 'wp_ajax_save_form', 'save_form' ); function save_form() { if ( check_ajax_referer( 'save_form_' . $_post['form'], 'nonce_token' ) ) { // Nonce validated. wp_send_json_success(); } }
من یه نانس واقعی برای وردپرس طراحی کردم که خودم استفاده میکردم. امروز براتون گذاشتمش روی گیتهاب، میتونین ازش استفاده کنین.
https://github.com/josephyas/wp-real-nonce
اگه سؤال یا نظری داشتین روی لینکدین یا توییتر سریعتر جواب میدم تا اینجا.
منابع: