;...z@nko!#
;...z@nko!#
خواندن ۸ دقیقه·۱ سال پیش

🎗 برسی CORS Policy سمت سرور و بک اند ❄️


CORS
CORS


🪽 سلام به همگی! به اون افرادی که لذت میبرن از شکافتن لایه های ابسترکت و عمیق شدن 🦔

تو این مقاله میخوایم راجب CORS Policy حرف بزنیم و ببینیم کلا چی هستش، چرا از نظر امنیتی مهمه و اگر با ارور های مربوط به CORS Policy بخورد کردیم چطوری دیباگ کنیم. جنبه های مختلفش رو برسی مکنیم تا درک خیلی بهتری ازش پیدا بکنیم. این مقاله شامل موضوعات زیر میشه:

  • توضیح کوتاهی راجب SOP.
  • برسی اینکه CORS چی هستش و موارد بیسیک.
  • از نظر امنیتی چرا CORS اهمیت داره و برسی flow کلی.
  • برسی هدر هایی مربوط به CORS.
  • نگاهی به CORS داخل جنگو و نحوه دیباگ کردن ارور های مربوط بهش.



SOP(Same-origin policy)

قبل از CORS بیاید یکم راجب SOP حرف بزنیم، SOP یه مکانیزم امنیتی هستش برای جلوگیری از یه سری اتک مثل CSRF که به صورت دیفالت داخل مروگر ها اعمال شده، وقتی ما سایت x رو باز میکنیم داخل این سایت میتونیم به همین origin فعلی درخواست بفرستیم و مکانیزم SOP مشکلی با این عملکرد نداره، ولی اگر بیایم از origin X درخواست بفرستیم به origin Y اینجا هستش که SOP به ما گیر میده و ارور های مربوط به CORS Policy میده، و اجازه نمیده درخواست مون ارسال بشه و به دیتای origin دیگه دسترسی داشته باشیم.

فرض کنید یه هکر بیاد یه سیات مخرب ایجاد بکنه و یه کد js داخل سایت باشه که وقتی کاربر سایت رو باز میکنه این کد js اجرا بشه، حالا اگر کاربر داخل سایت y لایگن باشه اینجا وقتی سایت هکر رو باز میکنه درخواست از سمت اون به سایت y فرستاده میشه(بر فرض اینکه هکر سایت y رو میدونه...) و ریسپانس درخواست برگشت داده میشه به هکر و اون میتونه به دیتا دسترسی داشته باشه که این امن نیست، برای همین SOP بوجود اومد تا دسترسی رو محدود بکنه(تو قسمت مربوط به security بیشتر برسی میکنیم).

origin
origin

نکته: وقتی میگیم origin منظور مون مبدا درخواست هستش، خود origin شامل 3 بخش میشه که داخل تصویر بالا میتونید مشاهد کنید.




CORS(Cross-Origin Resource Sharing) Mechanism?

بالاتر گفتیم SOP چی هستش و چه کاری انجام میده، ولی بعضی وقتا نیاز هستش که به بعضی از origin ها دسترسی بدیم، مثلا سمت فرانت اند درخواست با یه origin دیگه به backend ارسال میشه، یا اگر از OAuth اتنتیکیشن استفاده کرده باشیم گوگل و... نیاز دارن که یه سری تعاملات با origin ما داشته باشن و سرویس های دیگه...، اینجا هستش که CORS وارد ماجرا میشه و همونطور که از اسمش پیداست یعنی اشتراک گذاشتن دیتای یه origin با origin های دیگه، این هم یه مکانیزم دیگه هستش که بر اساس هدر های http تشخیص میده که یه origin اجازه ارسال درخواست به origin ما رو داره یا نه، مثل SOP دیفالت داخل مروگر ها هستش و اعمال میشه،‌ وقتی از یه origin دیگه درخواست میفرستید اول یه درخواست prefight رو میفرسته تا ببینه origin دیگه اجازه تعامل باهاش رو میده یا نه و بعد اگر داخل header ها تایید کرده بود ادامه درخواست ها رو میفرسته و...

نکته: داخل مرورگر وقتی از origin X درخواست رو برای origin Y میفرستیم اول یه ریکوئست از نوع OPTION ارسال میشه که بهش میگن "Preflight request"، این درخواست میره تا بدونه بک اند پالیسی خاصی برای هدر های CORS تایین کرده یا نه، مثلا بک اند شاید یه سری اجازه ها رو داده باشه(در قسمت هدر ها بیشتر میگیم) و اگر بک اند اجازه ای نداده باشه و... اینجا مروگر میاد به کاربر CORS Policy ERR میده.




