Let’s travel together.

آسیب پذیری یا باگCSRF چیست؟

زمان مطالعه: 15 دقیقه

آیا تا به حال شنیده‌اید که نباید بی‌احتیاط روی هر لینکی کلیک نماییم یا هر فایلی را باز کنیم؟ شاید شنیده‌اید که فردی با وارد شدن به یک لینک یا یک سایت مخرب که از طریق ایمیل یا شبکات اجتماعی برایش ارسال شده بود، هک شده باشد. در این نوشتار به یک آسیب‌پذیری خطرناک می‌پردازیم که تا کنون باعث بوجود آمدن بسیاری از این دست حملات در بستر اینترنت شده است و حتی سرویس‌های معروفی مانند Netflix و Youtube نیز دچار این آسیب‌پذیری بوده‌اند . حمله ای که به آن لقب “هیولای خفته ی جهان امنیت وب” را داده‌اند.

آسیب پذیری CSRF چیست؟

واژه CSRF مختصرCross Site Request Forgery می‌باشد؛ همچنین آن را با نام‌های XSRF، Sea Surf(موج سواری)‌‌، Session Riding(جلسه رانی)‌‌، Hostile Linking(پیوند خصمانه) وOne-click Attack(حمله یک کلیکی) نیز می‌شناسند. این حمله از جمله حملات خطرناک درServer-side  یا سمت سرور به شمار می‌رود که بیشترین تمرکز این حمله‌‌، روی وب‌سایت‌هایی می‌باشد که دارای سیستم احراز هویت کاربران‌‌، مانند سرویس‌ بانک ها‌‌، مراکز آموزشی‌‌، فروشگاه ها و … می‌باشد.

معنی لغوی این حمله به صورت “حملات جعل درخواست” گفته می‌شود و همانطور که از نام آن پیداست‌‌، نفوذگر در این نوع از حمله‌‌، موفق به فرستادن یک درخواست جعلی از با استفاده از هویت کاربر قربانی می‌شود که بنابر سطح آسیب‌پذیری و عملکرد درخواست ارسالی‌‌، ضرر‌های گوناگونی را وارد می‌کند.

تاثیرات حمله CSRF یا جعل درخواست

این حمله بر اساس عملکرد برنامه کاربردی (Web Application) می‌تواند آسیب‌های مخصوص به خود را داشته باشد. به مثال‌هایی از این حمله می‌پردازیم:

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

بنابراین دریافتیم که این آسیب‌پذیری می‌تواند در هر برنامه کاربردی‌‌، عملکرد مخربانه‌ای مرتبط با برنامه داشته باشد.

کشف آسیب‌پذیری CSRF

برای آنکه بتوان گفت یک برنامه کاربردی دارای آسیب‌پذیری CSRF می‌باشد‌‌، باید سه شرط کلیدی زیر در آن وجود داشته باشد:

وجود یک عملکرد(action) :

در هر برنامه کاربردی‌‌، وجود یک عملکرد است که باعث ساخته شدن درخواست جعلی بابت این عملکرد می شود . عملکردی مثل تغییر رمز عبور‌‌، دادن دسترسی به کاربران و …

احراز هویت بر اساس کوکی:

برای اینکه از هویت و نشست کاربر قربانی استفاده شود‌‌، باید احراز هویت برنامه برای انجام عملیات براساس کوکی نشست در درخواست باشد.

عدم وجود پارامتر‌های غیر قابل حدس:

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

ابزار‌های کشف آسیب‌پذیری CSRF

برای کشف این آسیب‌پذیری‌‌، ابزاری مورد نیاز است که نقش پروکسی داخلی را برای آنالیز درخواست ها (Request) و پاسخ ها (Responses)، برای ما ایفا کند. مانند:

  • Burp Suite

  • Fiddler

  • Postman

از مزایای این ابزار ها می توان به ایجاد تغییر در درخواست و همچنین مشاهده ی پاسخ ها (Responses) بصورت خام(RAW) اشاره کرد که در تست آسیب پذیری CSRF به ما کمک میکند.

انواع آسیب‌پذیری CSRF

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

