کاهش اسکریپت بین سایتی (XSS) با یک خط مشی امنیتی سختگیرانه محتوا (CSP)

پشتیبانی مرورگر

  • کروم: 52.
  • لبه: 79.
  • فایرفاکس: 52.
  • سافاری: 15.4.

منبع

برنامه نویسی متقابل سایت (XSS) ، توانایی تزریق اسکریپت های مخرب به یک برنامه وب، یکی از بزرگترین آسیب پذیری های امنیتی وب برای بیش از یک دهه بوده است.

سیاست امنیتی محتوا (CSP) یک لایه امنیتی اضافه شده است که به کاهش XSS کمک می کند. برای پیکربندی یک CSP، سربرگ Content-Security-Policy HTTP را به یک صفحه وب اضافه کنید و مقادیری را تنظیم کنید که کنترل کند عامل کاربر چه منابعی را برای آن صفحه بارگذاری کند.

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

اصطلاح کلیدی: nonce یک عدد تصادفی است که فقط یک بار استفاده می شود و می توانید از آن برای علامت گذاری یک تگ <script> به عنوان مورد اعتماد استفاده کنید.

اصطلاح کلیدی: تابع هش یک تابع ریاضی است که یک مقدار ورودی را به یک مقدار عددی فشرده به نام هش تبدیل می‌کند. شما می توانید از یک هش (به عنوان مثال SHA-256 ) برای علامت گذاری یک تگ <script> درون خطی به عنوان مورد اعتماد استفاده کنید.

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

چرا باید از CSP سختگیرانه استفاده کنید؟

اگر سایت شما قبلاً دارای یک CSP شبیه script-src www.googleapis.com ، احتمالاً در برابر متقابل سایت مؤثر نیست. به این نوع CSP، CSP لیست مجوز می گویند. آنها نیاز به سفارشی سازی زیادی دارند و مهاجمان می توانند از آنها عبور کنند .

CSPهای سختگیرانه مبتنی بر nonces یا هش رمزنگاری از این تله ها جلوگیری می کنند.

ساختار دقیق CSP

یک خط‌مشی امنیتی سختگیرانه محتوا از یکی از سرصفحه‌های پاسخ HTTP زیر استفاده می‌کند:

CSP سختگیرانه غیر مبتنی بر

Content-Security-Policy:
  script-src 'nonce-{RANDOM}' 'strict-dynamic';
  object-src 'none';
  base-uri 'none';
یک CSP سختگیرانه غیر مبتنی بر چگونه کار می کند.

CSP سختگیرانه مبتنی بر هش

Content-Security-Policy:
  script-src 'sha256-{HASHED_INLINE_SCRIPT}' 'strict-dynamic';
  object-src 'none';
  base-uri 'none';

ویژگی های زیر یک CSP مانند این را "سخت" و در نتیجه ایمن می کند:

  • از nonces 'nonce-{RANDOM}' یا هش 'sha256-{HASHED_INLINE_SCRIPT}' استفاده می‌کند تا نشان دهد توسعه‌دهنده سایت به کدام برچسب <script> اعتماد دارد تا در مرورگر کاربر اجرا شود.
  • 'strict-dynamic' را تنظیم می کند تا تلاش برای استقرار یک CSP غیر مبتنی بر هش را با اجازه دادن خودکار به اجرای اسکریپت هایی که یک اسکریپت قابل اعتماد ایجاد می کند، کاهش دهد. این همچنین استفاده از اکثر کتابخانه ها و ویجت های جاوا اسکریپت شخص ثالث را از حالت انسداد خارج می کند.
  • این بر اساس لیست های مجاز URL نیست، بنابراین از دور زدن های معمول CSP رنج نمی برد.
  • این اسکریپت های درون خطی غیرقابل اعتماد مانند کنترل کننده رویداد درون خطی یا javascript: URI ها را مسدود می کند.
  • object-src برای غیرفعال کردن پلاگین های خطرناک مانند Flash محدود می کند.
  • base-uri برای جلوگیری از تزریق تگ های <base> محدود می کند. این مانع از تغییر مکان اسکریپت های بارگیری شده از URL های نسبی توسط مهاجمان می شود.

یک CSP سختگیرانه را اتخاذ کنید

برای اتخاذ یک CSP سختگیرانه، باید:

  1. تصمیم بگیرید که آیا برنامه شما باید یک CSP غیر یک یا هش تنظیم کند.
  2. CSP را از بخش ساختار Strict CSP کپی کنید و آن را به عنوان یک هدر پاسخ در برنامه خود تنظیم کنید.
  3. Refactor قالب های HTML و کد سمت سرویس گیرنده برای حذف الگوهای ناسازگار با CSP.
  4. CSP خود را مستقر کنید.

می‌توانید از Lighthouse (نسخه 7.3.0 و بالاتر با flag --preset=experimental ) در طول این فرآیند استفاده کنید تا بررسی کنید که آیا سایت شما دارای CSP است یا خیر ، و آیا به اندازه کافی سختگیرانه است که در برابر XSS مؤثر باشد.

گزارش Lighthouse هشدار می دهد که هیچ CSP در حالت اجرا یافت نمی شود.
اگر سایت شما CSP ندارد، Lighthouse این هشدار را نشان می دهد.

مرحله 1: تصمیم بگیرید که آیا به یک CSP غیر مبتنی بر هش نیاز دارید یا خیر

در اینجا نحوه عملکرد دو نوع CSP سختگیرانه آمده است:

CSP غیر مبتنی بر

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

برای صفحات HTML ارائه شده بر روی سرور از یک CSP غیر مبتنی بر استفاده کنید. برای این صفحات، می توانید برای هر پاسخ یک عدد تصادفی جدید ایجاد کنید.

CSP مبتنی بر هش

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

از یک CSP مبتنی بر هش برای صفحات HTML که به صورت ایستا ارائه می شوند یا صفحاتی که نیاز به کش دارند استفاده کنید. برای مثال، می‌توانید از یک CSP مبتنی بر هش برای برنامه‌های وب تک صفحه‌ای که با فریم‌ورک‌هایی مانند Angular، React یا موارد دیگر ساخته شده‌اند، استفاده کنید که به‌صورت ایستا و بدون رندر سمت سرور ارائه می‌شوند.

مرحله 2: یک CSP سختگیرانه تنظیم کنید و اسکریپت های خود را آماده کنید

هنگام تنظیم یک CSP، چند گزینه دارید:

  • حالت فقط گزارش ( Content-Security-Policy-Report-Only ) یا حالت اجرایی ( Content-Security-Policy ). در حالت فقط گزارش، CSP هنوز منابع را مسدود نمی کند، بنابراین هیچ چیز در سایت شما خراب نمی شود، اما می توانید خطاها را ببینید و برای هر چیزی که مسدود شده بود گزارش دریافت کنید. به صورت محلی، وقتی CSP خود را تنظیم می کنید، این واقعاً مهم نیست، زیرا هر دو حالت خطاهای موجود در کنسول مرورگر را به شما نشان می دهند. در هر صورت، حالت اجرا می تواند به شما کمک کند منابعی را که بلوک های پیش نویس CSP خود را پیدا می کنید، پیدا کنید، زیرا مسدود کردن یک منبع می تواند صفحه شما را شکسته به نظر برساند. حالت فقط گزارش بعداً در این فرآیند بسیار کاربردی می شود ( مرحله 5 را ببینید).
  • هدر یا تگ <meta> HTML. برای توسعه محلی، یک تگ <meta> می تواند برای بهینه سازی CSP شما و مشاهده سریع تاثیر آن بر سایت شما راحت تر باشد. با این حال:
    • بعداً، هنگام استقرار CSP خود در تولید، توصیه می کنیم آن را به عنوان یک هدر HTTP تنظیم کنید.
    • اگر می‌خواهید CSP خود را در حالت فقط گزارش تنظیم کنید، باید آن را به عنوان یک هدر تنظیم کنید، زیرا متا تگ‌های CSP از حالت فقط گزارش پشتیبانی نمی‌کنند.

گزینه A: CSP غیر مبتنی بر

هدر پاسخ HTTP Content-Security-Policy زیر را در برنامه خود تنظیم کنید:

Content-Security-Policy:
  script-src 'nonce-{RANDOM}' 'strict-dynamic';
  object-src 'none';
  base-uri 'none';

یک nonce برای CSP ایجاد کنید

Nonce یک عدد تصادفی است که فقط یک بار در هر بارگذاری صفحه استفاده می شود. یک CSP مبتنی بر غیرانس تنها زمانی می تواند XSS را کاهش دهد که مهاجمان نتوانند مقدار nonce را حدس بزنند. یک nonce CSP باید باشد:

  • یک مقدار تصادفی رمزنگاری قوی (طول ایده آل 128+ بیت)
  • برای هر پاسخی که به تازگی تولید شده است
  • Base64 کدگذاری شده است

در اینجا چند نمونه از نحوه اضافه کردن یک CSP nonce در چارچوب های سمت سرور آورده شده است:

const app = express();

app.get('/', function(request, response) {
  // Generate a new random nonce value for every response.
  const nonce = crypto.randomBytes(16).toString("base64");

  // Set the strict nonce-based CSP response header
  const csp = `script-src 'nonce-${nonce}' 'strict-dynamic'; object-src 'none'; base-uri 'none';`;
  response.set("Content-Security-Policy", csp);

  // Every <script> tag in your application should set the `nonce` attribute to this value.
  response.render(template, { nonce: nonce });
});

یک ویژگی nonce به عناصر <script> اضافه کنید

با یک CSP مبتنی بر nonce، هر عنصر <script> باید دارای یک ویژگی nonce باشد که با مقدار nonce تصادفی مشخص شده در هدر CSP مطابقت داشته باشد. همه اسکریپت ها می توانند nonce یکسانی داشته باشند. اولین قدم این است که این ویژگی ها را به همه اسکریپت ها اضافه کنید تا CSP به آنها اجازه دهد.

گزینه B: سربرگ پاسخ CSP مبتنی بر هش

هدر پاسخ HTTP Content-Security-Policy زیر را در برنامه خود تنظیم کنید:

Content-Security-Policy:
  script-src 'sha256-{HASHED_INLINE_SCRIPT}' 'strict-dynamic';
  object-src 'none';
  base-uri 'none';

برای چند اسکریپت درون خطی، نحو به شرح زیر است: 'sha256-{HASHED_INLINE_SCRIPT_1}' 'sha256-{HASHED_INLINE_SCRIPT_2}' .