Understanding CORS Security

فرض کنید یه سری کاربر داخل سایت ما(shop.com) لاگین کردن و دربک اند براشون سشن ایجاد شده( درواقع authenticate شدن)، این وسط یه هکر هم وجود داره که یه وبسایت فیک بالا اورده، مثلا test.com و داخل سایتش یه کد js وجود داره که وقتی صفحه وبسایت باز میشه این js ران میشه، داخل عکس میتونید flow کلی رو ببینید:

flow
flow


داخل تصویر بالا همونطور که میبینید تو استپ 1 و 2 یوزر اول سایت test.com رو باز کرده بعد کد js ران شده و درخواست رو فرستاده به shop.com و چون origin متفاوت هستش میاد اول درخواست prefight میفرسته تا ببینه سرور بهش اجازه ارسال درخواست اصلی رو میده یا نه، تو استپ 3 بک اند اگر درست کانفیگ نشده باشه و.. به همه اجازه میده، اینجا اگر اجازه بده میره مرحله 4 و درغیر اینصورت ریکوئست ارور CORS Policy میگیره.

تو استپ 4 میاد درخواست اصلی اجرا میشه که میتونه درخواست به سمت هر endpointی باشه و... اینجا هکر میتونه پارامتر credintial=True رو هم داخل درخواست تو js قرار بده که اینشکلی از قابلیت ارسال اتوماتیک داده های مربوط به اعتبار سنجی از سمت مرورگر استفاده میشه: کاربر داخل سایت shop.com لاگین هستش پس هنوز سشنس داخل لوکال استوریج وجود داره و اینجا هستش که از قابلیت دیفالت مروگر استفاده میشه و زمان درخواست از اینجا سشن رو برمیداره مرورگر و با درخواست میفرسته سمت بک اند، درواقع مثل این میمونه که کاربر درخواست رو فرستاده باشه نه هکر.

تو استپ 5 بک اند میاد برای کاربر یه response برمیگردونه که این باز برمیگرده به هکر و اون میتونه به دیتا دسترسی داشته باشه همچنین داخل این ریسپانس تو headers یه set-cookie هستش که مربوط به کاربر و هکر میتونه بهش دسترسی پیدا کنه و با همین به سشن کاربر لاگین کنه و...




CORS Headers

همونطور که گفتیم بر اساس هدر هایی که از سمت بک اند درجواب ریکوئست prefight میاد مشخص میشه چه دسترسی های رو داده به origin دیگه، ما یه سری Header میتونیم ست بکنیم سمت بک اند که درجواب درخواست prefight ارسال میشه:

Base: Access-Control-Allow-Origin: <origin> | *
Ex: Access-Control-Allow-Origin: https://google.com, https://virgool.io

داخل این هدر مشخص میکنیم که کدوم origin ها اجازه دسترسی رو دارن، میتونیم از * استفاده کنیم که یعنی همه origin ها و این اصلا پیشنهاد نمیشه(بعضی جاها از regex هم پشتیبانی میکنن یا مینویسین که اون هم پیشنهاد نمیشه مگر اینکه مطمن باشید که چی مینویسید)، بهتر که origin های مورد نیاز رو فقط اضافه کنید.

.

Base: Access-Control-Expose-Headers: <header-name>[, <header-name>]*
Ex: Access-Control-Expose-Headers: x,y,z

این هدر مشخص میکنه که کلاینت(مروگر) به چه هدر هایی دسترسی داشته باشه، به صورت پیشفرض وقتی از یه origin دیگه ریسپانس میاد فقط به هدر هایی مثل Cache-Control، Content-Language و Content-Type دسترسی داره کلاینت. اگر ما بخوایم هدر هایی دیگه ای رو هم دسترسی داشته باشه مثل مورد x,y,z تعریف میکنیم.
.

Base: Access-Control-Max-Age: <delta-seconds>
Ex: Access-Control-Max-Age: 30

داخل این هدر میتونیم مشخص بکنیم که تا چه مدت مروگر درخواست prefight رو با هر ریکوئست نفرسته، یعنی اولین بار میفرسته و درخواست های بعدی دیگه نمیفرسته تا اون n ثانیه تموم بشه بعدش یه درخواست prefight دیگه میفرسته.
.

