چگونه از حمله CSRF جلوگیری کنیم؟

csrf defence

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

توکن CSRF چیست؟

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

توکن‌های CSRF می‌توانند از حملات جعل درخواست فراوبگاهی (Cross-Site Request Forgery) یا CSRF جلوگیری کنند، چون با وجود این توکن‌ها، برای هکر غیرممکن می‌شود که یک ریکوئست HTTP کاملا معتبر بسازد که بتوان آن را به کاربر قربانی داد تا اجرا کند. از آن‌جایی که مهاجم نمی‌تواند مقدار توکن CSRF یک کاربر را تعیین یا پیش‌بینی کند، نمی‌تواند ریکوئستی بسازد که تمام پارامترهای لازم برای قبول‌شدن توسط اپلیکیشن را داشته باشد.

توکن‌های CSRF را چگونه باید تولید کرد؟

توکن‌های CSRF باید پراکندگی بالایی داشته باشند (یعنی نظم و الگویی نداشته باشند) و پیش‌بینی آن‌ها به شدت سخت باشد، و به طور کلی ویژگی‌های توکن‌های سشن را داشته باشند.

برای تولید این توکن‌ها باید از یک تولیدکننده اعداد شبه‌تصادفی (PRNG) قدرتمند و رمزنگاری‌شده استفاده کنید که داخل خود یک برچسب زمانی حاوی زمان ایجاد‌شدن، در کنار یک مقدار مخفی (Secret) ثابت داشته باشد.

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

توکن‌های CSRF را چگونه باید انتقال داد؟

با توکن‌های CSRF باید به‌عنوان مقادیر محرمانه رفتار کنید و از لحظه‌ای که تولید می‌شوند تا لحظه‌ای که از بین می‌روند، آن‌ها را به صورت ایمن مدیریت کنید. رویکردی که معمولا موثر واقع می‌شود، این است که داخل یک فیلد مخفی از یک فرم HTML که با استفاده از متد POST ثبت می‌شود توکن را به کلاینت مخابره کنید. این‌گونه وقتی فرم ثبت شد، توکن به عنوان یک پارامتر به ریکوئست اضافه می‌شود:

<input type=”hidden” name=”csrf-token” value=”CIwNZNlR4XbisJF39I8yWnWX9wX4WFoz” />

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

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

  • در جاهای مختلفی در سمت کلاینت و سرور لاگ‌گیری می‌شود؛
  • امکان دارد به منابع خارجی که در هدر Referer ریکوئست HTTP آمده‌اند مخابره شود، و
  • می‌تواند روی صفحه در مرورگر کاربر نمایش داده شود.

برخی اپلیکیشن‌ها، توکن‌های CSRF را داخل یک هدر شخصی‌سازی‌شده در ریکوئست ارسال می‌کنند. این‌گونه یک لایه دفاعی دیگر نیز ایجاد می‌شود که در برابر مهاجمی که توانسته توکن یک کاربر را پیش‌بینی یا ضبط کند هم از کاربر حفاظت می‌کند، زیرا مروررها معمولا اجازه ارسال هدرهای شخصی‌سازی‌شده از یک دامنه به دامنه دیگر را نمی‌دهند. البته وقتی این رویکرد پیاده‌سازی شود، اپلیکیشن فقط می‌تواند با استفاده از XHR (به جای فرم‌های HTML) ریکوئست‌های محافظت‌شده در برابر CSRF بزند که ممکن است برای بسیاری از موارد استفاده واقعی، پیچیدگی آن بیش از حد باشد.

توکن‌های CSRF را نباید داخل کوکی‌ها مخابره کرد.

توکن‌های CSRF را چگونه باید اعتبارسنجی کرد؟

