در این مقاله با Content Security Policy یا به اختصار CSP آشنا خواهیم شد. سپس در ادامه نحوه پیاده سازی و استفاده از آن را در Blazor بررسی می کنیم.

Content Security Policy چیست؟

CSP یکی از مکانیزم های امنیتی پیاده سازی شده در مرورگر های مدرن هست که به جلوگیری از حملاتی مانند XSS یا Cross-Site Scripting و data injection کمک می کند. این نوع حملات به جهت سرقت اطلاعات، deface کردن سایت، پخش بد‌افزار و … انجام می‌شوند. پیاده سازی CSP به گونه‌ای است که با مرورگر و وب سرور های قدیمی سازگار هست. بنابراین اگر یکی از طرفین از CSP پشتیبانی نکند، سایت بدون مشکل لود می شود و در این حالت، مرورگر به استفاده از مکانیزم امنیتی same-origin policy اکتفا می کند. CSP در مبحث دفاع در عمق بررسی میشود. بنابراین، نبودن آن به معنای آسیب پذیری نیست ولی پیاده سازی و استفاده صحیح از آن باعث افزایش امنیت میشود.

قبل از آشنایی بیشتر با CSP و same-origin policy بهتر هست با مفاهیم origin و same-origin آشنا شویم.

same-origin چیست؟

origin یک محتوای وب از ترکیب موارد زیر از URL آن بدست می آید :

  1. Scheme یا Protocol
  2. Hostname یا Domin
  3. Port

برای مثال در مورد آدرس  https://softamoz.com :

مقدار scheme برابر https و مقدار hostname برابر softamoz.com و مقدار port برابر ۴۴۳ (پورت پیشفرض https) هست. در صورتی که دو URL دارای origin یکسان باشند، same-origin نامیده میشوند. برای مثال https://subdomain.softamoz.com با URL فوق same-origin نیست! چون مقدار hostname این دو URL برابر نیستند. برای کسب اطلاعات بیشتر و مشاهده چندین نمونه، این لینک را مطالعه کنید.

در ادامه با نحوه عملکرد مکانیزم های امنیتی CSP و same-origin policy آشنا می شویم.

Content Security Policy چگونه کار می کند؟

زمانی که صفحه ای از یک وب‌سایت را درون مرورگر باز می کنیم، مرورگر بررسی می کند که اجازه اجرای چه کد هایی از JavaScript را دارد. این عمل شامل سایر Resource های صفحه همانند CSS ، تصاویر و … هم می شود. به عنوان توسعه دهنده سایت، با استفاده از CSP ، میتوانیم اطلاعاتی را در اختیار مرورگر قرار دهیم تا بتواند امکان لود و اجرای این Resource ها را بررسی کند. برای مثال میتوانیم به مرورگر بفهمانیم تنها فایل های JS لود شده از origin سایت ما اجرا شوند، یا inline CSS ها امکان اجرا نداشته باشند و … . به این شکل امکان اجرای script های مخرب تزریق شده به سایت کمتر شده و تا حدی جلوی حملات XSS (در صورت تنظیم صحیح CSP) گرفته می شود.

CSP به چه شکل پیاده سازی می شود؟

پیاده سازی CSP معمولا با یکی از دو روش زیر انجام می شود :

  1. استفاده از HTTP Response headers
  2. استفاده از تگ meta در HTML

مثالی از روش ۲:

<meta
  http-equiv="Content-Security-Policy"
  content="default-src 'self'; img-src https://*; child-src 'none';" />

برخی از امکانات مثل CSP violation reports فقط در روش اول امکان استفاده دارند. سینتکس کلی CSP در روش ۱ به این شکل هست :

Content-Security-Policy: <policy-directive>; <policy-directive>

یک یا چند هدر با عنوان Content-Security-Policy ایجاد و policy-directive ها به عنوان مقدار آن مشخص می شوند. هر policy-directive شامل <directive> <value> هست. در روش ۲ پراپرتی content حاوی policy-directive ها هست و http-equiv هم مقدار مشابه هدر یعنی Content-Security-Policy را دارد.

نوشتن یک CSP