Base: Access-Control-Allow-Credentials: true | false
Ex: Access-Control-Allow-Credentials: true

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

.

Base: Access-Control-Allow-Methods: * | post, put, get, patch, delete
Ex: Access-Control-Allow-Methods: get

اینجا متود هایی که اجازه دارن رو تایین میکنیم مثلا الان گفتیم درخواست get رو فقط از allow origin ها قبول کن و هر متود دیگه ای که بیاد ارور CORS Policy میگیره.
.

Base: Access-Control-Allow-Headers: <header-name>[, <header-name>]*
Ex: Access-Control-Allow-Headers: custom_header

بالاتر یه Access-Control-Expose-Headers داشتیم اونجا یه سری هدر ست میکردیم که کلاینت دسترسی داشته باشه بهش از داخل response، ولی اینجا یه سری هدر مشخص میکنیم که کلاینت بتونه بفرسته، یعنی غیر اگر غیر از هدر های که ما گفتیم رو بفرسته کلاینت بهش ارور CORS بده ( اگر هدر کاستومی داشته باشیم باید اینجا اضافه کنیم در غیر اینصورت پیشفرض Deny میشه)‌.

نکته : هدر های access-control-request-private-network و access-control-allow-private-networ قبلا برای دست رسی دادن به شبکه پرایویت وجود داشتن که در ورژن جدید مروگر ها غیر فعال شدن، مگر اینکه خودتون فعال کنید.




Django CORS & DEBUG

داخل جنگو میتونیم همه موارد گفته شده رو با پکیج django-cors-headers هندل بکنیم که خیلی ساده و راحت هستش، کافیه مواردی که داخل لینک بالا گفته رو انجام بدیم تا اعمال بشه. داخل فریمورک های دیگه هم باید ماژول هایی برای این وجود داشته باشه و اگر هم وجود نداشت کافیه داخل هدر ریسپانس برای درخواست prefight اون موارد مورد نیاز رو قرار بدید تا اوکی بشه.

برای دیباگ کردن ارور های مربوط به CORS اگر تب مربوط به network مروگر رو چک بکنید اونجا میتونید وضعیت درخواست رو ببینید و اگر ارور دریافت کرده باشید و faield شده باشه میتونید برید داخل تب console اونجا با جزئیات کامل تری ارور هستش، مثلا ممکنه ارور داده باشه که این origin داخل allow origin ها نیستش یا دست رسی لازم برای فلان هدر و متود ها داده نشده از سمت بک اند و... در کل برای حل ارور ها اگر هدر هایی که بالاتر توضیح دادیم رو استفاده کنید میتونید خیلی راحت دیباگ کنید.


همچنین اگر زمانی اومدید با پکیج django-cors-headers هدر ها و موارد مورد نیاز تون رو ست کردید ولی همچنان مشکل داشت میتونید ریسپانس اون ریکوئست OPTION که فرستاده میشه رو برسی کنید ببینید واقعا سرور داره اون هدر ها و مواردی که ست کردید رو برمیگردونه یا نه؟ و میتونید وبسرور رو هم چک کنید (اگر مثلا از nginx یا apache و.. استفاده میکنید).



خب دوستان امید وارم توضیحات کافی و خوبی رو داده باشم و دید بهتری از CORS Policy پیدا کرده باشید و اگر به ارور های مربوط بهش برخورد کردید بتونید راحت دیباگ کنید و مناسب ترین تصمیم رو بگیرید.

مرسی که تا اینجا خوندید، اگر داخل پست مشکلی وجود داشت یا چیزی به اشتباه گفت شده بود و یا می تونست بهتر باشه خوشحال میشم کامنت بزارید، چاکس ❤️




Links :

https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#the_http_response_headers

https://portswigger.net/web-security/cors

https://owasp.org/www-community/attacks/CORS_OriginHeaderScrutiny

https://cheatsheetseries.owasp.org/cheatsheets/HTTP_Headers_Cheat_Sheet.html

https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy

djangosecurityhttpامنیت
یه بک اند دولوپر پایتون، علاقمه مند به DevOps و دیپ شدن در مباحث مرتبط "-) https://mastodon.social/@zankoAN
شاید از این پست‌ها خوشتان بیاید