CSRF را می‌توان از نظر نوع پیاده‌سازی به 3 بخش تقسیم نمود:

  • سناریو متد GET
  • سناریو متد POST
  • سناریو متد‌های دیگر

 سناریو متد GET

در این سناریو‌‌، سایت آسیب پذیر برای انجام عملیات‌های حساس مانند انتقال وجه‌‌، تغییر در نام کاربری‌‌، ایمیل یا رمز عبور و … از متد GET استفاده می‌کند که از اشتباهاتی است که باعث بالا رفتن شدت آسیب‌پذیری CSRF در برنامه می‌شود. در نظر داشته باشید که در یک برنامه کاربردی‌‌، درخواستی با متد GET نباید باعث ایجاد یک عملکرد در سمت سرور شود. مثالی از این موضوع در زیر مشاهده می‌نمایید:

در یک برنامه کاربردی مخصوص بانک‌‌، نفوذگری قصد انتقال وجه به مبلغ 100 دلار، به فردی با شماره کارت فرضی 1234 را دارد. او پس از تعیین مبلغ و شماره کارت بانکی گیرنده‌‌، روی دکمه ” انتقال” کلیک می‌کند و مشاهده می‌کند  که درخواست او به صورت GET درحال ارسال است و محتوای URL، رشته‌ای مانند زیر است:

http://bank.com/transfer.do?acct=1234&amount=100

این درخواست شرایط گفته شده آسیب‌پذیری CSRF را شامل می‌شود:

  • وجود عملکرد حساس در GET
  • احراز هویت بر اساس کوکی
  • پارامتر‌های قابل تشخیص

او متوجه می‌شود که شماره کارت فرد گیرنده از طریق پارامتر acct و مبلغ مد نظر وی از طریق پارامتر amount در url تعیین می‌شود و احراز هویت وی هم از طریق کوکی صورت می‌گیرد.

پس نتیجه می‌گیریم که اگر درون پارامتر acct به جای شماره کارت بانکی مقصد، شماره کارت خود و در پارامتر amount مبلغ دلخواه خود را بنویسد‌‌، فردی که این درخواست را ارسال کند‌‌، در صورت Login بودن در سایت بانک مربوطه‌‌، مبلغ 100 دلار را به حساب او واریز می‌کند.

در اینجا نفوذگر برای اینکه قربانی را منجر به ارسال این درخواست جعلی بنماید‌‌، می‌تواند از روش‌ها و تکنیک‌های مهندسی اجتماعی بهره گیرد، به عنوان مثال می‌تواند از تکنیک‌هایی مانند موارد زیر استفاده کند:

  • ارسال یک ایمیل به همراه یک فایل html .
  • قرار دادن یک URL یا اسکریپت در صفحاتی که ممکن است قربانی حین عملیات بانکی آن را ببیند.

1

نفوذگر از کد‌های پیوندی که کاربر را به یک مسیر هدایت می‌کنند مثل کد html زیر‌‌، در سایت خود یا هر سایتی که به هر دلیلی قابلیت استفاده از این کد را دارد‌‌، استفاده می‌کند و با متنی وسوسه انگیز سعی بر ترغیب قربانی به کلیک روی متن مورد نظر مانند “Click here” می‌نماید:

<a href="http://bank.com/transfer.do?acct=4321&amount=100">
Click here!</a>

قربانی با دیدن متن‌هایی فریب دهنده مانند برنده شدن در قرعه کشی‌‌، گرفتن یک کد تخفیف بسیار ویژه‌‌، خواندن یک خبر بسیار جذاب و امثال آن، ترغیب به کلیک بر متن دارای پیوند میشود وکلیک را انجام می‌دهد.

پس از آن که قربانی روی متن کلیک کند، درخواستی با متد GET همراه با کوکی وی به سایت بانک ارسال و مبلغی را از حساب او به حساب نفوذگر منتقل می‌کند.

البته این راه بیشتر در مواقعی کاربرد دارد که نفوذگر فقط میتواند یک متن را لینک کند یا خود لینک را ارسال کند . مثلا در بعضی وبلاگ ها‌‌، در قسمت‌های کامنت‌‌، در متن ایمیل و راه‌هایی مانند آن.

چون در صورت امکان نوشتن کد html نفوذگر می‌تواند از تگ <img> یا <form>  برای ارسال درخواست جعل شده استفاده کند:

<img src=”http://bank.com/transfer.do?acct=4321&amount=1000″ width=”0″ height=”0″ border=”0″>

در صورتی که قربانی‌‌، صفحه ای حاوی این کد را باز کند‌‌، مرورگر قربانی به صورت خودکار برای باز کردن تصویر‌‌، درخواست مورد نظر نفوذگر را به سمت سایت بانک میفرستد . در اینجا درخواست با متد GET فرستاده و وجه منتقل می‌شود ولی قربانی اثری از سایت بانک و تصویر اجرا شده را نمی‌بیند . زیرا صفت‌های تگ این تصویر ساخته شده‌‌، طول و عرض تصویر”0” قرار داده‌اند که باعث می‌شود تصویر نفوذگر دیده نشود.

در نظر داشته باشید که اگر برای این درخواست از متد POST استفاده میشد‌‌، استفاده از تگ <img>‌‌، تگ‌های پیوندی یا فرستادن آدرس پیوند برای ارسال درخواست وجود نمی‌داشت. بسیاری از فریمورک‌های تحت وب نظیرruby on rails، Django  و موارد دیگر‌‌، به صورت خودکار از بعضی از راهکار‌های پیشگیری در برابر CSRF فقط در درخواست‌هایی که با متد POST است، استقاده می‌کنند. پس تا اینجا با مشکلات استفاده از متد GET برای فرستادن اینگونه درخواست ها آشنا شدیم. در ادامه این نوشتار با راهکار‌های امن سازی برنامه در برابر CSRF بیشتر آشنا خواهیم شد.

 

مثال واقعی CSRF با متد GET

در 17 ژانویه 2016‌‌، در سایت HackerOne (از پلتفرم‌های معروف باگ بانتی یا کشف آسیب‌پذیری)‌‌، گزارشی توسط یک کارشناس تست نفوذ از WeSecureApp مبنی بر وجود آسیب‌پذیری در یکی از دامنه‌های مرتبط با Twitter با نام shopify به آدرس  twittercommerce. shopifyapps.com ثبت شد.

2

 

این دامنه به منظور ارتباط کاربران صاحب فروشگاه در توییتر، برای ارسال مطلب در رابطه با محصولاتشان در برنامه و بود . همچنین این برنامه دارای قابلیتی برای Disconnect یا خارج کردن حساب توییتر متصل به برنامه shopify بود.

کارشناس کشف کننده ی این آسیب‌پذیری‌‌، متوجه شد که عمل خارج کردن حساب در این برنامه با متد GET و با url زیر صورت می‌گیرد:

https://twitter-commerce.shopifyapps.com/auth/twitter/disconnect/

و این برنامه برای این عملکرد از درخواست GET زیر استفاده می‌کرد:

GET /auth/twitter/disconnect HTTP/1.1
Host: twitter-commerce.shopifyapps.com
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:43.0)
Gecko/20100101 Firefox/43.0
Accept: text/html, application/xhtml+xml, application/xml
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: https://twitter-commerce.shopifyapps.com/account
Cookie: _twitter-commerce_session=REDACTED
Connection: keep-alive

کارشناس کشف کننده این آسیب‌پذیری از کد زیر به عنوان poc (اثبات مفهوم) استفاده کرد:

<html>
<body>
<img src="https://twitter-commerce.shopifyapps.com/auth/twitter/disconnect">
</body>
</html>

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

سناریو متد POST

تا اینجا متوجه شدیم نباید از متد GET برای انجام عملکرد‌های مهم و موثر در سمت سرور استفاده کرد. ولی با فرض اینکه برای اینگونه درخواست ها از متد POST استفاده شده باشد‌‌، آیا راهی برای بهره برداری از آسیب‌پذیری CSRf وجود نخواهد داشت؟ در ادامه به سناریو بهره برداری از باگ CSRF با متد POST می‌پردازیم :

فرض کنید وب‌سایتی با نام “example.com”  دارای قابلیت تغییر ایمیل برای هر کاربر در پنل کاربری خود دارد و زمانی که کاربر اقدام به تغییر ایمیل می‌کند‌‌، درخواست http زیر ارسال می‌شود:

POST /email/change HTTP/1.1
Host: example.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 30
Cookie: session=yvthwsztyeQkAPzeQ5gHgTvlyxHfsAfE

email=victim@normal-user.com

که تمام شرایط وجود باگ CSRF را در بر می‌گیرد:

  • اقدام تغییر ایمیل که مورد توجه نفوذگر قرار می‌گیرد. زیرا در مرحله ی بعد از تغییر ایمیل قربانی به ایمیل خود‌‌، نوبت به تغییر رمز عبور و به دست گرفتن کنترل کامل حساب کاربری فرا می‌رسد.
  • در اینجا برای شناسایی کاربر از session cookie استفاده شده و هیچ توکن یا مکانیزم دیگری برای احراز هویت کاربر ارسال کننده درخواست وجود ندارد.
  • نفوذگر تمامی‌مقادیر مورد نیاز برای ارسال درخواست تغییر ایمیل را به راحتی می‌تواند تشخیص دهد.

پس نفوذگر می‌تواند این درخواست را تغییر بدهد تا ایمیل کاربر به ایمیل مورد نظر او تغییر پیدا کند. برای اینکار در پارامتر email‌‌، آدرس ایمیل خود را مینویسد.

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

<form action="https://example.com/email/change" method="POST">
<input type="hidden" name="email" value="hacker@evil-user.net"/>
</form>
<script>
document.forms[0].submit  
</script>

بعد از مراحل گفته شده در صورتی که کاربر قربانی وارد صفحه مد نظر سایت نفوذگر بشود‌‌، مراحل زیر اتفاق می‌افتد:

  • سایت نفوذگر درخواست http سفارشی شده را به سمت سایت آسیب پذیر هدایت می‌کند.
  • در صورت عضو بودن قربانی در سایت آسیب پذیر، مرورگ به صورت خودکاری کوکی کاربر را درون درخواست قرار می‌دهد و درخواست، بصورت پنهانی و خودکار ارسال می‌شود ؛ دستور جاوا اسکریپت نوشته شده‌‌، خود به خود فرم را ارسال می‌کند
  • سایت آسیب پذیر درخواست را پردازش کرده و ایمیل مربوط به قربانی را تغییر می‌دهد.

دقت کنید که از روش‌های متد POST مثل استفاده از دستور form یا دستور  XHR (که در ادامه به آن می‌پردازیم) در سناریو متد GET هم می‌توان استفاده نمود‌‌، اما از روش‌های گفته شده در سناریو GET نمی‌توان در حملات با سناریو POST استفاده نمود.

مثال واقعی CSRF با متد POST

3

مثالی از این گونه آسیب‌پذیری در برنامه وب Instacart وجود داشت که در تاریخ 9 آگوست 2015 در سایت HackerOne گزارش شد. Instacart یک سرویس انتقال

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

کارشناس گزارش دهنده این آسیب‌پذیری‌‌، متوجه شد در پنل کاربری ارسال کنندگان محصول با مسیر https://admin.instacart.com/api/v2/zones‌‌، به حمله CSRF آسیب پذیر بود در این صفحه درخواستی با متد POST برای بروز کردن منطقه فعالیتی کاربر در برنامه ارسال می‌شد‌‌.

به عنوان مثال نفوذگر می‌توانست با دستور html زیر‌‌، از این آسیب‌پذیری بهره‌برداری بنماید:

<iframe style="display:none" name="csrf-frame"></iframe>
<form method='POST' action="https://admin.instacart.com/api/v2/zones" target="csrf-frame" id="csrf-form">
<input type="hidden" name="zip" value="10001" />
<input type="hidden" name="override" value="true" />
<input type="submit" value="Submit request" />
</form>
<script>document.getElementById("csrf-form").submit()</script>

نفوذگر در این دستور از دو input مخفی برای ارسال مقادیر مورد نیاز درخواست استفاده می‌کند که مورد اول‌‌، پارامتر zip برای ارسال zip-code منطقه جغرافیایی کاربر و مورد دوم‌‌، پارامتر override مربوط به API می‌باشد که آن را برابر یا True قرار داده است.