اسکریپت های منبع را به صورت پویا بارگیری کنید

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

نمونه ای از نحوه درون خط کردن اسکریپت های خود.
توسط CSP مجاز است
<script>
  var scripts = [ 'https://example.org/foo.js', 'https://example.org/bar.js'];

  scripts.forEach(function(scriptUrl) {
    var s = document.createElement('script');
    s.src = scriptUrl;
    s.async = false; // to preserve execution order
    document.head.appendChild(s);
  });
</script>
برای اینکه اجازه دهید این اسکریپت اجرا شود، باید هش اسکریپت درون خطی را محاسبه کرده و آن را به سرصفحه پاسخ CSP اضافه کنید و جایگزین مکان‌دار {HASHED_INLINE_SCRIPT} شود. برای کاهش تعداد هش ها، می توانید تمام اسکریپت های درون خطی را در یک اسکریپت ادغام کنید. برای مشاهده عملی آن، به این مثال و کد آن مراجعه کنید.
توسط CSP مسدود شده است
<script src="https://example.org/foo.js"></script>
<script src="https://example.org/bar.js"></script>
CSP این اسکریپت ها را مسدود می کند زیرا فقط اسکریپت های درون خطی را می توان هش کرد.

ملاحظات بارگیری اسکریپت

مثال اسکریپت درون خطی s.async = false را اضافه می کند تا اطمینان حاصل شود که foo قبل از bar اجرا می شود، حتی اگر bar ابتدا بارگیری شود. در این قطعه، s.async = false هنگام بارگیری اسکریپت ها تجزیه کننده را مسدود نمی کند، زیرا اسکریپت ها به صورت پویا اضافه می شوند. تجزیه کننده فقط در حین اجرای اسکریپت ها متوقف می شود، همانطور که برای اسکریپت های async انجام می شود. با این حال، با این قطعه، به خاطر داشته باشید:

  • ممکن است یک یا هر دو اسکریپت قبل از پایان دانلود سند اجرا شوند. اگر می خواهید سند تا زمان اجرای اسکریپت ها آماده شود، قبل از اینکه اسکریپت ها را اضافه کنید منتظر رویداد DOMContentLoaded باشید. اگر این باعث مشکل در عملکرد می شود زیرا اسکریپت ها به اندازه کافی زود دانلود نمی شوند، از برچسب های پیش بارگذاری زودتر در صفحه استفاده کنید.
  • defer = true کاری نمی کند. اگر به آن رفتار نیاز دارید، اسکریپت را در صورت نیاز به صورت دستی اجرا کنید.

مرحله 3: الگوهای HTML و کد سمت مشتری را Refactor کنید

کنترل‌کننده‌های رویداد درون خطی (مانند onclick="…" , onerror="…" ) و URI‌های جاوا اسکریپت ( <a href="javascript:…"> ) می‌توانند برای اجرای اسکریپت‌ها استفاده شوند. این بدان معناست که مهاجمی که باگ XSS را پیدا می‌کند می‌تواند این نوع HTML را تزریق کرده و جاوا اسکریپت مخرب را اجرا کند. یک CSP غیر مبتنی بر هش استفاده از این نوع نشانه گذاری را ممنوع می کند. اگر سایت شما از هر یک از این الگوها استفاده می کند، باید آنها را به جایگزین های ایمن تر تبدیل کنید.

اگر CSP را در مرحله قبل فعال کرده باشید، هر بار که CSP یک الگوی ناسازگار را مسدود می کند، می توانید نقض CSP را در کنسول مشاهده کنید.

گزارش نقض CSP در کنسول برنامه‌نویس Chrome.
خطاهای کنسول برای کد مسدود شده

در بیشتر موارد، راه حل ساده است:

کنترل کننده رویداد درون خطی Refactor

توسط CSP مجاز است
<span id="things">A thing.</span>
<script nonce="${nonce}">
  document.getElementById('things').addEventListener('click', doThings);
</script>
CSP به گردانندگان رویداد اجازه می دهد که با استفاده از جاوا اسکریپت ثبت شوند.
توسط CSP مسدود شده است
<span onclick="doThings();">A thing.</span>
CSP کنترل کننده های رویداد درون خطی را مسدود می کند.

Refactor javascript: URIs

توسط CSP مجاز است
<a id="foo">foo</a>
<script nonce="${nonce}">
  document.getElementById('foo').addEventListener('click', linkClicked);
</script>
CSP به گردانندگان رویداد اجازه می دهد که با استفاده از جاوا اسکریپت ثبت شوند.
توسط CSP مسدود شده است
<a href="javascript:linkClicked()">foo</a>
CSP جاوا اسکریپت را مسدود می کند: URI ها.

eval() از جاوا اسکریپت خود حذف کنید

اگر برنامه شما از eval() برای تبدیل سریال‌سازی‌های رشته‌های JSON به اشیاء JS استفاده می‌کند، باید چنین نمونه‌هایی را به JSON.parse() تبدیل کنید، که سریع‌تر نیز است.

اگر نمی‌توانید همه استفاده‌های eval() را حذف کنید، همچنان می‌توانید یک CSP غیرمبتنی سخت تنظیم کنید، اما باید از کلمه کلیدی CSP 'unsafe-eval' استفاده کنید که باعث می‌شود خط‌مشی شما کمی ایمن‌تر شود.

شما می‌توانید این و نمونه‌های بیشتری از این نوع refactoring را در این کد CSP سخت‌گیرانه بیابید:

مرحله 4 (اختیاری): برای پشتیبانی از نسخه های قدیمی مرورگر، نسخه های جایگزین اضافه کنید

پشتیبانی مرورگر

  • کروم: 52.
  • لبه: 79.
  • فایرفاکس: 52.
  • سافاری: 15.4.

منبع

اگر نیاز به پشتیبانی از نسخه های قدیمی مرورگر دارید:

  • استفاده از strict-dynamic مستلزم افزودن https: به عنوان نسخه بازگشتی برای نسخه های قبلی سافاری است. وقتی این کار را انجام می دهید:
    • همه مرورگرهایی که از strict-dynamic پشتیبانی می‌کنند https: بازگشتی را نادیده می‌گیرند، بنابراین این امر قدرت سیاست را کاهش نمی‌دهد.
    • در مرورگرهای قدیمی، اسکریپت‌های با منبع خارجی تنها در صورتی می‌توانند بارگیری شوند که از منبع HTTPS باشند. این امنیت کمتر از یک CSP سختگیرانه است، اما همچنان از برخی دلایل رایج XSS مانند تزریق javascript: URIها جلوگیری می کند.
  • برای اطمینان از سازگاری با نسخه‌های مرورگر بسیار قدیمی (4 سال به بالا)، می‌توانید به‌عنوان نسخه‌ی بازگشتی unsafe-inline اضافه کنید. همه مرورگرهای اخیر در صورت وجود یک CSP nonce یا هش، از unsafe-inline چشم پوشی می کنند.
Content-Security-Policy:
  script-src 'nonce-{random}' 'strict-dynamic' https: 'unsafe-inline';
  object-src 'none';
  base-uri 'none';

مرحله 5: CSP خود را مستقر کنید

پس از تأیید اینکه CSP شما هیچ اسکریپت قانونی را در محیط توسعه محلی شما مسدود نمی کند، می توانید CSP خود را در مرحله مرحله بندی و سپس در محیط تولید خود مستقر کنید:

  1. (اختیاری) با استفاده از هدر Content-Security-Policy-Report-Only CSP خود را در حالت گزارش فقط اجرا کنید. حالت فقط گزارش برای آزمایش یک تغییر بالقوه شکست مانند یک CSP جدید در تولید قبل از شروع به اجرای محدودیت‌های CSP مفید است. در حالت فقط گزارش، CSP شما بر رفتار برنامه‌تان تأثیر نمی‌گذارد، اما مرورگر همچنان وقتی با الگوهای ناسازگار با CSP شما مواجه می‌شود، خطاهای کنسول و گزارش‌های تخلف ایجاد می‌کند، بنابراین می‌توانید ببینید چه چیزی برای کاربران نهایی شما خراب می‌شود. برای اطلاعات بیشتر، گزارش API را ببینید.
  2. وقتی مطمئن هستید که CSP شما سایت شما را برای کاربران نهایی شما خراب نمی کند، CSP خود را با استفاده از هدر پاسخ Content-Security-Policy گسترش دهید. توصیه می کنیم CSP خود را با استفاده از هدر HTTP سمت سرور تنظیم کنید زیرا از تگ <meta> ایمن تر است. پس از تکمیل این مرحله، CSP شما شروع به محافظت از برنامه شما در برابر XSS می کند.

محدودیت ها

یک CSP سختگیرانه به طور کلی یک لایه امنیتی قوی اضافه می کند که به کاهش XSS کمک می کند. در بیشتر موارد، CSP با رد الگوهای خطرناک مانند javascript: URI، سطح حمله را به میزان قابل توجهی کاهش می دهد. با این حال، بر اساس نوع CSP که استفاده می کنید (nonces، هش، با یا بدون 'strict-dynamic' )، مواردی وجود دارد که CSP از برنامه شما نیز محافظت نمی کند:

  • اگر یک اسکریپت ندارید، اما مستقیماً به بدنه یا پارامتر src آن عنصر <script> تزریق شده است.
  • اگر به مکان‌های اسکریپت‌های ایجاد شده به‌صورت پویا ( document.createElement('script') )، از جمله به هر توابع کتابخانه‌ای که گره‌های DOM script را بر اساس مقادیر آرگومان‌هایشان ایجاد می‌کنند، تزریق شده باشد. این شامل برخی از APIهای رایج مانند .html() jQuery و همچنین .get() و .post() در jQuery < 3.0 می شود.
  • اگر در برنامه های قدیمی AngularJS تزریق قالب وجود دارد. مهاجمی که می تواند به قالب AngularJS تزریق کند، می تواند از آن برای اجرای جاوا اسکریپت دلخواه استفاده کند.
  • اگر این خط‌مشی حاوی 'unsafe-eval' باشد، تزریق‌هایی به eval() ، setTimeout() و چند API دیگر که به ندرت استفاده می‌شوند.

