CSRF Tokens در وردپرس (توکن‌های ضد جعل درخواست) چطور کار می‌کنند؟ این پرسشی است که پاسخ آن، مرز بین یک فرم امن و یک فرم آسیب‌پذیر را مشخص می‌کند. CSRF Token (توکن ضد جعل درخواست) یک مقدار منحصربه‌فرد است که به هر فرم یا درخواست تغییردهنده اضافه می‌شود و در سمت سرور بررسی می‌گردد. برخلاف احراز هویت که هویت کاربر را تأیید می‌کند، CSRF Token تأیید می‌کند که درخواست از یک منبع معتبر و از طرف کاربر واقعی ارسال شده است. در وردپرس، این توکن‌ها با نام Nonce (Number used once - عدد یک‌بارمصرف) شناخته می‌شوند و از طریق توابع wp_create_nonce()، wp_nonce_field() و wp_verify_nonce() پیاده‌سازی می‌شوند. تفاوت اصلی CSRF Token با Nonce وردپرس در این است که CSRF Token یک مفهوم عمومی است و Nonce پیاده‌سازی خاص وردپرس از آن است. مکانیزم کار به این شکل است: سرور یک توکن منحصربه‌فرد تولید می‌کند، آن را در فرم قرار می‌دهد، و هنگام ارسال، بررسی می‌کند که توکن معتبر و متعلق به همان کاربر و همان اکشن است. بدون این توکن، مهاجم می‌تواند با یک صفحه مخرب، کاربر را وادار به ارسال درخواست ناخواسته کند. در این نوشتار، از ریشه‌های فنی CSRF Token تا پیاده‌سازی حرفه‌ای آن در وردپرس را بررسی می‌کنیم.

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

CSRF Token چیست؟

CSRF Token (توکن ضد جعل درخواست) یک مقدار منحصربه‌فرد و غیرقابل پیش‌بینی است که به هر فرم یا درخواست تغییردهنده اضافه می‌شود. این توکن در سمت سرور تولید و در فرم قرار می‌گیرد، سپس هنگام ارسال، سرور بررسی می‌کند که توکن معتبر و متعلق به همان کاربر و همان اکشن است. اگر توکن نامعتبر یا غایب باشد، درخواست رد می‌شود.

سه ویژگی اصلی CSRF Token عبارتند از:

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

این سه ویژگی، توکن را به یک «امضای دیجیتال سبک» تبدیل می‌کند که ثابت می‌کند درخواست از منبع معتبر ارسال شده است. برای درک عمیق‌تر جایگاه این مفهوم در امنیت وب، اصول امنیت وب را ببینید.

CSRF Token یک «اثر انگشت» است: ثابت می‌کند فرم از سایت شما آمده، نه از یک صفحه مخرب. بدون آن، هر درخواست معتبر به‌نظر می‌رسد.

چرا CSRF Token ضروری است؟

CSRF یکی از شایع‌ترین آسیب‌پذیری‌های وب است و در OWASP Top 10 در دسته «Broken Access Control» قرار می‌گیرد. در این حمله، مهاجم کاربر احراز هویت‌شده را وادار به ارسال درخواست ناخواسته به سایتی می‌کند که در آن لاگین است. مرورگر به‌طور خودکار Cookie احراز هویت را ارسال می‌کند و سرور درخواست را معتبر می‌داند.

یک مثال ساده از حمله CSRF بدون توکن:

<form action="https://victim.com/wp-admin/profile.php" method="POST">
  <input type="hidden" name="email" value="attacker@evil.com">
  <input type="submit" value="برنده شوید!">
</form>
<script>document.forms[0].submit();</script>

اگر سایت در برابر CSRF محافظت نداشته باشد، مرورگر کاربر Cookie احراز هویت را ارسال می‌کند و وردپرس ایمیل کاربر را تغییر می‌دهد. CSRF Token این حمله را خنثی می‌کند، زیرا مهاجم نمی‌تواند توکن را پیش‌بینی یا جعل کند. برای درک عمیق‌تر این حمله، حملات CSRF و روش‌های دفع را ببینید.

تفاوت CSRF Token و Nonce وردپرس

