Content Security Policy در وردپرس چرا پیچیده است؟
CSP در وردپرس تعیین میکند چه منابعی مجاز به بارگذاری هستند و XSS را دفع میکند. چرا پیادهسازی اشتباه آن، سایت را کاملاً میشکند؟
در یک پروژه، بعد از پیادهسازی CSP، ویرایشگر گوتنبرگ از کار افتاد. بررسی نشان داد که گوتنبرگ از Inline Scripts و iframe استفاده میکند و CSP آنها را مسدود کرده بود. بعد از افزودن Nonce و Whitelist کردن Endpointهای REST API، ویرایشگر به حالت عادی بازگشت. این تجربه، پیچیدگی CSP در وردپرس را در یک کلمه خلاصه میکند: تعادل.
CSP چیست و چرا پیچیده است؟
Content Security Policy (CSP) یک هدر امنیتی HTTP است که به مرورگر میگوید چه منابعی (Script، Style، Image، Font، Frame) میتوانند بارگذاری شوند و از کدام مبدأ. این هدر، یکی از قویترین ابزارهای دفاع در برابر XSS است. اگر با Content Security Policy آشنا شده باشید، میدانید که این استاندارد از سال ۲۰۱۲ در حال توسعه است.
پیچیدگی CSP در وردپرس از چند جهت قابل تحلیل است. اول، Inline Scripts: وردپرس و بسیاری از افزونهها از Inline Scripts استفاده میکنند که CSP بهطور پیشفرض مسدود میکند. دوم، Inline Styles: قالبها و صفحهسازها از Inline Styles استفاده میکنند. سوم، منابع خارجی: سایتهای وردپرسی از CDN، Google Fonts، سرویسهای تحلیلی و دهها منبع خارجی دیگر استفاده میکنند. چهارم، افزونههای شخص ثالث: هر افزونه میتواند منابع خود را بارگذاری کند که مدیریت آنها در CSP پیچیده است. پنجم، ویرایشگر گوتنبرگ: گوتنبرگ از iframe، WebSocket، و REST API استفاده میکند که نیازمند Whitelist کردن است.
«CSP یک شمشیر دو لبه است: امنیت بالاتر، اما پیچیدگی پیکربندی که میتواند سایت را از کار بیندازد.»
اگر با هدرهای امنیتی HTTP و کاربرد آنها آشنا شده باشید، میدانید که CSP پیچیدهترین هدر امنیتی است. اگر با حمله XSS و روشهای جلوگیری آشنا شده باشید، میدانید که CSP مؤثرترین دفاع در برابر XSS است.
| چالش | علت | راهحل |
|---|---|---|
| Inline Scripts | وردپرس و افزونهها | Nonce یا Hash |
| Inline Styles | قالبها و صفحهسازها | unsafe-inline (موقت) |
| منابع خارجی | CDN، Fonts، Analytics | Whitelist کردن |
| ویرایشگر گوتنبرگ | iframe و REST API | Whitelist اختصاصی |
CSP چگونه از XSS جلوگیری میکند؟
XSS (Cross-Site Scripting) یک حمله است که در آن، مهاجم کد مخرب JavaScript را در صفحه تزریق میکند. اگر با حمله XSS و روشهای جلوگیری آشنا شده باشید، میدانید که سه نوع XSS وجود دارد: Stored، Reflected و DOM-based.
CSP از XSS به چند روش جلوگیری میکند:
روش اول: محدودسازی Script Sources. دستور script-src تعیین میکند که Scriptها از کدام مبدأ بارگذاری شوند. اگر مهاجم کد مخرب را از یک دامنه خارجی بارگذاری کند، مرورگر آن را مسدود مینماید.
روش دوم: مسدودسازی Inline Scripts. دستور script-src بهطور پیشفرض Inline Scripts را مسدود میکند. این یعنی اگر مهاجم کد مخرب را در HTML تزریق کند، مرورگر آن را اجرا نمیکند.
روش سوم: مسدودسازی eval. دستور script-src بهطور پیشفرض eval() را مسدود میکند. این یعنی اگر مهاجم از eval() برای اجرای کد استفاده کند، مرورگر آن را مسدود مینماید.
Content-Security-Policy: script-src 'self' https://trusted.cdn.com
این هدر، فقط Scriptهایی را مجاز میکند که از Same-Origin یا trusted.cdn.com بارگذاری شوند.
دستورات کلیدی CSP
CSP دهها دستور مختلف دارد که هرکدام یک نوع منبع را کنترل میکند. مهمترین دستورات:
دستور اول: default-src. مقدار پیشفرض برای تمام دستورات دیگر.
default-src 'self'
دستور دوم: script-src. کنترل منابع JavaScript.
script-src 'self' 'nonce-abc123'
دستور سوم: style-src. کنترل منابع CSS.
style-src 'self' 'unsafe-inline'
دستور چهارم: img-src. کنترل منابع تصویر.
img-src 'self' data: https:
دستور پنجم: font-src. کنترل منابع فونت.
font-src 'self' https://fonts.gstatic.com
دستور ششم: connect-src. کنترل درخواستهای Fetch و XHR.
connect-src 'self' https://api.example.com
دستور هفتم: frame-ancestors. کنترل iframeهای والد.
frame-ancestors 'self'
دستور هشتم: form-action. کنترل مقصد فرمها.
form-action 'self'
دستور نهم: base-uri. کنترل تگ <base>.
base-uri 'self'
دستور دهم: object-src. کنترل Pluginها و Embedها.
object-src 'none'
ترکیب چند دستور:
Content-Security-Policy: default-src 'self'; script-src 'self' 'nonce-abc123'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' https://fonts.gstatic.com; connect-src 'self'; frame-ancestors 'self'; form-action 'self'; base-uri 'self'; object-src 'none'
اگر با استانداردهای امنیت وب آشنا شده باشید، این ترکیب را بهعنوان یک CSP پایه میشناسید.
چالشهای CSP در وردپرس
وردپرس چند ویژگی دارد که CSP را پیچیده میکند:
چالش اول: Inline Scripts در هسته. وردپرس از Inline Scripts در چند جا استفاده میکند: wp_localize_script، wp_add_inline_script، و wp_add_inline_style. این Inline Scriptها با CSP مسدود میشوند.
چالش دوم: Inline Styles در قالبها. بسیاری از قالبها و صفحهسازها از Inline Styles استفاده میکنند. اگر با چرا قالبهای بلاکی آینده وردپرس هستند آشنا شده باشید، میدانید که قالبهای بلاکی نیز از Inline Styles استفاده میکنند.
چالش سوم: منابع خارجی. سایتهای وردپرسی از CDN، Google Fonts، Google Analytics و دهها سرویس خارجی استفاده میکنند.
چالش چهارم: ویرایشگر گوتنبرگ. گوتنبرگ از iframe، WebSocket و REST API استفاده میکند که نیازمند Whitelist کردن است.
چالش پنجم: افزونههای شخص ثالث. هر افزونه میتواند منابع خود را بارگذاری کند و مدیریت آنها در CSP پیچیده است.
«CSP در وردپرس یک پروژه مستمر است، نه یک پیکربندی یکباره. هر افزونه جدید میتواند CSP را بشکند.»
Nonce و Hash: راهحل Inline Scripts
Nonce و Hash دو راهحل برای مجاز کردن Inline Scripts در CSP هستند. هرکدام مزایا و معایب خاص خود را دارند.
Nonce. یک مقدار تصادفی است که در هر درخواست تولید میشود و در هدر CSP و در تگ <script> قرار میگیرد:
Content-Security-Policy: script-src 'nonce-abc123'
<script nonce="abc123">
console.log( 'Allowed' );
</script>
مزایا: انعطافپذیری بالا، امکان استفاده از Inline Scripts پویا. معایب: نیازمند تولید Nonce در هر درخواست و تزریق آن در تمام Inline Scriptها.
در وردپرس، میتوان Nonce را با فیلتر script_loader_tag تزریق کرد:
add_filter( 'script_loader_tag', function( $tag, $handle, $src ) {
$nonce = wp_create_nonce( 'csp_nonce' );
return str_replace( '<script ', '<script nonce="' . $nonce . '" ', $tag );
}, 10, 3 );
Hash. یک هش رمزنگاریشده از محتوای Script است که در هدر CSP قرار میگیرد:
Content-Security-Policy: script-src 'sha256-abc123...'
<script>
console.log( 'Allowed' );
</script>
مزایا: نیازی به تولید Nonce در هر درخواست نیست. معایب: هر تغییر در محتوای Script، هش را باطل میکند.
اگر با Subresource Integrity در وردپرس آشنا شده باشید، میدانید که Hash در SRI و CSP مشابه است.
پیادهسازی گامبهگام در وردپرس
پیادهسازی CSP در وردپرس در چند گام انجام میشود:
گام اول: شروع با Report-Only. ابتدا CSP را در حالت Report-Only فعال کنید تا تخلفات را بدون مسدودسازی شناسایی نمایید:
add_action( 'send_headers', function() {
header( 'Content-Security-Policy-Report-Only: default-src \'self\'; report-uri /csp-report' );
} );
گام دوم: پایش تخلفات. تخلفات را در Console مرورگر و در Endpoint گزارشگیری بررسی کنید.
گام سوم: Whitelist کردن منابع. بر پایه تخلفات، منابع مجاز را به CSP اضافه کنید:
Content-Security-Policy:
default-src 'self';
script-src 'self' 'unsafe-inline' https://cdn.example.com;
style-src 'self' 'unsafe-inline' https://fonts.googleapis.com;
font-src 'self' https://fonts.gstatic.com;
img-src 'self' data: https:;
connect-src 'self' https://api.example.com;
frame-ancestors 'self'
گام چهارم: حذف unsafe-inline. بعد از شناسایی تمام Inline Scripts، آنها را با Nonce یا Hash جایگزین کنید و unsafe-inline را حذف نمایید.
گام پنجم: تغییر به حالت اجرا. بعد از تست کامل، CSP را از Report-Only به حالت اجرا تغییر دهید.
اگر با روشهای افزایش امنیت وبسایت آشنا شده باشید، این گامها برای شما آشناست.
CSP Report-Only و مهاجرت تدریجی
CSP Report-Only یک حالت است که در آن، CSP اجرا میشود اما منابع مسدود نمیشوند، فقط گزارش میشوند. این حالت، برای مهاجرت تدریجی ایدهآل است.
Content-Security-Policy-Report-Only: default-src 'self'; report-uri /csp-report
استراتژی مهاجرت:
- هفته اول: Report-Only با CSP ساده.
- هفته دوم: تحلیل تخلفات و Whitelist کردن منابع.
- هفته سوم: حذف unsafe-inline و استفاده از Nonce.
- هفته چهارم: تغییر به حالت اجرا.
- هفته پنجم به بعد: پایش مستمر و تنظیم.
اگر با Real User Monitoring و اهمیت آن آشنا شده باشید، میدانید که پایش مستمر بخشی از این استراتژی است.
Reporting و تحلیل تخلفات
CSP Reporting یک مکانیزم است که در آن، مرورگر تخلفات را به یک Endpoint ارسال میکند. این مکانیزم، برای شناسایی منابع مسدودشده حیاتی است.
Content-Security-Policy: default-src 'self'; report-uri /csp-report; report-to csp-endpoint
Endpoint گزارشگیری در وردپرس:
add_action( 'rest_api_init', function() {
register_rest_route( 'csp/v1', '/report', array(
'methods' => 'POST',
'callback' => function( $request ) {
$report = $request->get_json_params();
error_log( print_r( $report, true ) );
return new WP_REST_Response( null, 204 );
},
'permission_callback' => '__return_true',
) );
} );
اگر با روشهای امنسازی REST API آشنا شده باشید، این Endpoint باید با Rate Limiting محافظت شود.
Strict CSP و Nonce-based Approach
Strict CSP یک رویکرد است که در آن، فقط منابع مجاز با Nonce یا Hash بارگذاری میشوند و unsafe-inline حذف میشود. این رویکرد، بالاترین امنیت را فراهم میکند.
Content-Security-Policy:
default-src 'none';
script-src 'nonce-abc123' 'strict-dynamic';
style-src 'nonce-def456';
img-src 'self' data:;
font-src 'self';
connect-src 'self';
base-uri 'none';
form-action 'none';
frame-ancestors 'none';
object-src 'none'
دستور strict-dynamic یک ویژگی پیشرفته است که به Nonce اجازه میدهد به Scriptهای Child نیز اعتماد کند. این دستور، در سایتهایی که از Loaderهای پویا استفاده میکنند مفید است.
اشتباهات رایج در پیادهسازی CSP
اشتباه اول: شروع با حالت اجرا بهجای Report-Only. اگر CSP مستقیم در حالت اجرا فعال شود، سایت ممکن است از کار بیفتد. راهحل: شروع با Report-Only.
اشتباه دوم: استفاده دائمی از unsafe-inline. این دستور، امنیت CSP را بهشدت کاهش میدهد. راهحل: جایگزینی با Nonce یا Hash.
اشتباه سوم: Whitelist کردن unsafe-eval. این دستور، امنیت را کاهش میدهد. راهحل: حذف eval() از کد.
اشتباه چهارم: فراموش کردن frame-ancestors. این دستور، از Clickjacking جلوگیری میکند. راهحل: تنظیم frame-ancestors 'self'.
اشتباه پنجم: Whitelist کردن دامنههای عمومی. اگر https: را Whitelist کنید، امنیت CSP کاهش مییابد. راهحل: Whitelist کردن دامنههای خاص.
اشتباه ششم: عدم مدیریت Nonce. Nonce باید در هر درخواست تولید شود و در تمام Inline Scriptها تزریق گردد. راهحل: استفاده از فیلترهای وردپرس.
اشتباه هفتم: فراموش کردن ویرایشگر گوتنبرگ. گوتنبرگ از iframe و REST API استفاده میکند. راهحل: Whitelist کردن این Endpointها.
اشتباه هشتم: عدم پایش مستمر. CSP نیازمند پایش مستمر است چون هر افزونه جدید میتواند تخلف ایجاد کند.
پرسشهای پرتکرار درباره CSP
CSP چیست و چرا در وردپرس پیچیده است؟
CSP یک هدر امنیتی است که منابع مجاز بارگذاری را تعریف میکند. در وردپرس پیچیده است چون وردپرس و افزونهها از Inline Scripts و Inline Styles استفاده میکنند، سایتها از منابع خارجی زیاد استفاده میکنند، و ویرایشگر گوتنبرگ نیازمند Whitelist کردن است.
چگونه CSP را در وردپرس پیادهسازی کنم؟
پنج گام: اول، Report-Only فعال کنید. دوم، تخلفات را پایش کنید. سوم، منابع مجاز را Whitelist کنید. چهارم، unsafe-inline را با Nonce جایگزین کنید. پنجم، به حالت اجرا تغییر دهید.
Nonce و Hash چه تفاوتی دارند؟
Nonce یک مقدار تصادفی است که در هر درخواست تولید میشود و انعطافپذیری بالایی دارد. Hash یک هش از محتوای Script است که ثابت است و هر تغییر در Script آن را باطل میکند.
آیا CSP بر سرعت سایت تأثیر میگذارد؟
تأثیر منفی ندارد. CSP فقط یک سیاست امنیتی است و در مرورگر اعمال میشود. اما اگر CSP نادرست باشد، میتواند منابع را مسدود کند و تجربه کاربری را مختل کند.
آیا CSP با ویرایشگر گوتنبرگ سازگار است؟
بله، اما باید iframe، REST API و WebSocket را Whitelist کنید. توصیه میشود CSP را برای صفحات Admin تنظیم نکنید یا از CSP مخصوص استفاده کنید.
آیا CSP با WooCommerce کار میکند؟
بله، اما باید Endpointهای WooCommerce، درگاههای پرداخت و سرویسهای تحلیلی را Whitelist کنید.
چگونه تخلفات CSP را تحلیل کنم؟
از Report-Only Mode برای جمعآوری تخلفات، از Console مرورگر برای مشاهده خطاها، و از یک Endpoint Reporting برای ثبت تخلفات در دیتابیس استفاده کنید.
آیا CSP جایگزین XSS Prevention است؟
خیر، CSP یک لایه دفاعی است، نه جایگزین. برای جلوگیری کامل از XSS، باید Sanitization، Escaping، و CSP را ترکیب کنید.
آیا CSP برای همه سایتها ضروری است؟
بله، برای همه سایتها توصیه میشود. حتی اگر سایت شما محتوای حساس ندارد، XSS میتواند برای سرقت Session و تزریق کد مخرب استفاده شود.
آیا CSP بر SEO تأثیر میگذارد؟
تأثیر مستقیمی ندارد اما بخشی از امنیت فنی است. اگر با سئو تکنیکال و اهمیت آن آشنا شده باشید، میدانید که امنیت یکی از سیگنالهای رتبهبندی است.
تحلیل معمارانه سطح ارشد
از منظر معماری نرمافزار، CSP یک نمونه از Policy-Based Security Enforcement است: بهجای اعتماد به کد اپلیکیشن، مرورگر یک سیاست امنیتی را اجرا میکند. این رویکرد، در معماریهای مدرن به یک اصل تبدیل شده: از Zero-Trust تا Principle of Least Privilege.
چالش اصلی، Legacy Code Compatibility است: وردپرس و بسیاری از افزونهها از الگوهای قدیمی (مثل Inline Scripts) استفاده میکنند که با CSP در تضاد هستند. راهحل، مهاجرت تدریجی با Nonce و Hash است.
چالش دوم، Third-Party Integration است: هر افزونه جدید میتواند منابع خارجی جدیدی اضافه کند که CSP را میشکند. راهحل، استفاده از Automated Reporting و پایش مستمر است.
چالش سوم، Trade-off بین امنیت و قابلیت است: CSP سختگیرانه، امنیت بالاتر اما قابلیت کمتر. راهحل، استفاده از Strict CSP with Nonce است که تعادل مناسبی فراهم میکند.
چالش چهارم، Observability است: اگر CSP منبعی را مسدود کند، چگونه میتوان فهمید؟ راهحل، استفاده از Reporting API و ترکیب آن با RUM. اگر با Real User Monitoring و اهمیت آن آشنا شده باشید، این ترکیب را بهعنوان یک رویکرد حرفهای میشناسید.
در نهایت، CSP یک Evolution است، نه یک Revolution. این هدر، تکامل طبیعی معماری امنیتی وب است: از کنترل متمرکز به کنترل توزیعشده، از اعتماد کامل به کد به تأیید هر منبع. تیمهایی که این رویکرد را در فرهنگ خود نهادینه میکنند، سیستمهایی میسازند که در برابر طیف گستردهای از حملات مقاوم هستند. اگر با طراحی معماری وب مقیاسپذیر آشنا شده باشید، این رویکرد را بهعنوان یک اصل مهندسی میشناسید.
اگر این تجربه را در یک پروژه واقعی داشتهاید، جالب است بدانید کدام جنبه از CSP بیشترین چالش را ایجاد کرد. تجربه خودتان را در دیدگاهها بنویسید؛ بهخصوص اگر راهحل دیگری پیدا کردهاید که میتواند برای خواننده بعدی مفید باشد. 🔒