توسعه دهندگان و مهندسان امنیتی باید در طول بررسی کدها و ممیزی های امنیتی به چنین الگوهایی توجه ویژه ای داشته باشند. می‌توانید جزئیات بیشتری در مورد این موارد در خط‌مشی امنیت محتوا بیابید: آشفتگی موفقیت‌آمیز بین سخت شدن و کاهش .

در ادامه مطلب

،

پشتیبانی مرورگر

  • کروم: 52.
  • لبه: 79.
  • فایرفاکس: 52.
  • سافاری: 15.4.

منبع

برنامه نویسی متقابل سایت (XSS) ، توانایی تزریق اسکریپت های مخرب به یک برنامه وب، یکی از بزرگترین آسیب پذیری های امنیتی وب برای بیش از یک دهه بوده است.

سیاست امنیتی محتوا (CSP) یک لایه امنیتی اضافه شده است که به کاهش XSS کمک می کند. برای پیکربندی یک CSP، سربرگ Content-Security-Policy HTTP را به یک صفحه وب اضافه کنید و مقادیری را تنظیم کنید که کنترل کند عامل کاربر چه منابعی را برای آن صفحه بارگذاری کند.

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

اصطلاح کلیدی: nonce یک عدد تصادفی است که فقط یک بار استفاده می شود و می توانید از آن برای علامت گذاری یک تگ <script> به عنوان مورد اعتماد استفاده کنید.

اصطلاح کلیدی: تابع هش یک تابع ریاضی است که یک مقدار ورودی را به یک مقدار عددی فشرده به نام هش تبدیل می‌کند. شما می توانید از یک هش (به عنوان مثال SHA-256 ) برای علامت گذاری یک تگ <script> درون خطی به عنوان مورد اعتماد استفاده کنید.

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

چرا باید از CSP سختگیرانه استفاده کنید؟

اگر سایت شما قبلاً دارای یک CSP شبیه script-src www.googleapis.com ، احتمالاً در برابر متقابل سایت مؤثر نیست. به این نوع CSP، CSP لیست مجوز می گویند. آنها نیاز به سفارشی سازی زیادی دارند و مهاجمان می توانند از آنها عبور کنند .

CSPهای سختگیرانه مبتنی بر nonces یا هش رمزنگاری از این تله ها جلوگیری می کنند.

ساختار دقیق CSP

یک خط‌مشی امنیتی سختگیرانه محتوا از یکی از سرصفحه‌های پاسخ HTTP زیر استفاده می‌کند:

CSP سختگیرانه غیر مبتنی بر

Content-Security-Policy:
  script-src 'nonce-{RANDOM}' 'strict-dynamic';
  object-src 'none';
  base-uri 'none';
یک CSP سختگیرانه غیر مبتنی بر چگونه کار می کند.

CSP سختگیرانه مبتنی بر هش

Content-Security-Policy:
  script-src 'sha256-{HASHED_INLINE_SCRIPT}' 'strict-dynamic';
  object-src 'none';
  base-uri 'none';

ویژگی های زیر یک CSP مانند این را "سخت" و در نتیجه ایمن می کند:

  • از nonces 'nonce-{RANDOM}' یا هش 'sha256-{HASHED_INLINE_SCRIPT}' استفاده می‌کند تا نشان دهد توسعه‌دهنده سایت به کدام برچسب <script> اعتماد دارد تا در مرورگر کاربر اجرا شود.
  • 'strict-dynamic' را تنظیم می کند تا تلاش برای استقرار یک CSP غیر مبتنی بر هش را با اجازه دادن خودکار به اجرای اسکریپت هایی که یک اسکریپت قابل اعتماد ایجاد می کند، کاهش دهد. این همچنین استفاده از اکثر کتابخانه ها و ویجت های جاوا اسکریپت شخص ثالث را از حالت انسداد خارج می کند.
  • این بر اساس لیست های مجاز URL نیست، بنابراین از دور زدن های معمول CSP رنج نمی برد.
  • این اسکریپت های درون خطی غیرقابل اعتماد مانند کنترل کننده رویداد درون خطی یا javascript: URI ها را مسدود می کند.
  • object-src برای غیرفعال کردن پلاگین های خطرناک مانند Flash محدود می کند.
  • base-uri برای جلوگیری از تزریق تگ های <base> محدود می کند. این مانع از تغییر مکان اسکریپت های بارگیری شده از URL های نسبی توسط مهاجمان می شود.

یک CSP سختگیرانه اتخاذ کنید

برای اتخاذ یک CSP سختگیرانه، باید:

  1. تصمیم بگیرید که آیا برنامه شما باید یک CSP غیر یک یا هش تنظیم کند.
  2. CSP را از بخش ساختار Strict CSP کپی کنید و آن را به عنوان یک هدر پاسخ در برنامه خود تنظیم کنید.
  3. Refactor قالب های HTML و کد سمت سرویس گیرنده برای حذف الگوهای ناسازگار با CSP.
  4. CSP خود را مستقر کنید.

می‌توانید از Lighthouse (نسخه 7.3.0 و بالاتر با flag --preset=experimental ) در طول این فرآیند استفاده کنید تا بررسی کنید که آیا سایت شما دارای CSP است یا خیر ، و آیا به اندازه کافی سختگیرانه است که در برابر XSS مؤثر باشد.

گزارش Lighthouse هشدار می دهد که هیچ CSP در حالت اجرا یافت نمی شود.
اگر سایت شما CSP ندارد، Lighthouse این هشدار را نشان می دهد.

مرحله 1: تصمیم بگیرید که آیا به یک CSP غیر مبتنی بر هش نیاز دارید یا خیر

در اینجا نحوه عملکرد دو نوع CSP سختگیرانه آمده است:

CSP غیر مبتنی بر

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

برای صفحات HTML ارائه شده بر روی سرور از یک CSP غیر مبتنی بر استفاده کنید. برای این صفحات، می توانید برای هر پاسخ یک عدد تصادفی جدید ایجاد کنید.

CSP مبتنی بر هش

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

از یک CSP مبتنی بر هش برای صفحات HTML که به صورت ایستا ارائه می شوند یا صفحاتی که نیاز به کش دارند استفاده کنید. برای مثال، می‌توانید از یک CSP مبتنی بر هش برای برنامه‌های وب تک صفحه‌ای که با فریم‌ورک‌هایی مانند Angular، React یا موارد دیگر ساخته شده‌اند، استفاده کنید که به‌صورت ایستا و بدون رندر سمت سرور ارائه می‌شوند.

مرحله 2: یک CSP سختگیرانه تنظیم کنید و اسکریپت های خود را آماده کنید

هنگام تنظیم یک CSP، چند گزینه دارید:

  • حالت فقط گزارش ( Content-Security-Policy-Report-Only ) یا حالت اجرایی ( Content-Security-Policy ). در حالت فقط گزارش، CSP هنوز منابع را مسدود نمی کند، بنابراین هیچ چیز در سایت شما خراب نمی شود، اما می توانید خطاها را ببینید و برای هر چیزی که مسدود شده بود گزارش دریافت کنید. به صورت محلی، وقتی CSP خود را تنظیم می کنید، این واقعاً مهم نیست، زیرا هر دو حالت خطاهای موجود در کنسول مرورگر را به شما نشان می دهند. در هر صورت، حالت اجرا می تواند به شما کمک کند منابعی را که بلوک های پیش نویس CSP خود را پیدا می کنید، پیدا کنید، زیرا مسدود کردن یک منبع می تواند صفحه شما را شکسته به نظر برساند. حالت فقط گزارش بعداً در این فرآیند بسیار کاربردی می شود ( مرحله 5 را ببینید).
  • هدر یا تگ <meta> HTML. برای توسعه محلی، یک تگ <meta> می تواند برای بهینه سازی CSP شما و مشاهده سریع تاثیر آن بر سایت شما راحت تر باشد. با این حال:
    • بعداً، هنگام استقرار CSP خود در تولید، توصیه می کنیم آن را به عنوان یک هدر HTTP تنظیم کنید.
    • اگر می‌خواهید CSP خود را در حالت فقط گزارش تنظیم کنید، باید آن را به عنوان یک هدر تنظیم کنید، زیرا متا تگ‌های CSP از حالت فقط گزارش پشتیبانی نمی‌کنند.

گزینه A: CSP غیر مبتنی بر

هدر پاسخ HTTP Content-Security-Policy زیر را در برنامه خود تنظیم کنید:

Content-Security-Policy:
  script-src 'nonce-{RANDOM}' 'strict-dynamic';
  object-src 'none';
  base-uri 'none';

یک nonce برای CSP ایجاد کنید

Nonce یک عدد تصادفی است که فقط یک بار در هر بارگذاری صفحه استفاده می شود. یک CSP مبتنی بر غیرانس تنها زمانی می تواند XSS را کاهش دهد که مهاجمان نتوانند مقدار nonce را حدس بزنند. یک nonce CSP باید باشد:

  • یک مقدار تصادفی رمزنگاری قوی (طول ایده آل 128+ بیت)
  • برای هر پاسخی که به تازگی تولید شده است
  • Base64 کدگذاری شده است

در اینجا چند نمونه از نحوه اضافه کردن یک CSP nonce در چارچوب های سمت سرور آورده شده است:

const app = express();

app.get('/', function(request, response) {
  // Generate a new random nonce value for every response.
  const nonce = crypto.randomBytes(16).toString("base64");

  // Set the strict nonce-based CSP response header
  const csp = `script-src 'nonce-${nonce}' 'strict-dynamic'; object-src 'none'; base-uri 'none';`;
  response.set("Content-Security-Policy", csp);

  // Every <script> tag in your application should set the `nonce` attribute to this value.
  response.render(template, { nonce: nonce });
});

یک ویژگی nonce به عناصر <script> اضافه کنید

با یک CSP مبتنی بر nonce، هر عنصر <script> باید دارای یک ویژگی nonce باشد که با مقدار nonce تصادفی مشخص شده در هدر CSP مطابقت داشته باشد. همه اسکریپت ها می توانند nonce یکسانی داشته باشند. اولین قدم این است که این ویژگی ها را به همه اسکریپت ها اضافه کنید تا CSP به آنها اجازه دهد.

گزینه B: سربرگ پاسخ CSP مبتنی بر هش

هدر پاسخ HTTP Content-Security-Policy زیر را در برنامه خود تنظیم کنید:

Content-Security-Policy:
  script-src 'sha256-{HASHED_INLINE_SCRIPT}' 'strict-dynamic';
  object-src 'none';
  base-uri 'none';