ویژگیCSRF Token (عمومی)Nonce وردپرس
مفهومعمومی در وبپیاده‌سازی خاص وردپرس
مدت اعتبارمعمولاً تا پایان نشست۱۲ تا ۲۴ ساعت
اتصال به کاربربلهبله (با User ID و توکن)
اتصال به اکشنمعمولاً خیربله (اکشن خاص)
یک‌بارمصرفمعمولاً بلهخیر

جمع‌بندی این مقایسه ساده است: Nonce وردپرس یک نوع خاص از CSRF Token است که به اکشن و کاربر گره خورده و مدت اعتبار محدودی دارد. برای درک عمیق‌تر Nonce، نانس وردپرس و امنیت فرم را ببینید.

مکانیزم فنی CSRF Token

مکانیزم CSRF Token در سه مرحله انجام می‌شود:

مرحله ۱: تولید توکن

سرور یک توکن تصادفی و منحصربه‌فرد تولید می‌کند و آن را در نشست کاربر ذخیره می‌کند:

$token = bin2hex( random_bytes( 32 ) );
$_SESSION['csrf_token'] = $token;

مرحله ۲: درج توکن در فرم

<form method="post">
  <input type="hidden" name="csrf_token" value="<?php echo esc_attr( $token ); ?>">
  <input type="submit" value="ذخیره">
</form>

مرحله ۳: بررسی توکن در سمت سرور

if ( ! isset( $_POST['csrf_token'] ) ||
     ! hash_equals( $_SESSION['csrf_token'], $_POST['csrf_token'] ) ) {
  die( 'Invalid CSRF token' );
}

استفاده از hash_equals() به‌جای == ضروری است، زیرا از حملات timing attack جلوگیری می‌کند. برای درک عمیق‌تر ساختار امنیتی، نوشتن کد PHP امن برای وردپرس را ببینید.

پیاده‌سازی CSRF Token در وردپرس

در وردپرس، پیاده‌سازی CSRF Token با Nonce انجام می‌شود. سه تابع اصلی عبارتند از:

ساخت توکن

$token = wp_create_nonce( 'myplugin_action' );

درج در فرم

<?php wp_nonce_field( 'myplugin_action', 'myplugin_token' ); ?>

بررسی در سمت سرور

if ( ! isset( $_POST['myplugin_token'] ) ||
     ! wp_verify_nonce( $_POST['myplugin_token'], 'myplugin_action' ) ) {
  wp_die( 'Security check failed' );
}

علاوه بر این، وردپرس توابع check_admin_referer() و check_ajax_referer() را نیز ارائه می‌دهد که ترکیبی از بررسی Nonce و Referer هستند. برای درک عمیق‌تر، پیاده‌سازی نانس در فرم‌های سفارشی را ببینید.

CSRF Token در AJAX و REST API

در AJAX و REST API، ارسال CSRF Token کمی متفاوت است:

AJAX با admin-ajax.php

// در JavaScript
jQuery.post( ajaxurl, {
  action: 'myplugin_save',
  nonce: mypluginData.nonce,
  data: formData,
} );

// در PHP
add_action( 'wp_ajax_myplugin_save', function() {
  check_ajax_referer( 'myplugin_save', 'nonce' );
  // پردازش
} );

REST API

fetch( '/wp-json/myplugin/v1/settings', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-WP-Nonce': wpApiSettings.nonce,
  },
  body: JSON.stringify( data ),
} );

در REST API، وردپرس به‌طور خودکار Nonce را از هدر X-WP-Nonce می‌خواند و بررسی می‌کند. برای درک عمیق‌تر، استفاده از REST API در وردپرس را ببینید.

محدودیت‌ها و لایه‌های تکمیلی

CSRF Token یک ابزار قدرتمند است، اما کامل نیست:

  • در برابر XSS آسیب‌پذیر است: اگر سایت در برابر XSS آسیب‌پذیر باشد، مهاجم می‌تواند توکن را بخواند.
  • در برابر Clickjacking محافظت نمی‌کند: در Clickjacking، فرم واقعاً کلیک می‌شود و توکن معتبر است.
  • مدت اعتبار محدود: ممکن است در فرم‌های طولانی منقضی شود.
  • وابستگی به Cookie: اگر Cookie ارسال نشود، توکن بی‌اثر است.

