CSRF چیست و چگونه کار میکند؟
CSRF مخفف Cross-Site Request Forgery است. مکانیزم آن به یک ویژگی بنیادی مرورگر تکیه دارد: مرورگر کوکیهای یک دامنه را بهصورت خودکار به آن دامنه پیوست میکند، بدون توجه به اینکه درخواست از کدام صفحه شروع شده است. اگر برنامه فقط به وجود کوکی نشست اعتماد کند، صفحهای در دامنهی مهاجم میتواند درخواستی معتبر به دامنهی هدف بسازد و برنامه آن را بهعنوان اقدام آگاهانهی کاربر بپذیرد.
سه پیششرط برای بهرهبرداری لازم است:
- یک عملیات ارزشمند: تغییر ایمیل، تغییر رمز، انتقال وجه، افزودن کاربر، تغییر تنظیمات امنیتی.
- مدیریت نشست مبتنی بر کوکی: برنامه هویت را فقط از کوکی میخواند و هیچ چیز دیگری در درخواست لازم نیست. اگر برنامه هدر
Authorizationبخواهد، CSRF کلاسیک کار نمیکند چون مرورگر آن را خودکار نمیفرستد. - پارامترهای قابل پیشبینی: مهاجم بتواند تمام مقادیر لازم را از قبل بداند یا حدس بزند.
تفاوت کلیدی با XSS: در XSS مهاجم کد را در زمینهی سایت هدف اجرا میکند و میتواند پاسخها را بخواند؛ در CSRF مهاجم فقط میتواند درخواست را بفرستد و پاسخ را نمیبیند. به همین دلیل CSRF ذاتاً یک حملهی «نوشتنی» است. و به همین دلیل هم هر XSS روی دامنه، همهی دفاعهای CSRF را بیاثر میکند — چون مهاجم میتواند توکن را بخواند.
SameSite دقیقاً چه چیزی را عوض کرد؟
این بخش، پرخطاترین قسمت محتوای فارسی امنیت است. واقعیت به این شکل است:
| مرورگر | رفتار پیشفرض وقتی SameSite تعیین نشده |
|---|---|
| Chrome | محدودیت Lax را بهصورت پیشفرض اعمال میکند |
| Firefox | پیشفرض Lax را اعمال نمیکند. باگ ردیابی موزیلا (شمارهی ۱۶۱۷۶۰۹) با وضعیت RESOLVED WONTFIX بسته شده؛ این قابلیت در Firefox 96 عرضه و بهدلیل خرابی گستردهی وب بازگردانده شد |
| Safari | پیشفرض Lax در معنای SameSite ندارد؛ در عوض کوکیهای شخص ثالث را از طریق ITP مسدود میکند — سازوکاری متفاوت با حالتهای مرزی متفاوت |
مستندات MDN هم با احتیاط مینویسد «برخی مرورگرها اگر SameSite تعیین نشده باشد از Lax استفاده میکنند» — نه همه.
معنای سه مقدار:
Strict— کوکی فقط در درخواستهای همسایت ارسال میشود؛ حتی هنگام کلیک روی لینک از سایت دیگر هم ارسال نمیشود (کاربر خارجشده بهنظر میرسد).Lax— علاوه بر درخواستهای همسایت، در درخواستهای بینسایتی که هم پیمایش سطح بالا باشند و هم با متد امن (GET/HEAD/OPTIONS/TRACE) انجام شوند، ارسال میشود.None— در همهی درخواستها ارسال میشود و صفتSecureاجباری است.
وقتی Lax بهعنوان پیشفرض اعمال میشود، کروم نسخهی سهلگیرانهتری به کار میبرد که کوکی را در درخواستهای POST بینسایتی هم میفرستد، بهشرطی که کوکی حداکثر دو دقیقه پیش تنظیم شده باشد. Chromium این را «مداخلهی موقتی» توصیف کرده که در آینده حذف خواهد شد. اینکه آیا هماکنون حذف شده یا نه از منابع رسمی روشن نیست — بنابراین در تست نفوذ باید وجودش را آزمود، نه فرض کرد که هست یا نیست.
چرا SameSite=Lax حمله را غیرممکن نمیکند
حتی در مرورگری که Lax را اعمال میکند، این مسیرها باز میمانند:
- عملیات وضعیتتغییردهنده روی GET. Lax صراحتاً پیمایش GET را مجاز میداند. هر اندپوینتی مثل
/account/delete?id=…که با GET کار میکند، کاملاً قابل بهرهبرداری است. - پارامتر Method Override. فریمورکهایی که
_method=POSTیا هدرX-HTTP-Method-Overrideرا میپذیرند، اجازه میدهند یک درخواست GET اثر POST داشته باشد و همزمان قید Lax را برآورده کند. - Gadget تغییر مسیر سمت کلاینت. اگر خودِ سایت هدف تغییر مسیری را با جاوااسکریپت انجام دهد، درخواست حاصل از دید مرورگر یک درخواست همسایت عادی بهنظر میرسد.
- زیردامنههای خواهر. این مهمترین نکته است: SameSite بر پایهی دامنهی قابل ثبت است، نه Origin. یعنی
a.example.comوb.example.comاز نظر SameSite «همسایت» محسوب میشوند. یک XSS یا Open Redirect روی هر زیردامنهای، تمام حفاظت SameSite را خنثی میکند.
«همهی مرورگرهای مدرن پیشفرض SameSite=Lax دارند، پس CSRF حل شده است.» غلط است. کروم چنین میکند؛ فایرفاکس نمیکند و باگ مربوطه در موزیلا با وضعیت WONTFIX بسته شده. سافاری هم سازوکار متفاوتی (مسدودسازی کوکی شخص ثالث در ITP) دارد. مهمتر از آن، SameSite یک رفتار مرورگر است نه یک کنترل سمت سرور: شما در حال اتکا به انتخاب و نسخهی مرورگر کاربر هستید. توکن CSRF سمت سرور همچنان الزامی است.
یک تصحیح اصطلاحی هم لازم است: SameSite درخواستهای بینسایتی را محدود میکند، نه بینمبدأیی. a.example.com به b.example.com بینمبدأ (cross-origin) است اما همسایت (same-site) — و SameSite هیچ اثری بر آن ندارد. این تمایز را با CORS که واقعاً مبدأمحور است اشتباه نگیرید.
چگونه در تست نفوذ کشف میشود
روال عملی:
- فهرست عملیات وضعیتتغییردهنده: تغییر ایمیل و رمز، تغییر تنظیمات دو عاملی، افزودن/حذف کاربر، انتقال وجه، تغییر آدرس تحویل، اتصال حسابهای خارجی.
- بررسی صفات کوکی در پنل Application مرورگر یا در پاسخ سرور: آیا
SameSiteصراحتاً تعیین شده؟ آیاHttpOnlyوSecureهستند؟ آیا پیشوند__Host-استفاده شده؟ - حذف یا خرابکردن توکن: پارامتر توکن را حذف کنید، مقدارش را خالی بگذارید، مقدار یک کاربر دیگر را بگذارید، یا فقط یک کاراکترش را عوض کنید. الگوهای معیوب رایج: توکن فقط وقتی بررسی میشود که وجود داشته باشد؛ توکن به نشست مقید نیست؛ توکن روی
GETبررسی نمیشود. - تغییر متد: اگر عملیات با POST است، همان را با GET یا با
_methodامتحان کنید. - آزمون در فایرفاکس: اگر سرور
SameSiteرا صراحتاً تعیین نکرده، بهرهبرداری را در فایرفاکس بیازمایید — نتیجه ممکن است با کروم متفاوت باشد. - بررسی زیردامنهها: فهرست زیردامنهها را با subfinder استخراج کنید؛ هر XSS یا تغییر مسیر باز روی یک زیردامنه، سطح حملهی CSRF را باز میکند.
در Burp Suite نسخهی حرفهای، ابزار تولید اثبات مفهوم CSRF کار ساخت فرم را خودکار میکند؛ اما تشخیص اینکه آیا اندپوینت واقعاً محافظتنشده است، دستی میماند.
نمونهی فنی و نگاشت به استانداردها
شکل کلاسیک اثبات مفهوم — یک فرم که بهصورت خودکار ارسال میشود:
<form action="https://app.example.com/account/email"
method="POST">
<input name="email" value="attacker@example.net">
</form>
<script>document.forms[0].submit()</script>و شکل GET که حتی با Lax هم کار میکند و به یک صفحهی HTML هم نیاز ندارد:
<img src="https://app.example.com/account/delete?confirm=1">نگاشت به استانداردها
- OWASP Top 10:2025: CSRF زیر دستهی A01 — Broken Access Control قرار دارد. در نسخهی ۲۰۱۳ دستهی مستقل بود و امروز نیست، اما همچنان یک یافتهی رایج است.
- CWE-352 — Cross-Site Request Forgery. در فهرست ۲۰۲۵ CWE Top 25 رتبهی سوم را دارد؛ یعنی برخلاف تصور «حلشده بودن»، همچنان یکی از پرتکرارترین و پرآسیبترین ضعفهای ثبتشده است.
- WSTG-SESS: آزمون CSRF یکی از نه آزمون بخش مدیریت نشست راهنمای آزمون OWASP است.
پرسشهای متداول
آیا با SameSite دیگر به توکن CSRF نیاز نداریم؟
نیاز دارید. SameSite یک رفتار مرورگر است، نه یک کنترل سمت سرور؛ اتکا به آن یعنی اتکا به مرورگر و نسخهای که کاربر انتخاب کرده. فایرفاکس پیشفرض Lax را اعمال نمیکند، عملیات مبتنی بر GET حتی با Lax قابل سوءاستفادهاند، و زیردامنههای خواهر از نظر SameSite همسایت محسوب میشوند. توکن همزمانساز سمت سرور همچنان الزامی است.
آیا فایرفاکس واقعاً پیشفرض SameSite=Lax ندارد؟
ندارد. باگ ردیابی موزیلا با شناسهی ۱۶۱۷۶۰۹ با وضعیت RESOLVED WONTFIX بسته شده است. این قابلیت در Firefox 96 عرضه شد اما بهدلیل خرابی گستردهی سایتها بازگردانده و غیرفعال شد. تنظیم مربوطه در نسخهی انتشار خاموش است. بنابراین برنامهای که SameSite را صراحتاً تعیین نکرده و توکن CSRF ندارد، امروز در فایرفاکس قابل بهرهبرداری است.
اگر از JWT در هدر Authorization استفاده کنم، CSRF ندارم؟
در حالت کلاسیک بله، چون مرورگر هدر Authorization را خودکار ضمیمه نمیکند و مهاجم نمیتواند آن را از سایت خودش تنظیم کند. اما اگر همان JWT را در کوکی نگه دارید، دقیقاً همان سطح حمله برمیگردد. توجه کنید که نگهداری توکن در localStorage هم مشکل CSRF را با مشکل بزرگتر «خواندنی بودن توسط XSS» عوض میکند.
CSRF در OWASP Top 10 کجاست؟
در نسخهی ۲۰۲۵ دستهی مستقلی ندارد و ذیل A01 کنترل دسترسی شکسته قرار میگیرد؛ شناسهی CWE آن ۳۵۲ است. نکتهی مهم اینکه CWE-352 در فهرست ۲۰۲۵ CWE Top 25 رتبهی سوم را دارد، یعنی از نظر دادهی واقعی هنوز بسیار پرتکرار است.