CSP: سپر نامرئی که سایت شما را از هک نجات می‌دهد!

CSP: سپر نامرئی که سایت شما را از هک نجات می‌دهد!

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

Content-Security-Policy (CSP) یک هدر HTTP است که به مرورگر می‌گوید فقط از کدام منبع مجاز است اسکریپت، استایل، فونت یا تصویر بارگذاری شود. با این‌حال، بدون آن، مرورگر به هر کدی که در HTML صفحه ظاهر شود اعتماد می‌کند؛ فارغ از این‌که آن کد از سرور خودتان آمده یا از یک حمله تزریقی.

پاسخ کوتاه: پیاده‌سازی CSP یعنی تعریف صریح منابع مجاز اسکریپت و استایل در یک هدر HTTP. بهترین روش، شروع از حالت Report-Only برای جمع‌آوری داده واقعی است؛ سپس سیاست نهایی، ترجیحاً مبتنی بر نانس، به‌صورت اجرایی فعال می‌شود.

طبق گزارش امنیتی ۲۰۲۵ Web Almanac که هر سال میلیون‌ها سایت را بررسی می‌کند، فقط ۲۱.۹٪ از سایت‌ها اصلاً CSP دارند. بدتر این‌که از همین تعداد کم هم ۹۲٪ از unsafe-inline استفاده می‌کنند. این گزینه عملاً بیشتر محافظت واقعی CSP را خنثی می‌کند و پیاده‌سازی CSP را به یک اقدام صرفاً نمایشی تبدیل می‌کند.

چرا حمله تزریق اسکریپت هنوز رایج‌ترین راه نفوذ به سایت‌هاست؟

در واقع، حمله XSS (Cross-Site Scripting) به این معنی است که مهاجم کدی را از طریق یک ورودی ناامن (فرم، پارامتر URL، کامنت) وارد صفحه می‌کند. مرورگر قربانی، این کد را همان‌قدر اجرا می‌کند که کد اصلی سایت را. در نتیجه، این کد می‌تواند کوکی جلسه کاربر را بدزدد، فرم پرداخت را دستکاری کند یا کاربر را به یک صفحه فیشینگ هدایت کند.

در واقع، مشکل اصلی این نیست که تیم‌های توسعه تنبل‌اند؛ مشکل این است که پاک‌سازی ورودی (Sanitization) به‌تنهایی هرگز ۱۰۰٪ کامل نیست. همیشه یک مسیر فراموش‌شده، یک افزونه شخص‌ثالث، یا یک کتابخانه قدیمی وجود دارد که یک روزنه باز می‌گذارد.

چرا فقط اعتماد به کد پاک‌سازی‌شده کافی نیست؟

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

نکته فنی: به‌جای لیست‌کردن ده‌ها دامنه CDN و شخص‌ثالث در سیاست CSP، نسخه سوم این استاندارد راه بهتری دارد. با ترکیب nonce و strict-dynamic، فقط اسکریپت‌های دارای مجوز صریح (و هر چیزی که خودِ آن‌ها بارگذاری کنند) اجرا می‌شوند؛ روشی به‌مراتب مقاوم‌تر در برابر دور زدن سیاست.

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

ویژگیCSP Report-OnlyCSP اجرایی (Enforce)
نقشفقط گزارش نقض قانون، بدون مسدودسازیمسدودسازی واقعی منابع غیرمجاز
ریسک قطع‌شدن عملکرد سایتصفر — چیزی مسدود نمی‌شوددر صورت سیاست ناقص، ممکن است
هدر HTTP مربوطهContent-Security-Policy-Report-OnlyContent-Security-Policy
زمان مناسب استفادهمرحله تست و جمع‌آوری داده واقعیبعد از تأیید کامل سیاست

راهکاری که برای اکثر سایت‌های پویا (فروشگاه اینترنتی، پنل مدیریتی، وبلاگ با کامنت) بهترین تعادل امنیت و نگهداری را دارد، سیاست سخت‌گیرانه مبتنی بر نانس (Nonce-based Strict CSP) است. این رویکرد بسیار بهتر از صرفاً لیست‌کردن دامنه‌های مجاز عمل می‌کند.

مزایا

  • مقاوم در برابر بیشتر روش‌های شناخته‌شده دور زدن CSP
  • نیازی به نگهداری یک لیست طولانی و همیشه ناقص از دامنه‌های مجاز ندارد
  • با strict-dynamic، اسکریپت‌هایی که خودِ اسکریپت اصلی به‌صورت پویا بارگذاری می‌کند هم پوشش داده می‌شوند

معایب

  • نیاز به تغییر در Backend برای تولید یک نانس تصادفی و یکتا در هر درخواست
  • اسکریپت‌های inline قدیمی باید بازنویسی یا به فایل جدا منتقل شوند
  • برخی ابزار یا افزونه شخص‌ثالث قدیمی ممکن است با نانس سازگار نباشند