همچنین نفوذگر از دستور iframe و اسکریپت نوشته شده‌‌، برای ارسال شدن درخواست بصورت خودکار توسط مرورگر قربانی استفاده کرده است.

در نتیجه‌‌، پس از باز شدن این صفحه در مرورگر قربانی‌‌، منطقه فعالیت کاربر در سایت instacart بدون آنکه متوجه بشود‌‌، قابل تغییر بود!

سناریو متد‌های دیگر

باید بپذیریم که آسیب‌پذیری CSRF با این سناریو به‌اندازه متد‌های GET و POST اتفاق نمی‌افتد. ولی دانستن آن خالی از لطف نیست و همچنین ممکن است از این موارد برای پایپس کردن بعضی از فیلتراسیون ها بهره گرفت.

فرض کنید یک برنامه کاربردی وب مربوط به بانک از متد PUT برای انتقال وجه 100 دلار به کاربر user در درخواست خود به شیوه زیر استفاده کند:

PUT http://bank.com/transfer.do HTTP/1.1
{ "acct":"user", "amount":100 }

نفوذگر با دیدن این درخواست متوجه می‌شود اطلاعات به صورت JSON منتقل می‌شود و احراز هویت بر اساس کوکی است. او برای ارسال درخواست جعلی از سمت کاربر دستور XHR زیر را ایجاد می‌کند:

<script>function put() {    var x = new XMLHttpRequest();    x.open("PUT","http://bank.com/transfer.do",true);    x.setRequestHeader("Content-Type", "application/json");    x.send(JSON.stringify({"acct":"attacker", "amount":100})); }</script> <body onload="put()"> 

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

همانطور که در ابتدا اشاره شد‌‌،شاید به دلیل استفاده نشدن این گونه متد ها در بسیاری از برنامه‌های وب‌‌، این آسیب‌پذیری با این روش رخ ندهد‌‌، اما لازم است تا با سناریو آن آشنا باشیم تا در مواقعی‌‌، بتوانیم فیلترها را با تغییر متد درخواست بایپس کنیم.

XHR یا XmlHttpRequest چیست؟

XHR یک API پراستفاده در فناوری Ajax برنامه‌های وب می‌باشد که به صورت یک Object در برنامه بکار می‌رود. این API برای ارسال و دریافت اطلاعات بین مرورگر و سرور به کار می‌رود. به طوری که بدون رفرش شدن صفحه ارسال و دریافت اطلاعات را انجام می‌دهد. به عنوان مثال بعد از نوشتن نام کاربری در فیلد مربوطه‌‌، وجود یا عدم وجود کاربر با نام نوشته شده با علامت تیک یا ضربدر در کنار فیلد مشخص می‌شود. همچنین مثال‌های دیگری از این API را می‌توان در برنامه‌های وب پویا مشاهده کرد.

ترکیب CSRF با حمله‌های دیگر

در ابتدا به این نکته اشاره شد که CSRF با روش‌های مهندسی اجتماعی برای کامل شدن حمله ترکیب می‌شود. اما در این بخش به روش‌هایی می‌پردازیم که با ترکیب شدن CSRF با حملات دیگر‌‌، علاوه بر بایپس فیلتراسیون و تدابیر امنیتی‌‌، باعث خطرناک‌تر شدن حمله می‌شود. البته مدنظر داشته باشید که حملات می‌توانند ترکیب‌های مختلفی داشته باشند‌‌، اما در این نوشتار به معرفی چند روش ادغام CSRF با آسیب‌پذیری‌های معروف‌‌، بسنده می‌کنیم:

حمله CSRF از طریق XSS

در این بخش سعی شده تا این سناریو با مثال واضح شرح داده شود اما برای بهتر متوجه شدن این بخش بهتر است که کمی‌با روش‌های حمله XSS هم آشنا باشید.

در یک برنامه وب آسیب پذیر به XSS‌‌، در کنار سناریو‌هایی که نفوذگر برای بهره برداری از این آسیب‌پذیری دارد‌‌، سناریو CSRF هم قابل بهره برداری است. جالب اینجاست که حمله ی CSRF در این سناریو‌‌، در هر دو روش Reflected XSS و Stored XSS قابل اجرا می‌باشد. در ادامه به مثالی از آن می‌پردازیم:

یک برنامه کاربردی وب در قسمت کامنت‌ها به باگ XSS از نوع Stored آسیب پذیر است. این به این معنی است که کد‌های جاوا اسکریپت نفوذگر در این بخش ذخیره و با بارگیری شدن صفحه، دستور جاوا اسکریپتی نوشته شده، در مرورگر کاربر‌‌ به صورت خودکار اجرا می‌شود. برای مثال نفوذگر قطعه کد زیر را در بخش کامنت ارسال می‌کند:

<script>
var req = new XMLHttpRequest(); 
req.onload = handleResponse; 
req.open('get','/my-account',true); 
req.send();
function handleResponse() {
    var token = this.responseText.match(/name="csrf" value="(\w+)"/)[1];
    var changeReq = new XMLHttpRequest(); 
    changeReq.open('post', '/my-account/change-pass', true);
    changeReq.send('csrf='+token+'&pass=123456')
};
</script>

کد جاوا اسکریپتی که نفوذگر از آن استفاده کرده‌‌، یک در خواست GET به برنامه ارسال می‌کند که به مسیر /my-account/change-pass فرستاده می‌شود. این درخواست نیاز به دو پارامتر pass و csrf دارد. پارامتر pass‌‌، رمز عبور جدید کاربر را تعیین میکند و پارامتر csrf‌‌، اشاره به csrf-token دارد که یک رشته کد متغیر می‌باشد که به ازای هر درخواست فرستاده می‌شود تا درخواست‌ها توسط کاربر و از داخل برنامه ارسال شود؛ ولی به دلیل باگ XSS و اجرا شدن دستور جاوا اسکریپت در برنامه‌‌، نفوذگر دستور مربوط به csrf-token را فراخوانی می‌کند تا به ازای هر قربانی که این درخواست را می‌فرستد‌‌، توکن معتبر برنامه هم ارسال شود.

در نتیجه‌‌، کاربرانی که صفحه‌ی شامل این قطعه کد را می‌بینند‌‌، رمز عبور آنها به 123456 تغییر می‌کند. پس همانطور که مشاهده می‌کنید‌‌، این حمله با ترکیب حمله XSS حتی از رویکرد امنیتی csrf-token که برای جلوگیری از CSRF تعیین شده بود هم عبور می‌کند.

این حمله چگونه کشف شد؟

یک مثال واقعی از این نوع حمله، می‌تواند نخستین باری باشد که این نوع حمله مشاهده شد. این حمله نخستین بار در تاریخ 4 اکتبر 2005‌‌، توسط یک بدافزار کرم(worm) به نام Samy در شبکه‌ی اجتماعی MySpace مشاهده شد. نتیجه‌ی حمله این بود که در عرض 20 ساعت‌‌، تصویر پروفایل بیش از 1 میلیون کاربر این شبکه‌ی اجتماعی به متن مقابل تغییر کرد:

but most of all, samy is my hero
که یعنی “اما بیش تر از همه‌‌، سامی ‌قهرمان من است”

همچنین افرادی که تحت تاثیر این حمله قرار گرفتند‌‌، بدون آنکه متوجه شوند یک درخواست دوستی به فردی با نام Samy فرستاده بودند و این فرد کسی نبود جز سامی‌کامکار.

4

سامی‌کامکار متولد 19 آذر 1364 یک محقق امنیتی‌‌، متخصص نفوذ رایانه و یک کارآفرین است. در خانواده‌ای اصالتا ایرانی در کشور آمریکا چشم به جهان گشود. ولی علارغم اینکه کامکار اصالت خودش را ایرانی می‌داند‌‌، در رسانه‌های خاجی اشاره‌ی زیادی به این موضوع نمی‌شود.

حمله CSRF و OpenRedirect

در صورتی که یک وب‌سایت دچار آسیب‌پذیری OpenRedirect باشد، در این صورت نفوذگر حملات متفاوتی را می‌تواند ترکیب کند. مثلا وب‌سایتی با دامنه example.com در مسیر :

https://example.com/?redirect_to=https://example2.com

به باگ openredirect آسیب پذیر است. شاید مانند مثال قبلی نفوذگر نتواند کد مخرب خود را به سایت تزریق بنماید اما فرض کنید این مسیر را به شیوه ی زیر تغییر دهد:

http://example.com/?redirect_to=

https://vulnerable.com/panel/change_pass?pass=123456

در این صورت فرد قربانی ممکن است با دیدن دامنه ی example.com و به قصد خواندن یک مطلب روی پیوند کلیک کند و وارد این صفحه شود‌‌، در این صورت رمزعبور او در سایت آسیب‌پذیری که در آن‌‌، حساب کاربری دارد به 123456 تغییر می‌کند. در واقع این روش را هم با کمک آسیب پذیری OpenRedirect می‌توان از روش‌های مهندسی اجتماعی حساب کرد.

امن سازی برنامه در برابر CSRF

در این قسمت به معرفی روش‌هایی که برای پیشگیری از این آسیب‌پذیری مورد استفاده قرار می‌گیرند می‌پردازیم :

از csrf-token در درخواست ها استفاده شود

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

روش synchronizer token pattern

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

روش Double Submit Cookie Pattern

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

در مرحله آخر سرور علاوه بر اعتبار سنجی کوکی نشست‌‌، توکن موجود در header درخواست را با توکن موجود در بدنه تطابق می‌دهد‌‌، و پس از اعتبارسنجی انتقال وجه انجام می‌شود.

حداقل از یک روش دفاع در عمق استفاده شود

در ادامه به چند روش دفاع در عمق برای جلوگیری از CSRF می‌پردازیم:

  • صفت SameSite در کوکی ها

SameSite یک صفت مانند Secure‌‌،HttpOnly و… در کوکی می‌باشد که هدف آن جلوگیری از حملات CSRF می‌باشد. این صفت به مرورگر کمک می‌کند تا متوجه شود که باید به ازای درخواست از یک سایت متفاوت، کوکی ذخیره شده در مرورگر را ارسال بنماید یا خیر. برای این صفت 3 مقدار Strict‌‌، Lax و None قابل استفاده‌اند.

مرورگر Chrome در نسخه‌های جدید خودش به صورت پیشفرض مقدار SameSite را برابر با Lax قرار می‌دهد که به واسطه‌ی آن کوکی ها قابلیت فرستاده شدن از وب‌سایت‌های شخص ثالثی را دارند اما فقط در صورت داشتن دو شرط زیر:

  • کاربر را از یک پیوند مشخص به وب‌سایت مدنظر مسیردهی بنمایند‌‌، نه از طریق iframe و مسیر imageکه از روش‌های CSRF هستند.
  • برای ارسال درخواست از متد GET و HEAD استفاده شود.

البته وب‌سایت ها می‌توانند کوکی خود را بنا بر حسب نیاز به None تغییر بدهند که هیچ مسیر دهی ای از وب‌سایت شخص ثالث انجام نشود.

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

  • دفاع مبتنی بر تعامل کاربر

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

برای اینکار می‌توانیم از گزینه‌های زیر بهره ببریم:

  • احراز هویت دو مرحله ای
  • توکن یکبار مصرف
  • استفاده از Captcha
  • تایید منبع درخواست با header ‌های استاندارد

برای اجرای این محدودیت دو قدم وجود دارد که هر دوی آنها بررسی header درخواست می‌باشند:

  • تشخیص سامانه ای که درخواست از سوی آن صادر شده است. (source origin) می‌تواند از طریق هدر Origin و Referer انجام شود.
  • تشخیص سامانه‌ای که درخواست به سمت آن میرود.(target origin)

بایپس‌های حمله CSRF

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

  • اعتبار سنجی نشدن CSRF Token با تغییر متد درخواست.
  • اعتبار سنجی نشدن CSRF Token با حذف پارامتر از درخواست
  • منطبق نبودن CSRF Token با کوکی نشست
  • دفاع در برابر CSRF فقط از طریق هدر Referer
  • اعتبار سنجی نشدن Referer در صورت نبودن آن
  • چک شدن دامنه در Referer به تنهایی
  • توکن دادن به کوکی در مسیر غلط

 

جمع بندی

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

منبع Portswigger.net Owasp.org Hackerone.com
مطالب مشابه
ارسال نظر

آدرس ایمیل شما منتشر نخواهد شد.