برای چند اسکریپت درون خطی، نحو به شرح زیر است: 'sha256-{HASHED_INLINE_SCRIPT_1}' 'sha256-{HASHED_INLINE_SCRIPT_2}' .

اسکریپت های منبع را به صورت پویا بارگیری کنید

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

نمونه ای از نحوه درون خط کردن اسکریپت های خود.
توسط CSP مجاز است
<script>
  var scripts = [ 'https://example.org/foo.js', 'https://example.org/bar.js'];

  scripts.forEach(function(scriptUrl) {
    var s = document.createElement('script');
    s.src = scriptUrl;
    s.async = false; // to preserve execution order
    document.head.appendChild(s);
  });
</script>
برای اینکه اجازه دهید این اسکریپت اجرا شود، باید هش اسکریپت درون خطی را محاسبه کرده و آن را به سرصفحه پاسخ CSP اضافه کنید و جایگزین مکان‌دار {HASHED_INLINE_SCRIPT} شود. برای کاهش تعداد هش ها، می توانید تمام اسکریپت های درون خطی را در یک اسکریپت ادغام کنید. برای مشاهده عملی آن، به این مثال و کد آن مراجعه کنید.
توسط CSP مسدود شده است
<script src="https://example.org/foo.js"></script>
<script src="https://example.org/bar.js"></script>
CSP این اسکریپت ها را مسدود می کند زیرا فقط اسکریپت های درون خطی را می توان هش کرد.

ملاحظات بارگیری اسکریپت

مثال اسکریپت درون خطی s.async = false را اضافه می کند تا اطمینان حاصل شود که foo قبل از bar اجرا می شود، حتی اگر bar ابتدا بارگیری شود. در این قطعه، s.async = false هنگام بارگیری اسکریپت ها تجزیه کننده را مسدود نمی کند، زیرا اسکریپت ها به صورت پویا اضافه می شوند. تجزیه کننده فقط در حین اجرای اسکریپت ها متوقف می شود، همانطور که برای اسکریپت های async انجام می شود. با این حال، با این قطعه، به خاطر داشته باشید:

  • ممکن است یک یا هر دو اسکریپت قبل از پایان دانلود سند اجرا شوند. اگر می خواهید سند تا زمان اجرای اسکریپت ها آماده شود، قبل از اینکه اسکریپت ها را اضافه کنید منتظر رویداد DOMContentLoaded باشید. اگر این باعث مشکل در عملکرد می شود زیرا اسکریپت ها به اندازه کافی زود دانلود نمی شوند، از برچسب های پیش بارگذاری زودتر در صفحه استفاده کنید.
  • defer = true کاری نمی کند. اگر به آن رفتار نیاز دارید، اسکریپت را در صورت نیاز به صورت دستی اجرا کنید.

مرحله 3: الگوهای HTML و کد سمت مشتری را Refactor کنید

کنترل‌کننده‌های رویداد درون خطی (مانند onclick="…" , onerror="…" ) و URI‌های جاوا اسکریپت ( <a href="javascript:…"> ) می‌توانند برای اجرای اسکریپت‌ها استفاده شوند. این بدان معناست که مهاجمی که باگ XSS را پیدا می‌کند می‌تواند این نوع HTML را تزریق کرده و جاوا اسکریپت مخرب را اجرا کند. یک CSP غیر مبتنی بر هش استفاده از این نوع نشانه گذاری را ممنوع می کند. اگر سایت شما از هر یک از این الگوها استفاده می کند، باید آنها را به جایگزین های ایمن تر تبدیل کنید.

اگر CSP را در مرحله قبل فعال کرده باشید، هر بار که CSP یک الگوی ناسازگار را مسدود می کند، می توانید نقض CSP را در کنسول مشاهده کنید.

گزارش نقض CSP در کنسول برنامه‌نویس Chrome.
خطاهای کنسول برای کد مسدود شده

در بیشتر موارد، راه حل ساده است:

کنترل کننده رویداد درون خطی Refactor

توسط CSP مجاز است
<span id="things">A thing.</span>
<script nonce="${nonce}">
  document.getElementById('things').addEventListener('click', doThings);
</script>
CSP به گردانندگان رویداد اجازه می دهد که با استفاده از جاوا اسکریپت ثبت شوند.
توسط CSP مسدود شده است
<span onclick="doThings();">A thing.</span>
CSP کنترل کننده های رویداد درون خطی را مسدود می کند.

Refactor javascript: URIs

توسط CSP مجاز است
<a id="foo">foo</a>
<script nonce="${nonce}">
  document.getElementById('foo').addEventListener('click', linkClicked);
</script>
CSP به گردانندگان رویداد اجازه می دهد که با استفاده از جاوا اسکریپت ثبت شوند.
توسط CSP مسدود شده است
<a href="javascript:linkClicked()">foo</a>
CSP جاوا اسکریپت را مسدود می کند: URI ها.

eval() از جاوا اسکریپت خود حذف کنید

اگر برنامه شما از eval() برای تبدیل سریال‌سازی‌های رشته‌های JSON به اشیاء JS استفاده می‌کند، باید چنین نمونه‌هایی را به JSON.parse() تبدیل کنید، که سریع‌تر نیز است.

اگر نمی‌توانید همه استفاده‌های eval() را حذف کنید، همچنان می‌توانید یک CSP غیرمبتنی سخت تنظیم کنید، اما باید از کلمه کلیدی CSP 'unsafe-eval' استفاده کنید که باعث می‌شود خط‌مشی شما کمی ایمن‌تر شود.

شما می‌توانید این و نمونه‌های بیشتری از این نوع refactoring را در این کد CSP سخت‌گیرانه بیابید:

مرحله 4 (اختیاری): برای پشتیبانی از نسخه های قدیمی مرورگر، نسخه های جایگزین اضافه کنید

پشتیبانی مرورگر

  • کروم: 52.
  • لبه: 79.
  • فایرفاکس: 52.
  • سافاری: 15.4.

منبع

اگر نیاز به پشتیبانی از نسخه های قدیمی مرورگر دارید:

  • استفاده از strict-dynamic مستلزم افزودن https: به عنوان نسخه بازگشتی برای نسخه های قبلی سافاری است. وقتی این کار را انجام می دهید:
    • همه مرورگرهایی که از strict-dynamic پشتیبانی می‌کنند https: بازگشتی را نادیده می‌گیرند، بنابراین این امر قدرت سیاست را کاهش نمی‌دهد.
    • در مرورگرهای قدیمی، اسکریپت‌های با منبع خارجی تنها در صورتی می‌توانند بارگیری شوند که از منبع HTTPS باشند. این امنیت کمتر از یک CSP سختگیرانه است، اما همچنان از برخی دلایل رایج XSS مانند تزریق javascript: URIها جلوگیری می کند.
  • برای اطمینان از سازگاری با نسخه‌های مرورگر بسیار قدیمی (4 سال به بالا)، می‌توانید به‌عنوان نسخه‌ی بازگشتی unsafe-inline اضافه کنید. همه مرورگرهای اخیر در صورت وجود یک CSP nonce یا هش، از unsafe-inline چشم پوشی می کنند.
Content-Security-Policy:
  script-src 'nonce-{random}' 'strict-dynamic' https: 'unsafe-inline';
  object-src 'none';
  base-uri 'none';

مرحله 5: CSP خود را مستقر کنید

پس از تأیید اینکه CSP شما هیچ اسکریپت قانونی را در محیط توسعه محلی شما مسدود نمی کند، می توانید CSP خود را در مرحله مرحله بندی و سپس در محیط تولید خود مستقر کنید:

  1. (اختیاری) با استفاده از هدر Content-Security-Policy-Report-Only CSP خود را در حالت گزارش فقط اجرا کنید. حالت فقط گزارش برای آزمایش یک تغییر بالقوه شکست مانند یک CSP جدید در تولید قبل از شروع به اجرای محدودیت‌های CSP مفید است. در حالت فقط گزارش، CSP شما بر رفتار برنامه‌تان تأثیر نمی‌گذارد، اما مرورگر همچنان وقتی با الگوهای ناسازگار با CSP شما مواجه می‌شود، خطاهای کنسول و گزارش‌های تخلف ایجاد می‌کند، بنابراین می‌توانید ببینید چه چیزی برای کاربران نهایی شما خراب می‌شود. برای اطلاعات بیشتر، گزارش API را ببینید.
  2. وقتی مطمئن هستید که CSP شما سایت شما را برای کاربران نهایی شما خراب نمی کند، CSP خود را با استفاده از هدر پاسخ Content-Security-Policy گسترش دهید. توصیه می کنیم CSP خود را با استفاده از هدر HTTP سمت سرور تنظیم کنید زیرا از تگ <meta> ایمن تر است. پس از تکمیل این مرحله، CSP شما شروع به محافظت از برنامه شما در برابر XSS می کند.

محدودیت ها

یک CSP سختگیرانه به طور کلی یک لایه امنیتی قوی اضافه می کند که به کاهش XSS کمک می کند. در بیشتر موارد، CSP با رد الگوهای خطرناک مانند javascript: URI، سطح حمله را به میزان قابل توجهی کاهش می دهد. با این حال، بر اساس نوع CSP که استفاده می کنید (nonces، هش، با یا بدون 'strict-dynamic' )، مواردی وجود دارد که CSP از برنامه شما نیز محافظت نمی کند:

  • اگر یک اسکریپت ندارید، اما مستقیماً به بدنه یا پارامتر src آن عنصر <script> تزریق شده است.
  • اگر به مکان‌های اسکریپت‌های ایجاد شده به‌صورت پویا ( document.createElement('script') )، از جمله به هر توابع کتابخانه‌ای که گره‌های DOM script را بر اساس مقادیر آرگومان‌هایشان ایجاد می‌کنند، تزریق شده باشد. این شامل برخی از APIهای رایج مانند .html() jQuery و همچنین .get() و .post() در jQuery < 3.0 می شود.
  • اگر در برنامه های قدیمی AngularJS تزریق قالب وجود دارد. مهاجمی که می تواند به قالب AngularJS تزریق کند، می تواند از آن برای اجرای جاوا اسکریپت دلخواه استفاده کند.
  • اگر این سیاست حاوی 'unsafe-eval' باشد ، تزریق به eval() ، setTimeout() و چند API های دیگر که به ندرت استفاده می شوند.