در واقع، تیم سنتیوا در پروژه‌های پیاده‌سازی CSP این مراحل را عملی می‌کند:

  • ممیزی کامل منابع فعلی سایت (اسکریپت، فونت، تصویر، آیفریم) برای ساخت لیست دقیق مبدأهای واقعاً مجاز
  • طراحی و اجرای مرحله Report-Only، همراه با پایش روزانه گزارش‌های نقض پیش از هر تصمیم نهایی
  • پیاده‌سازی نانس سمت سرور و بازنویسی اسکریپت‌های inline باقی‌مانده
  • نگهداری و به‌روزرسانی مستمر سیاست، هم‌زمان با هر ابزار یا اسکریپت شخص‌ثالث جدیدی که به سایت اضافه می‌شود

اصل طلایی پیاده‌سازی CSP: هیچ‌وقت مستقیم با حالت اجرایی شروع نکنید. حداقل یک تا دو هفته در حالت Report-Only داده واقعی جمع کنید و سیاست را بر همان اساس اصلاح کنید. فقط بعد از رسیدن گزارش‌های نقض به صفر، حالت اجرایی را فعال کنید.

سناریوی این راهنما: یک فروشگاه اینترنتی فرضی به آدرس shop-example.ir در نظر می‌گیریم. این سایت فایل‌های استاتیک را از CDN اختصاصی cdn.shop-example.ir، فونت را از Google Fonts، و ابزار تحلیل ترافیک را از Google Tag Manager بارگذاری می‌کند. گزارش‌های نقض هم در آدرس shop-example.ir/csp-reports جمع‌آوری می‌شوند. دقیقاً همین نام‌ها در تمام مراحل زیر تکرار می‌شوند تا کل راهنما یک واحد یکپارچه و قابل‌تطبیق باشد.

۱. فعال‌سازی حالت Report-OnlyHTTP Header — Content-Security-Policy-Report-Only
Content-Security-Policy-Report-Only: default-src 'self'; script-src 'self' cdn.shop-example.ir www.googletagmanager.com; style-src 'self' fonts.googleapis.com; font-src fonts.gstatic.com; img-src 'self' cdn.shop-example.ir data:; connect-src 'self' www.google-analytics.com; report-to csp-endpoint

این مرحله چه کاری انجام می‌دهد؟

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

۲. تعریف نقطه دریافت گزارشHTTP Header — Reporting-Endpoints
Reporting-Endpoints: csp-endpoint="https://shop-example.ir/csp-reports"

نقطه دریافت گزارش چه نقشی دارد؟

این هدر مشخص می‌کند مرورگر گزارش‌های نقض را دقیقاً به کجا بفرستد. با این‌حال، بدون این هدر (یا معادل قدیمی‌ترش، report-uri)، حالت Report-Only عملاً کور است؛ چون داده‌ای برای تحلیل جمع نمی‌شود.

۳. فعال‌سازی سیاست نهایی اجرایی مبتنی بر نانسHTTP Header — Content-Security-Policy
Content-Security-Policy: default-src 'self'; script-src 'nonce-{RANDOM}' 'strict-dynamic'; style-src 'self' fonts.googleapis.com; font-src fonts.gstatic.com; object-src 'none'; base-uri 'none'; frame-ancestors 'none'; report-to csp-endpoint

چرا این سیاست نهایی متفاوت است؟

در این مرحله، دیگر لیست دامنه در script-src نیست؛ فقط اسکریپت‌هایی با نانس صحیح اجرا می‌شوند. بنابراین، مقدار {RANDOM} باید یک رشته تصادفی و یکتا باشد که Backend در هر درخواست، از نو تولید می‌کند؛ هرگز یک نانس ثابت را در چند درخواست تکرار نکنید.

۴. استفاده از نانس در تگ اسکریپتHTML — تگ اسکریپت با نانس
<script nonce="{RANDOM}" src="/assets/checkout.js"></script>

مقدار {RANDOM} در تگ HTML باید دقیقاً همان مقداری باشد که در هدر همان درخواست فرستاده شده است. به همین دلیل، بعد از فعال‌سازی، نتیجه را حتماً در کنسول توسعه‌دهنده مرورگر بررسی کنید تا هیچ اسکریپت مجازی به‌اشتباه مسدود نشده باشد.

هرگز این کارها را در پیاده‌سازی CSP نکنید. مستقیم از حالت اجرایی شروع نکنید. unsafe-inline یا unsafe-eval را به‌عنوان راه‌حل دائمی نگه ندارید. فقط با متد تگ meta به سراغ CSP نروید، چون frame-ancestors و گزارش نقض در آن کار نمی‌کند. به میان‌افزار اجازه ندهید خودکار به همه اسکریپت‌های صفحه نانس بدهد. از هدرهای منسوخ X-Content-Security-Policy یا X-WebKit-CSP به‌جای هدر استاندارد استفاده نکنید.