یک CSP با مجموعه ای از directive ها نوشته می شود. هر یک از directive ها سیاست (policy) لود شدن resource را مشخص می کند. هر policy بهتر است شامل directive با نام default-src باشد که به نوعی fallback محسوب می شود و در صورتی که resource دارای policy نباشد، از default-src به عنوان پیشفرض استفاده شود. برای مطالعه بیشتر در مورد default-src روی این لینک کلیک کنید.

برای جلوگیری از امکان اجرای inline script ها و متد eval() میتوانیم policy شامل default-src یا script-src بنویسیم. همچنین برای جلوگیری از اجرای inline css ها از default-src یا style-src استفاده کنیم. directive های متعددی برای resource های مختلف مثلا فونت، ویدئو، صوت، frames و … وجود دارد. برای مشاهده لیست کاملی از directive ها و مثال های بیشتر به بخش منابع مقاله مراجعه کنید.

بررسی چند مثال

در این بخش، چندین مثال با دو روش ذکر شده در قسمت های قبل (http header و html meta tag) را بررسی خواهیم کرد.

Content-Security-Policy: default-src 'self'

در این مثال، تمامی resource ها فقط اجازه لود از origin سایت را دارند. این اجازه شامل subdomain نمی شود (در شروع مقاله مثالی از same-origin نبودن subdomain بررسی شد).

Content-Security-Policy: default-src 'self' example.com *.example.com

در این مثال، resource ها امکان لود و اجرا از origin خود سایت و همچنین دامنه و زیر دامنه های example.com را دارند.

Content-Security-Policy: default-src 'self'; img-src *; media-src example.org example.net; script-src userscripts.example.com

در این مثال، امکان لود تصاویر از تمامی origin ها وجود دارد. اما مدیا یعنی صدا و تصویر از example.org و example.net امکان لود شدن دارند. همچنین اسکریپت ها فقط از userscripts.example.com لود خواهند شد. همچنین default-src مشخص می کند که به صورت پیشفرض تمامی resource ها در صورت نداشتن policy خاص تنها از origin خود سایت لود شوند.

Content-Security-Policy: default-src https://onlinebanking.example.com

در این مثال، تمامی resource ها از https و همچنین آدرس ذکر شده لود خواهند شد.

<meta http-equiv="Content-Security-Policy" content="default-src https:" />

در این مثال inline یا eval های نا امن (unsafe inline/eval) اجازه‌ اجرا ندارند و تنها اجازه لود شدن resource ها از https وجود دارد.

Content-Security-Policy: default-src https: 'unsafe-eval' 'unsafe-inline'; object-src 'none'

در این مثال، اجازه اجرای inline منابع وجود داره.

برای مشاهده لیست کاملی از directive ها و مثال های بیشتر به این لینک و این لینک مراجعه کنید.

آشنایی مختصر با Same-origin policy

همانطور که در ابتدای مقاله ذکر شد، در صورتی که وب سرور یا مرورگر از CSP پشتیبانی نکند یا اصلا هدر یا متا تگ های مربوط به CSP وجود نداشته باشد، مرورگر به استفاده از مکانیزم امنیتی Same-origin policy اکتفا می کند و Content Security Policy را در نظر نمی گیرد. همچنین در مورد بررسی Same-origin بودن دو محتوای وب صحبت شد.

Same-origin policy یا به اختصار SOP مکانیزم امنیتی مهمی در مرورگر هست. این مکانیزم اجازه تعامل یک داکیومنت یا اسکریپت لود شده توسط یک origin با origin دیگر را کنترل می کند. بنابراین دسترسی احتمالی داکیومنت های مخرب به سایر origin ها را کمتر می کند. برای مثال اگر یک سایت مخرب را باز کنید و در این سایت کد JS در حال اجرا باشد که بخواهد داده های یک سایت دیگر را که احتمالا در آن سایت لاگین هستید، سرقت کند، SOP جلوی این عمل را می گیرد! اگر عامدانه بخواهیم دو origin متفاوت با همدیگر ارتباط داشته باشند، میتوانیم از روش هایی مانند CORS، JSONP و Post Message استفاده کنیم. در مقالات آینده در مورد SOP و CORS صحبت خواهیم کرد اما برای کسب اطلاعات بیشتر به این لینک ، این لینک و این لینک مراجعه کنید.