توسعه دهندگان و مهندسان امنیتی باید در هنگام بررسی کد و ممیزی های امنیتی به چنین الگوهای توجه ویژه ای داشته باشند. در سیاست امنیت محتوا می توانید جزئیات بیشتری در مورد این موارد پیدا کنید: یک آشفتگی موفق بین سخت شدن و کاهش .

در ادامه مطلب

،

پشتیبانی مرورگر

  • کروم: 52.
  • لبه: 79.
  • Firefox: 52.
  • سافاری: 15.4.

منبع

برنامه نویسی متقابل سایت (XSS) ، امکان تزریق اسکریپت های مخرب به یک برنامه وب ، بیش از یک دهه است که یکی از بزرگترین آسیب پذیری های امنیتی وب بوده است.

سیاست امنیت محتوا (CSP) یک لایه امنیتی اضافه شده است که به کاهش XSS کمک می کند. برای پیکربندی CSP ، عنوان HTTP Content-Security-Policy HEDER را به یک صفحه وب اضافه کنید و مقادیری را تنظیم کنید که کنترل کننده منابع کاربر برای آن صفحه را کنترل می کند.

در این صفحه نحوه استفاده از CSP بر اساس غیر یا هش برای کاهش XSS توضیح داده شده است ، به جای CSP های متداول مبتنی بر آلولیستی که اغلب صفحه را در معرض XSS قرار می دهند زیرا می توان آنها را در اکثر تنظیمات دور کرد .

اصطلاح کلیدی: NONCE یک عدد تصادفی است که فقط یک بار استفاده می شود که می توانید برای علامت گذاری یک برچسب <script> به عنوان قابل اعتماد استفاده کنید.

اصطلاح کلیدی: یک تابع هش یک تابع ریاضی است که مقدار ورودی را به یک مقدار عددی فشرده به نام هش تبدیل می کند. می توانید از هش (به عنوان مثال SHA-256 ) استفاده کنید تا یک برچسب درون خطی <script> را به عنوان مورد اعتماد علامت گذاری کنید.

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

چرا باید از CSP سخت استفاده کنید؟

اگر سایت شما قبلاً دارای CSP است که شبیه script-src www.googleapis.com ، احتمالاً در برابر سایت متقابل مؤثر نیست. این نوع CSP CSP Allowlist نامیده می شود. آنها به سفارشی سازی زیادی نیاز دارند و توسط مهاجمان می توانند دور شوند.

CSP های دقیق و مبتنی بر افراد غیر رمزنگاری یا هشدهی از این مشکلات جلوگیری می کنند.

ساختار دقیق CSP

یک سیاست اساسی امنیتی محتوای اصلی از یکی از عنوان های پاسخ HTTP زیر استفاده می کند:

CSP سختگیرانه غیر مبتنی بر

Content-Security-Policy:
  script-src 'nonce-{RANDOM}' 'strict-dynamic';
  object-src 'none';
  base-uri 'none';
چگونه یک CSP سخت مبتنی بر غیر مبتنی بر کار می کند.

CSP سختگیرانه مبتنی بر هش

Content-Security-Policy:
  script-src 'sha256-{HASHED_INLINE_SCRIPT}' 'strict-dynamic';
  object-src 'none';
  base-uri 'none';

خصوصیات زیر یک CSP مانند این را "سخت" می کند و بنابراین ایمن است:

  • از nonces 'nonce-{RANDOM}' یا هش 'sha256-{HASHED_INLINE_SCRIPT}' استفاده می کند تا نشان دهد که <script> به توسعه دهنده سایت اعتماد می کند تا در مرورگر کاربر اجرا شود.
  • این 'strict-dynamic' را تنظیم می کند تا تلاش برای استقرار یک CSP مبتنی بر هش یا هش را با اجازه دادن به صورت خودکار اجرای اسکریپت هایی که یک اسکریپت قابل اعتماد ایجاد می کند ، کاهش دهد. این همچنین استفاده از بیشتر کتابخانه ها و ابزارک های جاوا اسکریپت شخص ثالث را از بین می برد.
  • این مبتنی بر لیست های اجازه URL نیست ، بنابراین از گذرگاه های مشترک CSP رنج نمی برد.
  • این اسکریپت های درون خطی را مانند دستگیرندگان رویداد Inline یا javascript: URIS.
  • این امر object-src را برای غیرفعال کردن افزونه های خطرناک مانند Flash محدود می کند.
  • این base-uri را محدود می کند تا تزریق برچسب های <base> را مسدود کند. این امر مانع از تغییر مکان های اسکریپت های بارگیری شده از URL های نسبی می شود.

یک CSP دقیق را اتخاذ کنید

برای اتخاذ یک CSP سخت ، شما باید:

  1. تصمیم بگیرید که آیا برنامه شما باید یک CSP مبتنی بر هش یا هش را تنظیم کند.
  2. CSP را از بخش ساختار دقیق CSP کپی کرده و آن را به عنوان عنوان پاسخ در برنامه خود تنظیم کنید.
  3. الگوهای HTML Refactor و کد سمت مشتری برای حذف الگوهای ناسازگار با CSP.
  4. CSP خود را مستقر کنید.

شما می توانید در طول این فرآیند از Lighthouse (v7.3.0 و بالاتر با پرچم --preset=experimental ) استفاده کنید تا بررسی کنید که آیا سایت شما دارای CSP است ، و اینکه آیا به اندازه کافی سخت است که در برابر XSS مؤثر باشد.

گزارش گزارش فانوس دریایی هشدار می دهد که هیچ CSP در حالت اجرای آن یافت نمی شود.
اگر سایت شما CSP ندارد ، فانوس دریایی این هشدار را نشان می دهد.

مرحله 1: تصمیم بگیرید که آیا به CSP غیر CE- یا هش نیاز دارید

در اینجا نحوه کار دو نوع CSP دقیق آورده شده است:

CSP مبتنی بر غیر CE

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

برای صفحات HTML که روی سرور ارائه شده است ، از CSP مبتنی بر Nonce استفاده کنید. برای این صفحات می توانید برای هر پاسخ یک شماره تصادفی جدید ایجاد کنید.

CSP مبتنی بر هش

برای یک CSP مبتنی بر هش ، هش از هر برچسب اسکریپت درون خطی به CSP اضافه می شود. هر فیلمنامه دارای هش متفاوت است. یک مهاجم نمی تواند یک اسکریپت مخرب را در صفحه شما قرار دهد یا اجرا کند ، زیرا هش آن اسکریپت برای اجرای آن باید در CSP شما باشد.

از CSP مبتنی بر هش برای صفحات HTML به صورت آماری استفاده کنید ، یا صفحاتی که باید ذخیره شوند. به عنوان مثال ، شما می توانید از CSP مبتنی بر هش برای برنامه های وب تک صفحه ای ساخته شده با چارچوب هایی مانند Angular ، React یا موارد دیگر استفاده کنید که از نظر آماری بدون ارائه سمت سرور ارائه می شوند.

مرحله 2: یک CSP سخت تنظیم کنید و اسکریپت های خود را آماده کنید

هنگام تنظیم CSP ، چند گزینه دارید:

  • حالت فقط گزارش ( Content-Security-Policy-Report-Only ) یا حالت اجرای ( Content-Security-Policy ). در حالت فقط گزارش ، CSP هنوز منابع را مسدود نمی کند ، بنابراین هیچ چیز در سایت شما شکسته نمی شود ، اما می توانید خطاها را مشاهده کنید و گزارش هایی را برای هر چیزی که مسدود شده باشد دریافت کنید. به صورت محلی ، وقتی CSP خود را تنظیم می کنید ، این مهم نیست ، زیرا هر دو حالت خطاهای موجود در کنسول مرورگر را به شما نشان می دهند. در هر صورت ، حالت اجرای می تواند به شما در یافتن منابعی پیش نویس بلوک های CSP کمک کند ، زیرا مسدود کردن یک منبع می تواند صفحه شما را خراب کند. حالت فقط گزارش بعداً در این فرآیند مفیدتر می شود (به مرحله 5 مراجعه کنید).
  • برچسب هدر یا HTML <meta> . برای توسعه محلی ، یک برچسب <meta> می تواند برای ترساندن CSP شما راحت تر باشد و به سرعت می بینید که چگونه این سایت را تحت تأثیر قرار می دهد. با این حال:
    • بعداً ، هنگام استقرار CSP خود در تولید ، توصیه می کنیم آن را به عنوان هدر HTTP تنظیم کنید.
    • اگر می خواهید CSP خود را در حالت فقط گزارش تنظیم کنید ، باید آن را به عنوان هدر تنظیم کنید ، زیرا برچسب های CSP متا از حالت فقط گزارش پشتیبانی نمی کنند.

گزینه A: CSP مبتنی بر غیر CE

عنوان زیر را با عنوان- Content-Security-Policy HTTP در برنامه خود تنظیم کنید:

Content-Security-Policy:
  script-src 'nonce-{RANDOM}' 'strict-dynamic';
  object-src 'none';
  base-uri 'none';

برای CSP یک NONCE ایجاد کنید

Nonce یک عدد تصادفی است که فقط یک بار در هر بار صفحه استفاده می شود. اگر مهاجمان نتوانند ارزش غیر CE را حدس بزنند ، CSP مبتنی بر Nonce فقط می تواند XSS را کاهش دهد. CSP غیرقانونی باید باشد:

  • یک مقدار تصادفی رمزنگاری قوی (در حالت ایده آل 128+ بیت)
  • تازه برای هر پاسخ تولید شده است
  • BASE64 رمزگذاری شده

در اینجا چند نمونه از نحوه اضافه کردن CSP NONCE در چارچوب های سمت سرور آورده شده است:

const app = express();

app.get('/', function(request, response) {
  // Generate a new random nonce value for every response.
  const nonce = crypto.randomBytes(16).toString("base64");

  // Set the strict nonce-based CSP response header
  const csp = `script-src 'nonce-${nonce}' 'strict-dynamic'; object-src 'none'; base-uri 'none';`;
  response.set("Content-Security-Policy", csp);

  // Every <script> tag in your application should set the `nonce` attribute to this value.
  response.render(template, { nonce: nonce });
});

یک ویژگی nonce را به عناصر <script> اضافه کنید

با داشتن یک CSP مبتنی بر NONCE ، هر عنصر <script> باید دارای یک ویژگی nonce باشد که با مقدار غیر CANCE تصادفی مشخص شده در عنوان CSP مطابقت داشته باشد. همه اسکریپت ها می توانند یکسان باشند. اولین قدم اضافه کردن این ویژگی ها به همه اسکریپت ها است تا CSP به آنها اجازه دهد.