یک نمونه معمول: فروشگاه اینترنتی متوسط

«وقتی حالت Report-Only را فعال کردیم، بعد از چند روز متوجه شدیم یکی از اسکریپت‌های تبلیغاتی شخص‌ثالث ما، بدون اطلاع تیم فنی، از یک دامنه ناشناخته بارگذاری می‌شد. اگر مستقیم حالت اجرایی را فعال کرده بودیم، یا سایت خراب می‌شد یا اصلاً متوجه این ریسک نمی‌شدیم.»

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

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

فوری (همین هفته)

  • فعال‌سازی CSP در حالت Report-Only با default-src 'self'
  • راه‌اندازی نقطه دریافت گزارش با هدر Reporting-Endpoints

کوتاه‌مدت (این ماه)

  • بررسی روزانه گزارش‌های نقض و افزودن منابع مجاز واقعی به سیاست
  • بازنویسی اسکریپت‌های inline باقی‌مانده با نانس سمت سرور

بلندمدت (مستمر)

  • فعال‌سازی نهایی حالت اجرایی و حذف کامل حالت Report-Only
  • بازبینی فصلی سیاست هم‌زمان با اضافه‌شدن هر ابزار یا اسکریپت شخص‌ثالث جدید

سوالات متداول تخصصی

آیا پیاده‌سازی CSP باعث کندشدن سایت می‌شود؟

نه. در واقع CSP فقط یک هدر HTTP است و مرورگر آن را بدون بار پردازشی محسوس بررسی می‌کند؛ تأخیر اضافه عملاً قابل اندازه‌گیری نیست.

تفاوت CSP Report-Only و CSP اجرایی چیست؟

حالت Report-Only فقط نقض‌ها را گزارش می‌کند بدون مسدودسازی؛ حالت اجرایی واقعاً منابع غیرمجاز را مسدود می‌کند. به همین دلیل، توصیه می‌شود همیشه اول Report-Only اجرا شود.

آیا CSP جایگزین فایروال وب (WAF) است؟

نه. در واقع CSP یک لایه دفاعی سمت مرورگر است که مکمل WAF عمل می‌کند، نه جایگزین آن. WAF ترافیک ورودی را فیلتر می‌کند؛ اما CSP اجرای کد در خروجی مرورگر را کنترل می‌کند.

برای سایت‌هایی با چند CDN و اسکریپت شخص‌ثالث، پیاده‌سازی CSP چطور انجام می‌شود؟

با شروع از حالت Report-Only، همه منابع واقعی مورد استفاده سایت شناسایی می‌شوند؛ سپس سیاست نهایی، ترجیحاً با نانس به‌جای لیست طولانی دامنه، ساخته می‌شود.

آیا یک افزونه آماده وردپرس برای CSP کافی است؟

افزونه‌های آماده می‌توانند نقطه شروع خوبی باشند، اما معمولاً نیاز به تنظیم دستی برای نانس و منابع خاص هر سایت دارند. بنابراین اتکای کامل بدون بازبینی، ریسک‌دار است.

پیاده‌سازی کامل CSP روی یک سایت متوسط چقدر طول می‌کشد؟

برای بیشتر سایت‌های متوسط با چند ابزار شخص‌ثالث، مسیر معمول شامل یک تا دو هفته حالت Report-Only و سپس فعال‌سازی تدریجی حالت اجرایی است. با این‌حال، این زمان به تعداد ابزارهای شخص‌ثالث سایت بستگی دارد.
  • پیاده‌سازی CSP، یک هدر HTTP است که تعیین می‌کند مرورگر فقط از کدام منابع مجاز است اسکریپت و استایل اجرا کند.
  • شروع همیشه باید از حالت Report-Only باشد؛ نه مستقیم حالت اجرایی.
  • سیاست مبتنی بر نانس (نه لیست طولانی دامنه) در برابر بیشتر روش‌های دور زدن CSP مقاوم‌تر است.
  • پیاده‌سازی CSP یک اقدام یک‌باره نیست؛ با هر ابزار شخص‌ثالث جدید باید بازبینی شود.
  • بدون این هدر، هر روزنه کوچک در پاک‌سازی ورودی می‌تواند به یک حمله کامل XSS تبدیل شود.

پیاده‌سازی CSP، سرمایه‌گذاری روی نامرئی‌ترین اما مؤثرترین لایه دفاعی وب‌سایت شماست.

منبع رایگان

«چک‌لیست پیاده‌سازی CSP» را رایگان دریافت کنید

همه مراحل، از Report-Only تا سیاست نهایی اجرایی، در یک چک‌لیست قابل‌چاپ.

یا تماس مستقیم

نوشته‌های مشابه