به همین دلیل، CSRF Token باید با لایه‌های دیگر ترکیب شود:

  • SameSite Cookies: محدودسازی ارسال Cookie در درخواست‌های cross-site.
  • بررسی Origin و Referer: لایه دفاعی اضافی.
  • تأیید مضاعف: برای اقدامات حساس، تأیید رمز فعلی.
  • 2FA: برای ورود و اقدامات حساس.

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

اشتباهات رایج در استفاده از CSRF Token

  • نادیده گرفتن توکن در AJAX: بسیاری از توسعه‌دهندگان توکن را فقط در فرم‌های HTML بررسی می‌کنند.
  • بررسی توکن در JavaScript: توکن باید در سمت سرور بررسی شود.
  • استفاده از یک توکن برای چند اکشن: هر اکشن باید توکن جداگانه داشته باشد.
  • اعتماد به توکن به‌تنهایی: باید با بررسی سطح دسترسی ترکیب شود.
  • فراموش کردن REST API: endpointهایی که با Cookie احراز هویت می‌کنند، نیازمند توکن هستند.
  • عدم مدیریت انقضا: باید پیام مناسب برای توکن منقضی نمایش داده شود.
  • استفاده از == به‌جای hash_equals(): این الگو در برابر timing attack آسیب‌پذیر است.
  • ذخیره توکن در localStorage: این الگو در برابر XSS آسیب‌پذیر است.

برای درک عمیق‌تر XSS، راهنمای پیشگیری از حملات XSS را ببینید.

پرسش‌های پرتکرار درباره CSRF Token

آیا CSRF Token با Nonce وردپرس یکی است؟ Nonce وردپرس یک نوع خاص از CSRF Token است که به اکشن و کاربر گره خورده و مدت اعتبار محدودی دارد.

چرا CSRF Token منقضی می‌شود؟ به دلیل محدودیت زمانی طراحی‌شده برای امنیت. اگر کاربر فرمی را ساعت‌ها باز نگه دارد، توکن منقضی می‌شود.

آیا CSRF Token در برابر Clickjacking محافظت می‌کند؟ نه، در Clickjacking کاربر واقعاً کلیک می‌کند و توکن معتبر است. برای دفاع در برابر Clickjacking، از هدرهای X-Frame-Options و frame-ancestors استفاده کنید. برای مرور کلی، راهنمای هدرهای امنیتی HTTP را ببینید.

آیا افزونه‌های امنیتی CSRF Token را خودکار اضافه می‌کنند؟ نه، توکن باید در کد فرم‌ها و درخواست‌های AJAX اضافه شود. برای مرور کلی، امنیت وردپرس را ببینید.

چطور بفهمم فرم من CSRF Token دارد؟ کد فرم را جست‌وجو کنید. هر فرمی که عملیات تغییردهنده انجام می‌دهد، باید wp_nonce_field() داشته باشد.

آیا استفاده از CSRF Token روی عملکرد سایت تأثیر دارد؟ تأثیر آن حداقلی است، زیرا تولید و بررسی توکن سریع است. برای مرور خطاهای مشابه، اشتباهات امنیتی رایج در وردپرس را ببینید.

برای مطالعه بیشتر درباره این مفهوم، صفحه Cross-site request forgery در ویکی‌پدیا مفید است.

خط پایان

CSRF Token یکی از آن لایه‌های امنیتی است که در سایه XSS و SQL Injection کمتر دیده می‌شود، اما در واقع «قفل اصلی» فرم‌های وب است. بدون توکن، هر فرم تغییردهنده می‌تواند قربانی CSRF شود و مهاجم می‌تواند بدون اطلاع کاربر، عملیات حساسی اجرا کند. در بستر وردپرس، Nonce یک پیاده‌سازی قدرتمند از این مفهوم است که در همه فرم‌ها، AJAX و REST API قابل استفاده است. دفاع مؤثر نیازمند استفاده از توکن در همه endpointهای تغییردهنده، ترکیب آن با بررسی سطح دسترسی، و افزودن لایه‌های تکمیلی مانند SameSite است. اگر سایت شما فرم تغییردهنده دارد، همین امروز کد را بازبینی کنید.

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