گزینه B: هدر پاسخ CSP مبتنی بر هش

عنوان زیر را با عنوان- Content-Security-Policy HTTP در برنامه خود تنظیم کنید:

Content-Security-Policy:
  script-src 'sha256-{HASHED_INLINE_SCRIPT}' 'strict-dynamic';
  object-src 'none';
  base-uri 'none';

برای چندین اسکریپت درون خطی ، نحو به شرح زیر است: 'sha256-{HASHED_INLINE_SCRIPT_1}' 'sha256-{HASHED_INLINE_SCRIPT_2}' .

اسکریپت های منبع را به صورت پویا بارگیری کنید

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

نمونه ای از نحوه ورود به اسکریپت های خود.
مجاز توسط CSP
<script>
  var scripts = [ 'https://example.org/foo.js', 'https://example.org/bar.js'];

  scripts.forEach(function(scriptUrl) {
    var s = document.createElement('script');
    s.src = scriptUrl;
    s.async = false; // to preserve execution order
    document.head.appendChild(s);
  });
</script>
برای اینکه این اسکریپت اجرا شود ، باید هش اسکریپت درون خطی را محاسبه کرده و آن را به عنوان پاسخ CSP اضافه کنید ، و جایگزین مکان {HASHED_INLINE_SCRIPT} . برای کاهش میزان هش ها ، می توانید تمام اسکریپت های درون خطی را در یک اسکریپت واحد ادغام کنید. برای دیدن این کار در عمل ، به این مثال و کد آن مراجعه کنید.
مسدود شده توسط CSP
<script src="https://example.org/foo.js"></script>
<script src="https://example.org/bar.js"></script>
CSP این اسکریپت ها را مسدود می کند زیرا فقط اسکریپت های درون خطی قابل هشدار هستند.

ملاحظات بارگیری اسکریپت

مثال اسکریپت درون خطی s.async = false را اضافه می کند تا اطمینان حاصل شود که foo قبل از bar اجرا می شود ، حتی اگر bar ابتدا بارگذاری شود. در این قطعه ، s.async = false تجزیه کننده را مسدود نمی کند در حالی که اسکریپت ها بارگذاری می شوند ، زیرا اسکریپت ها به صورت پویا اضافه می شوند. تجزیه کننده فقط در حالی که اسکریپت ها اجرا می شوند ، متوقف می شود ، همانطور که برای اسکریپت های async . با این حال ، با این قطعه ، به خاطر داشته باشید:

  • ممکن است قبل از بارگیری سند ، یکی یا هر دو اسکریپت اجرا شود. اگر می خواهید این سند تا زمان اجرای اسکریپت ها آماده شود ، قبل از اینکه اسکریپت ها را ضمیمه کنید ، منتظر رویداد DOMContentLoaded باشید. اگر این مسئله باعث ایجاد مشکل می شود زیرا اسکریپت ها به اندازه کافی زود بارگیری را شروع نمی کنند ، از پیش بارگذاری از قبل در صفحه استفاده کنید.
  • defer = true کاری نمی کند. اگر به آن رفتار احتیاج دارید ، در صورت لزوم فیلمنامه را به صورت دستی اجرا کنید.

مرحله 3: الگوهای HTML Refactor و کد سمت مشتری

دستگیرندگان رویداد Inline (مانند onclick="…" ، onerror="…" ) و JavaScript Uris ( <a href="javascript:…"> ) می توانند برای اجرای اسکریپت ها استفاده شوند. این بدان معنی است که یک مهاجم که یک اشکال XSS پیدا می کند می تواند این نوع HTML را تزریق کند و JavaScript مخرب را اجرا کند. CSP غیر CE- یا هش ، استفاده از این نوع نشانه ها را ممنوع می کند. اگر سایت شما از هر یک از این الگوهای استفاده می کند ، باید آنها را به گزینه های امن تر تبدیل کنید.

اگر در مرحله قبل CSP را فعال کرده اید ، می توانید هر بار که CSP یک الگوی ناسازگار را مسدود می کند ، نقض CSP را در کنسول مشاهده کنید.

گزارش های نقض CSP در کنسول توسعه دهنده Chrome.
خطاهای کنسول برای کد مسدود شده.

در بیشتر موارد ، رفع ساده است:

دستگیرندگان رویداد refactor inline

مجاز توسط CSP
<span id="things">A thing.</span>
<script nonce="${nonce}">
  document.getElementById('things').addEventListener('click', doThings);
</script>
CSP اجازه می دهد تا دستیار رویداد که با استفاده از JavaScript ثبت شده اند.
مسدود شده توسط CSP
<span onclick="doThings();">A thing.</span>
CSP دستگیره های رویداد Inline را بلوک می کند.

Refactor javascript: Uris

مجاز توسط CSP
<a id="foo">foo</a>
<script nonce="${nonce}">
  document.getElementById('foo').addEventListener('click', linkClicked);
</script>
CSP اجازه می دهد تا دستیار رویداد که با استفاده از JavaScript ثبت شده اند.
مسدود شده توسط CSP
<a href="javascript:linkClicked()">foo</a>
CSP بلوک JavaScript: Uris.

eval() از JavaScript خود حذف کنید

اگر برنامه شما از eval() برای تبدیل سریال های رشته JSON به اشیاء JS استفاده می کند ، باید چنین مواردی را به JSON.parse() ، که سریعتر است ، مجدداً تغییر دهید.

اگر نمی توانید تمام کاربردهای eval() را حذف کنید ، هنوز هم می توانید یک CSP مبتنی بر Nonce را تنظیم کنید ، اما باید از کلمه کلیدی CSP 'unsafe-eval' استفاده کنید ، که این امر باعث می شود سیاست شما کمی امن تر شود.

شما می توانید این نمونه ها و نمونه های بیشتری از چنین اصلاح مجدد را در این CODELAB CSP دقیق پیدا کنید:

مرحله 4 (اختیاری): برای پشتیبانی از نسخه های مرورگر قدیمی ، فالزها را اضافه کنید

پشتیبانی مرورگر

  • کروم: 52.
  • لبه: 79.
  • Firefox: 52.
  • سافاری: 15.4.

منبع

اگر نیاز به پشتیبانی از نسخه های مرورگر قدیمی دارید:

  • استفاده از strict-dynamic نیاز به افزودن https: به عنوان یک بازپرداخت برای نسخه های قبلی Safari. وقتی این کار را انجام می دهید:
    • همه مرورگرهایی که از strict-dynamic پشتیبانی می کنند https: Fallback ، بنابراین این باعث کاهش قدرت این سیاست نمی شود.
    • در مرورگرهای قدیمی ، اسکریپت های خارج از کشور فقط در صورتی که از منشأ HTTPS بیایند ، بارگیری می شوند. این کمتر از یک CSP سخت امن است ، اما هنوز هم از برخی موارد متداول XSS مانند تزریق javascript: URIS.
  • برای اطمینان از سازگاری با نسخه های مرورگر بسیار قدیمی (4+ سال) ، می توانید به عنوان یک بازپرداخت unsafe-inline اضافه کنید. در صورت عدم وجود CSP یا هش ، همه مرورگرهای اخیر unsafe-inline نادیده گرفته می شوند.
Content-Security-Policy:
  script-src 'nonce-{random}' 'strict-dynamic' https: 'unsafe-inline';
  object-src 'none';
  base-uri 'none';

مرحله 5: CSP خود را مستقر کنید

پس از تأیید اینکه CSP شما هیچ اسکریپت قانونی را در محیط توسعه محلی شما مسدود نمی کند ، می توانید CSP خود را برای مرحله بندی و سپس به محیط تولید خود مستقر کنید:

  1. (اختیاری) CSP خود را در حالت فقط گزارش با استفاده از هدر Content-Security-Policy-Report-Only مستقر کنید. قبل از شروع اجرای محدودیت های CSP ، حالت فقط گزارش برای آزمایش یک تغییر بالقوه در حال شکستن مانند CSP جدید در تولید مفید است. در حالت فقط گزارش ، CSP شما بر رفتار برنامه شما تأثیر نمی گذارد ، اما مرورگر هنوز هم خطاهای کنسول و گزارش های نقض را هنگام برخورد با الگوهای ناسازگار با CSP شما ایجاد می کند ، بنابراین می توانید ببینید که چه چیزی برای کاربران نهایی شما شکسته است. برای اطلاعات بیشتر ، به گزارش API مراجعه کنید.
  2. هنگامی که اطمینان دارید که CSP شما سایت شما را برای کاربران نهایی خود نمی شکند ، CSP خود را با استفاده از هدر پاسخ Content-Security-Policy مستقر کنید. توصیه می کنیم CSP خود را با استفاده از یک سرور HTTP Header Side تنظیم کنید زیرا از یک برچسب <meta> ایمن تر است. پس از اتمام این مرحله ، CSP شما از برنامه شما از XSS محافظت می کند.

محدودیت ها

یک CSP دقیق به طور کلی یک لایه امنیتی قوی را فراهم می کند که به کاهش XSS کمک می کند. در بیشتر موارد ، CSP با رد الگوهای خطرناک مانند javascript: URIS ، سطح حمله را به میزان قابل توجهی کاهش می دهد. با این حال ، بر اساس نوع CSP که استفاده می کنید (غیر ، هش ، با یا بدون 'strict-dynamic' ) ، مواردی وجود دارد که CSP از برنامه شما نیز محافظت نمی کند:

  • اگر یک اسکریپت را غافل می کنید ، اما یک تزریق مستقیماً به بدن یا پارامتر src آن عنصر <script> وجود دارد.
  • در صورت تزریق در مکان اسکریپت های ایجاد شده پویا ( document.createElement('script') ) ، از جمله در هر کارکرد کتابخانه ای که گره های DOM script را بر اساس مقادیر آرگومان های خود ایجاد می کنند ، وجود دارد. این شامل برخی از API های مشترک مانند JQuery's .html() ، و همچنین .get() و .post() در jQuery <3.0 است.
  • در صورت وجود تزریق الگو در برنامه های قدیمی AngularJS. مهاجمی که می تواند به یک الگوی AngularJS تزریق کند می تواند از آن برای اجرای JavaScript دلخواه استفاده کند.
  • اگر این سیاست حاوی 'unsafe-eval' ، تزریق به eval() ، setTimeout() و چند API های دیگر به ندرت استفاده شود.