وقتی یک توکن CSRF تولید می‌شود، باید در سمت سرور به همراه داده‎های سشن کاربر ذخیره شود. پس از آن وقتی یک ریکوئست دریافت شد که نیاز به اعتبارسنجی داشت، اپلیکیشن سمت سرور باید اطمینان حاصل کند که آن ریکوئست، حاوی توکنی باشد که با توکن ذخیره‌شده در سشن کاربر مطابقت دارد. اعتبارسنجی باید بدون توجه به نوع محتوا یا متد HTTP ریکوئست انجام شود. اگر ریکوئست به کلی حاوی هیچ توکنی نبود، باید  همان‌طور که یک ریکوئست دارای توکن اشتباه رد می‌شود، آن هم رد شود.

csrf

دفاع در برابر CSRF با کوکی‌های SameSite

بعضی وبسایت‌ها با استفاده از کوکی‌های SameSite در برابر حملات CSRF از کاربران خود محافظت می‌کنند. SameSite یک attribute است که با استفاده از آن می‌توان امکان ثبت و نحوه ثبت کوکی‌ها را در ریکوئست‌های بین‌سایتی (Cross-Site) کنترل کرد. همان‌طور که در توضیح حملات CSRF گفتیم، مرورگر بدون توجه به این که ریکوئست از چه منبعی زده شده، به طور خودکار کوکی‌های لازم را به آن اضافه می‌کند. اپلیکیشن با تنظیم این attribute در کوکی‌های سشن، می‌تواند مانع این رفتار مرورگر شود.

وقتی سرور یک کوکی صادر می‌کند، اتریبیوت SameSite به هدر Set-Cookie اضافه می‌شود که یک Response Header است. بعد از اضافه شدن این اتریبیوت به این هدر، می‌توان مقدار Strict یا Lax را به آن داد. برای مثال:

Set-Cookie: SessionId=sYMnfCUrAlmqVVZn9dqevxyFpKZt30NN; SameSite=Strict;

Set-Cookie: SessionId=sYMnfCUrAlmqVVZn9dqevxyFpKZt30NN; SameSite=Lax;

اگر مقدار اتریبیوت SameSite معادل Lax قرار داده شود، در این صورت مرورگر تنها درصورتی کوکی‌ها را به ریکوئست‌های زده‌شده از سایت‌های دیگر اضافه می‌کند که دو شرط زیر برآورده شوند:

  • ریکوئست از متد GET استفاده کرده باشد. ریکوئست‌ها با متدهای دیگر، مانند متد POST، بدون کوکی ارسال می‌شوند.
  • ریکوئست نتیجه‎‌ی یک تعامل سطح بالا از سوی کاربر باشد؛ مثلا زمانی که کاربر روی یک لینک کلیک می‌کند. ریکوئست‌های دیگر، مانند ریکوئست‌های تولیدشده توسط اسکریپت‌ها، بدون کوکی زده می‌شوند.

استفاده از کوکی‌های SameSite در حالت Lax، حفاظتی نسبی را در برابر حملات CSRF فراهم می‌کند، زیرا آن دسته از اقدامات مجاز برای کاربر در اپلیکیشن‌ها که هدف حملات CSRF هستند، معمولا با استفاده از متد POST پیاده‌سازی می‌شوند. این حالت، دو نقص اصلی دارد:

  • در بعضی اپلیکیشن‌ها اقدامات حساس تحت اختیار کاربر با استفاده از ریکوئست‌های GET پیاده‌سازی شده‌اند.
  • بسیاری از اپلیکیشن‌ها و فریم‌ورک‌ها استفاده از متد HTTP متفاوت با متد درست را تحمل می‌کنند. در این مواقع، حتی اگر در طراحی خود اپلیکیشن از متد POST برای اقدام خاصی استفاده شده باشد، در عمل ریکوئست‌هایی را که با متد GET زده شده باشند هم قبول می‌کند.

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

علاقمند به حوزه امنیت اطلاعات و آشنا به حوزه تست نفوذ
  • facebook
  • twitter
  • googleplus
  • linkedIn
  • flickr

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

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