مکانیزم های CSP و SOP در برخی کاربرد ها همپوشانی دارند اما در نهایت عملکرد متفاوتی دارند. در صورت نبود CSP ، مرورگر فقط SOP را در نظر می گیرد، پس تنظیمات CORS نیز نقش فراوانی در امنیت سایت و کاربر دارد. توصیه می شود تنظیمات CSP و SOP به سختگیرانه ترین شکل ممکن انجام شود. در مورد SOP و CORS عملا سختگیرانه ترین حالت، تنظیم نکردن CORS هست که در این حالت تنها داکیومنت های Same-Origin با یکدیگر امکان ارتباط دارند.

Content Security Policy در Blazor

طبق داکیومنت مایکروسافت، در Blazor بهتر هست از directive های زیر استفاده کنید. همچنین به فراخور نیاز می توانید مواردی را به آن اضافه کنید.

Blazor WebAssembly:

<meta http-equiv="Content-Security-Policy" 
      content="base-uri 'self';
               default-src 'self';
               img-src data: https:;
               object-src 'none';
               script-src 'self'
                          'wasm-unsafe-eval';
               style-src 'self';
               upgrade-insecure-requests;">

Blazor Server:

<meta http-equiv="Content-Security-Policy" 
      content="base-uri 'self';
               default-src 'self';
               img-src data: https:;
               object-src 'none';
               script-src 'self';
               style-src 'self';
               upgrade-insecure-requests;">

در ادامه به بررسی directive های استفاده شده می پردازیم.

  • base-uri : مقدار URL تگ <base> را مشخص می کند. self یعنی همان origin سایت.
  • default-src : همانطور که قبلا صحبت شد. برای resource هایی که تنظیم خاصی در CSP برای آنها اعمال نشده. مقدار self یعنی تنها از origin سایت امکان لود و اجرا وجود داره.
  • img-src : منبع لود شدن تصاویر را مشخص می کند.
  • object-src : مقدار none یعنی تگ های <object> ، <embed> و <applet> امکان اجرا و لود ندارند.
  • script-src : منبع لود شدن اسکریپت ها را مشخص می کند. مقدار self یعنی origin سایت. مقدار wasm-unsafe-eval هم امکان اجرای Mono Runtime را فراهم می کند.
  • style-src : مقدار self امکان لود و اجرای style های لود شده از origin سایت را فراهم می کند. در صورتی که از inline css استفاده کرده باشید، باید با افزودن unsafe-inline اجازه اجرای آن را بدهید.
  • upgrade-insecure-requests : تمامی آدرس های http را با https جایگزین می کند.

تگ meta در مثال های بالا در head فایل index.html در Blazor WebAssembly و در head فایل Host.cshtml_ در Blazor Server قرار میگیرد.

CSP در ۸ NET. و Blazor

در NET 8 Preview 5. تنظیمات CSP تغییری داشته و نیازی به استفاده از unsafe-eval در نسخه وب اسمبلی بلیزر نیست.

منابع و مطالعه بیشتر

Content-Security-Policy Header ⟶ CSP Reference & Examples

Origin – MDN Web Docs Glossary: Definitions of Web-related terms | MDN (mozilla.org)

Content Security Policy (CSP) – HTTP | MDN (mozilla.org)

Content-Security-Policy – HTTP | MDN (mozilla.org)

CSP: default-src – HTTP | MDN (mozilla.org)

CSP: script-src – HTTP | MDN (mozilla.org)

CSP: style-src – HTTP | MDN (mozilla.org)

Same-origin policy – Web security | MDN (mozilla.org)

Cross-Origin Resource Sharing (CORS) – HTTP | MDN (mozilla.org)

CORS – MDN Web Docs Glossary: Definitions of Web-related terms | MDN (mozilla.org)

What is the difference between CORS and CSP

Enforce a Content Security Policy for ASP.NET Core Blazor | Microsoft Learn

ASP.NET Core updates in .NET 8 Preview 5 – .NET Blog (microsoft.com)

Microsoft Designer – Stunning designs in a flash (تصویر پست)