توسعه دهندگان و مهندسان امنیتی باید در هنگام بررسی کد و ممیزی های امنیتی به چنین الگوهای توجه ویژه ای داشته باشند. در سیاست امنیت محتوا می توانید جزئیات بیشتری در مورد این موارد پیدا کنید: یک آشفتگی موفق بین سخت شدن و کاهش .

در ادامه مطلب

،

پشتیبانی مرورگر

  • کروم: 52.
  • لبه: 79.
  • Firefox: 52.
  • سافاری: 15.4.

منبع

برنامه نویسی متقابل سایت (XSS) ، امکان تزریق اسکریپت های مخرب به یک برنامه وب ، بیش از یک دهه است که یکی از بزرگترین آسیب پذیری های امنیتی وب بوده است.

سیاست امنیت محتوا (CSP) یک لایه امنیتی اضافه شده است که به کاهش XSS کمک می کند. برای پیکربندی CSP ، عنوان HTTP Content-Security-Policy HEDER را به یک صفحه وب اضافه کنید و مقادیری را تنظیم کنید که کنترل کننده منابع کاربر برای آن صفحه را کنترل می کند.

در این صفحه نحوه استفاده از CSP بر اساس غیر یا هش برای کاهش XSS توضیح داده شده است ، به جای CSP های متداول مبتنی بر آلولیستی که اغلب صفحه را در معرض XSS قرار می دهند زیرا می توان آنها را در اکثر تنظیمات دور کرد .

اصطلاح کلیدی: NONCE یک عدد تصادفی است که فقط یک بار استفاده می شود که می توانید برای علامت گذاری یک برچسب <script> به عنوان قابل اعتماد استفاده کنید.

اصطلاح کلیدی: یک تابع هش یک تابع ریاضی است که مقدار ورودی را به یک مقدار عددی فشرده به نام هش تبدیل می کند. می توانید از هش (به عنوان مثال SHA-256 ) استفاده کنید تا یک برچسب درون خطی <script> را به عنوان مورد اعتماد علامت گذاری کنید.

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

چرا باید از CSP سخت استفاده کنید؟

اگر سایت شما قبلاً دارای CSP است که شبیه script-src www.googleapis.com ، احتمالاً در برابر سایت متقابل مؤثر نیست. این نوع CSP CSP Allowlist نامیده می شود. آنها به سفارشی سازی زیادی نیاز دارند و توسط مهاجمان می توانند دور شوند.

CSP های دقیق و مبتنی بر افراد غیر رمزنگاری یا هشدهی از این مشکلات جلوگیری می کنند.

ساختار دقیق CSP

یک سیاست اساسی امنیتی محتوای اصلی از یکی از عنوان های پاسخ HTTP زیر استفاده می کند:

CSP سختگیرانه غیر مبتنی بر

Content-Security-Policy:
  script-src 'nonce-{RANDOM}' 'strict-dynamic';
  object-src 'none';
  base-uri 'none';
چگونه یک CSP سخت مبتنی بر غیر مبتنی بر کار می کند.

CSP سختگیرانه مبتنی بر هش

Content-Security-Policy:
  script-src 'sha256-{HASHED_INLINE_SCRIPT}' 'strict-dynamic';
  object-src 'none';
  base-uri 'none';

خصوصیات زیر یک CSP مانند این را "سخت" می کند و بنابراین ایمن است:

  • از nonces 'nonce-{RANDOM}' یا هش 'sha256-{HASHED_INLINE_SCRIPT}' استفاده می کند تا نشان دهد که <script> به توسعه دهنده سایت اعتماد می کند تا در مرورگر کاربر اجرا شود.
  • این 'strict-dynamic' را تنظیم می کند تا تلاش برای استقرار یک CSP مبتنی بر هش یا هش را با اجازه دادن به صورت خودکار اجرای اسکریپت هایی که یک اسکریپت قابل اعتماد ایجاد می کند ، کاهش دهد. این همچنین استفاده از بیشتر کتابخانه ها و ابزارک های جاوا اسکریپت شخص ثالث را از بین می برد.
  • این مبتنی بر لیست های اجازه URL نیست ، بنابراین از گذرگاه های مشترک CSP رنج نمی برد.
  • این اسکریپت های درون خطی را مانند دستگیرندگان رویداد Inline یا javascript: URIS.
  • این امر object-src را برای غیرفعال کردن افزونه های خطرناک مانند Flash محدود می کند.
  • این base-uri را محدود می کند تا تزریق برچسب های <base> را مسدود کند. این امر مانع از تغییر مکان های اسکریپت های بارگیری شده از URL های نسبی می شود.

یک CSP دقیق را اتخاذ کنید

برای اتخاذ یک CSP سخت ، شما باید:

  1. تصمیم بگیرید که آیا برنامه شما باید یک CSP مبتنی بر هش یا هش را تنظیم کند.
  2. CSP را از بخش ساختار دقیق CSP کپی کرده و آن را به عنوان عنوان پاسخ در برنامه خود تنظیم کنید.
  3. الگوهای HTML Refactor و کد سمت مشتری برای حذف الگوهای ناسازگار با CSP.
  4. CSP خود را مستقر کنید.

شما می توانید در طول این فرآیند از Lighthouse (v7.3.0 و بالاتر با پرچم --preset=experimental ) استفاده کنید تا بررسی کنید که آیا سایت شما دارای CSP است ، و اینکه آیا به اندازه کافی سخت است که در برابر XSS مؤثر باشد.

گزارش گزارش فانوس دریایی هشدار می دهد که هیچ CSP در حالت اجرای آن یافت نمی شود.
اگر سایت شما CSP ندارد ، فانوس دریایی این هشدار را نشان می دهد.

مرحله 1: تصمیم بگیرید که آیا به CSP غیر CE- یا هش نیاز دارید

در اینجا نحوه کار دو نوع CSP دقیق آورده شده است:

CSP مبتنی بر غیر CE

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

برای صفحات HTML که روی سرور ارائه شده است ، از CSP مبتنی بر Nonce استفاده کنید. برای این صفحات می توانید برای هر پاسخ یک شماره تصادفی جدید ایجاد کنید.

CSP مبتنی بر هش

برای یک CSP مبتنی بر هش ، هش از هر برچسب اسکریپت درون خطی به CSP اضافه می شود. هر فیلمنامه دارای هش متفاوت است. یک مهاجم نمی تواند یک اسکریپت مخرب را در صفحه شما قرار دهد یا اجرا کند ، زیرا هش آن اسکریپت برای اجرای آن باید در CSP شما باشد.

از CSP مبتنی بر هش برای صفحات HTML به صورت آماری استفاده کنید ، یا صفحاتی که باید ذخیره شوند. به عنوان مثال ، شما می توانید از CSP مبتنی بر هش برای برنامه های وب تک صفحه ای ساخته شده با چارچوب هایی مانند Angular ، React یا موارد دیگر استفاده کنید که از نظر آماری بدون ارائه سمت سرور ارائه می شوند.

مرحله 2: یک CSP سخت تنظیم کنید و اسکریپت های خود را آماده کنید

هنگام تنظیم CSP ، چند گزینه دارید:

  • حالت فقط گزارش ( Content-Security-Policy-Report-Only ) یا حالت اجرای ( Content-Security-Policy ). در حالت فقط گزارش ، CSP هنوز منابع را مسدود نمی کند ، بنابراین هیچ چیز در سایت شما شکسته نمی شود ، اما می توانید خطاها را مشاهده کنید و گزارش هایی را برای هر چیزی که مسدود شده باشد دریافت کنید. به صورت محلی ، وقتی CSP خود را تنظیم می کنید ، این مهم نیست ، زیرا هر دو حالت خطاهای موجود در کنسول مرورگر را به شما نشان می دهند. در هر صورت ، حالت اجرای می تواند به شما در یافتن منابعی پیش نویس بلوک های CSP کمک کند ، زیرا مسدود کردن یک منبع می تواند صفحه شما را خراب کند. حالت فقط گزارش بعداً در این فرآیند مفیدتر می شود (به مرحله 5 مراجعه کنید).
  • برچسب هدر یا HTML <meta> . برای توسعه محلی ، یک برچسب <meta> می تواند برای ترساندن CSP شما راحت تر باشد و به سرعت می بینید که چگونه این سایت را تحت تأثیر قرار می دهد. با این حال:
    • بعداً ، هنگام استقرار CSP خود در تولید ، توصیه می کنیم آن را به عنوان هدر HTTP تنظیم کنید.
    • اگر می خواهید CSP خود را در حالت فقط گزارش تنظیم کنید ، باید آن را به عنوان هدر تنظیم کنید ، زیرا برچسب های CSP متا از حالت فقط گزارش پشتیبانی نمی کنند.

گزینه A: CSP مبتنی بر غیر CE

عنوان زیر را با عنوان- Content-Security-Policy HTTP در برنامه خود تنظیم کنید:

Content-Security-Policy:
  script-src 'nonce-{RANDOM}' 'strict-dynamic';
  object-src 'none';
  base-uri 'none';

برای CSP یک NONCE ایجاد کنید

Nonce یک عدد تصادفی است که فقط یک بار در هر بار صفحه استفاده می شود. اگر مهاجمان نتوانند ارزش غیر CE را حدس بزنند ، CSP مبتنی بر Nonce فقط می تواند XSS را کاهش دهد. CSP غیرقانونی باید باشد:

  • یک مقدار تصادفی رمزنگاری قوی (در حالت ایده آل 128+ بیت)
  • تازه برای هر پاسخ تولید شده است
  • BASE64 رمزگذاری شده

در اینجا چند نمونه از نحوه اضافه کردن CSP NONCE در چارچوب های سمت سرور آورده شده است:

const app = express();

app.get('/', function(request, response) {
  // Generate a new random nonce value for every response.
  const nonce = crypto.randomBytes(16).toString("base64");

  // Set the strict nonce-based CSP response header
  const csp = `script-src 'nonce-${nonce}' 'strict-dynamic'; object-src 'none'; base-uri 'none';`;
  response.set("Content-Security-Policy", csp);

  // Every <script> tag in your application should set the `nonce` attribute to this value.
  response.render(template, { nonce: nonce });
});

یک ویژگی nonce را به عناصر <script> اضافه کنید

با داشتن یک CSP مبتنی بر NONCE ، هر عنصر <script> باید دارای یک ویژگی nonce باشد که با مقدار غیر CANCE تصادفی مشخص شده در عنوان CSP مطابقت داشته باشد. همه اسکریپت ها می توانند یکسان باشند. اولین قدم اضافه کردن این ویژگی ها به همه اسکریپت ها است تا CSP به آنها اجازه دهد.

گزینه B: هدر پاسخ CSP مبتنی بر هش

عنوان زیر را با عنوان- Content-Security-Policy HTTP در برنامه خود تنظیم کنید:

Content-Security-Policy:
  script-src 'sha256-{HASHED_INLINE_SCRIPT}' 'strict-dynamic';
  object-src 'none';
  base-uri 'none';

برای چندین اسکریپت درون خطی ، نحو به شرح زیر است: 'sha256-{HASHED_INLINE_SCRIPT_1}' 'sha256-{HASHED_INLINE_SCRIPT_2}' .

اسکریپت های منبع را به صورت پویا بارگیری کنید

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

نمونه ای از نحوه ورود به اسکریپت های خود.
مجاز توسط CSP
<script>
  var scripts = [ 'https://example.org/foo.js', 'https://example.org/bar.js'];

  scripts.forEach(function(scriptUrl) {
    var s = document.createElement('script');
    s.src = scriptUrl;
    s.async = false; // to preserve execution order
    document.head.appendChild(s);
  });
</script>
برای اینکه این اسکریپت اجرا شود ، باید هش اسکریپت درون خطی را محاسبه کرده و آن را به عنوان پاسخ CSP اضافه کنید ، و جایگزین مکان {HASHED_INLINE_SCRIPT} . برای کاهش میزان هش ها ، می توانید تمام اسکریپت های درون خطی را در یک اسکریپت واحد ادغام کنید. برای دیدن این کار در عمل ، به این مثال و کد آن مراجعه کنید.
مسدود شده توسط CSP
<script src="https://example.org/foo.js"></script>
<script src="https://example.org/bar.js"></script>
CSP این اسکریپت ها را مسدود می کند زیرا فقط اسکریپت های درون خطی قابل هشدار هستند.

ملاحظات بارگیری اسکریپت

مثال اسکریپت درون خطی s.async = false را اضافه می کند تا اطمینان حاصل شود که foo قبل از bar اجرا می شود ، حتی اگر bar ابتدا بارگذاری شود. در این قطعه ، s.async = false تجزیه کننده را مسدود نمی کند در حالی که اسکریپت ها بارگذاری می شوند ، زیرا اسکریپت ها به صورت پویا اضافه می شوند. تجزیه کننده فقط در حالی که اسکریپت ها اجرا می شوند ، متوقف می شود ، همانطور که برای اسکریپت های async . با این حال ، با این قطعه ، به خاطر داشته باشید:

  • ممکن است قبل از بارگیری سند ، یکی یا هر دو اسکریپت اجرا شود. اگر می خواهید این سند تا زمان اجرای اسکریپت ها آماده شود ، قبل از اینکه اسکریپت ها را ضمیمه کنید ، منتظر رویداد DOMContentLoaded باشید. اگر این مسئله باعث ایجاد مشکل می شود زیرا اسکریپت ها به اندازه کافی زود بارگیری را شروع نمی کنند ، از پیش بارگذاری از قبل در صفحه استفاده کنید.
  • defer = true کاری نمی کند. اگر به آن رفتار احتیاج دارید ، در صورت لزوم فیلمنامه را به صورت دستی اجرا کنید.

مرحله 3: الگوهای HTML Refactor و کد سمت مشتری

دستگیرندگان رویداد Inline (مانند onclick="…" ، onerror="…" ) و JavaScript Uris ( <a href="javascript:…"> ) می توانند برای اجرای اسکریپت ها استفاده شوند. این بدان معنی است که یک مهاجم که یک اشکال XSS پیدا می کند می تواند این نوع HTML را تزریق کند و JavaScript مخرب را اجرا کند. CSP غیر CE- یا هش ، استفاده از این نوع نشانه ها را ممنوع می کند. اگر سایت شما از هر یک از این الگوهای استفاده می کند ، باید آنها را به گزینه های امن تر تبدیل کنید.

اگر در مرحله قبل CSP را فعال کرده اید ، می توانید هر بار که CSP یک الگوی ناسازگار را مسدود می کند ، نقض CSP را در کنسول مشاهده کنید.

گزارش های نقض CSP در کنسول توسعه دهنده Chrome.
خطاهای کنسول برای کد مسدود شده.

در بیشتر موارد ، رفع ساده است:

دستگیرندگان رویداد refactor inline

مجاز توسط CSP
<span id="things">A thing.</span>
<script nonce="${nonce}">
  document.getElementById('things').addEventListener('click', doThings);
</script>
CSP اجازه می دهد تا دستیار رویداد که با استفاده از JavaScript ثبت شده اند.
مسدود شده توسط CSP
<span onclick="doThings();">A thing.</span>
CSP دستگیره های رویداد Inline را بلوک می کند.

Refactor javascript: Uris

مجاز توسط CSP
<a id="foo">foo</a>
<script nonce="${nonce}">
  document.getElementById('foo').addEventListener('click', linkClicked);
</script>
CSP اجازه می دهد تا دستیار رویداد که با استفاده از JavaScript ثبت شده اند.
مسدود شده توسط CSP
<a href="javascript:linkClicked()">foo</a>
CSP بلوک JavaScript: Uris.

eval() از JavaScript خود حذف کنید

اگر برنامه شما از eval() برای تبدیل سریال های رشته JSON به اشیاء JS استفاده می کند ، باید چنین مواردی را به JSON.parse() ، که سریعتر است ، مجدداً تغییر دهید.

اگر نمی توانید تمام کاربردهای eval() را حذف کنید ، هنوز هم می توانید یک CSP مبتنی بر Nonce را تنظیم کنید ، اما باید از کلمه کلیدی CSP 'unsafe-eval' استفاده کنید ، که این امر باعث می شود سیاست شما کمی امن تر شود.

شما می توانید این نمونه ها و نمونه های بیشتری از چنین اصلاح مجدد را در این CODELAB CSP دقیق پیدا کنید:

مرحله 4 (اختیاری): برای پشتیبانی از نسخه های مرورگر قدیمی ، فالزها را اضافه کنید

پشتیبانی مرورگر

  • کروم: 52.
  • لبه: 79.
  • Firefox: 52.
  • سافاری: 15.4.

منبع

اگر نیاز به پشتیبانی از نسخه های مرورگر قدیمی دارید:

  • استفاده از strict-dynamic نیاز به افزودن https: به عنوان یک بازپرداخت برای نسخه های قبلی Safari. وقتی این کار را انجام می دهید:
    • همه مرورگرهایی که از strict-dynamic پشتیبانی می کنند https: Fallback ، بنابراین این باعث کاهش قدرت این سیاست نمی شود.
    • در مرورگرهای قدیمی ، اسکریپت های خارج از کشور فقط در صورتی که از منشأ HTTPS بیایند ، بارگیری می شوند. این کمتر از یک CSP سخت امن است ، اما هنوز هم از برخی موارد متداول XSS مانند تزریق javascript: URIS.
  • برای اطمینان از سازگاری با نسخه های مرورگر بسیار قدیمی (4+ سال) ، می توانید به عنوان یک بازپرداخت unsafe-inline اضافه کنید. در صورت عدم وجود CSP یا هش ، همه مرورگرهای اخیر unsafe-inline نادیده گرفته می شوند.
Content-Security-Policy:
  script-src 'nonce-{random}' 'strict-dynamic' https: 'unsafe-inline';
  object-src 'none';
  base-uri 'none';

مرحله 5: CSP خود را مستقر کنید

پس از تأیید اینکه CSP شما هیچ اسکریپت قانونی را در محیط توسعه محلی شما مسدود نمی کند ، می توانید CSP خود را برای مرحله بندی و سپس به محیط تولید خود مستقر کنید:

  1. (اختیاری) CSP خود را در حالت فقط گزارش با استفاده از هدر Content-Security-Policy-Report-Only مستقر کنید. قبل از شروع اجرای محدودیت های CSP ، حالت فقط گزارش برای آزمایش یک تغییر بالقوه در حال شکستن مانند CSP جدید در تولید مفید است. در حالت فقط گزارش ، CSP شما بر رفتار برنامه شما تأثیر نمی گذارد ، اما مرورگر هنوز هم خطاهای کنسول و گزارش های نقض را هنگام برخورد با الگوهای ناسازگار با CSP شما ایجاد می کند ، بنابراین می توانید ببینید که چه چیزی برای کاربران نهایی شما شکسته است. برای اطلاعات بیشتر ، به گزارش API مراجعه کنید.
  2. هنگامی که اطمینان دارید که CSP شما سایت شما را برای کاربران نهایی خود نمی شکند ، CSP خود را با استفاده از هدر پاسخ Content-Security-Policy مستقر کنید. توصیه می کنیم CSP خود را با استفاده از یک سرور HTTP Header Side تنظیم کنید زیرا از یک برچسب <meta> ایمن تر است. پس از اتمام این مرحله ، CSP شما از برنامه شما از XSS محافظت می کند.

محدودیت ها

یک CSP دقیق به طور کلی یک لایه امنیتی قوی را فراهم می کند که به کاهش XSS کمک می کند. در بیشتر موارد ، CSP با رد الگوهای خطرناک مانند javascript: URIS ، سطح حمله را به میزان قابل توجهی کاهش می دهد. However, based on the type of CSP you're using (nonces, hashes, with or without 'strict-dynamic' ), there are cases where CSP doesn't protect your app as well:

  • If you nonce a script, but there's an injection directly into the body or the src parameter of that <script> element.
  • If there are injections into the locations of dynamically created scripts ( document.createElement('script') ), including into any library functions that create script DOM nodes based on the values of their arguments. This includes some common APIs such as jQuery's .html() , as well as .get() and .post() in jQuery < 3.0.
  • If there are template injections in old AngularJS applications. An attacker that can inject into an AngularJS template can use it to execute arbitrary JavaScript .
  • If the policy contains 'unsafe-eval' , injections into eval() , setTimeout() , and a few other rarely used APIs.

Developers and security engineers should pay particular attention to such patterns during code reviews and security audits. You can find more details on these cases in Content Security Policy: A Successful Mess Between Hardening and Mitigation .

در ادامه مطلب