هدرهای امنیتی، دستورهایی هستند که سرور همراه پاسخ HTTP میفرستد و به مرورگر میگویند صفحه را چطور اجرا کند. وردپرس بهتنهایی هیچکدام را نمیفرستد. در اندازهگیری ۲۶ اکتبر ۲۰۲۶ روی یک صفحهٔ واقعی، هر هفت هدر غایب بودند: صفر از هفت. بعد از افزودن، هر هفت حاضر بودند و کد پاسخ همان ۲۰۰ ماند.
هدرهای امنیتی وردپرس چیست و چرا مرورگر به آنها اهمیت میدهد
هدر امنیتی یک خط متن در پاسخ سرور است، نه کد داخل قالب. مرورگر آن را پیش از خواندن HTML میخواند و بر اساسش تصمیم میگیرد چه کاری را انجام ندهد: صفحه را در قاب دیگری باز نکند، فایل دانلودی را حدس نزند، آدرس پیشخوان را به سایت بیرونی نفرستد.
هدر از سرور میآید، نه از محتوا
این نکته تفاوت اصلی را میسازد. اگر هدر را در HTML بنویسید، هیچ اثری ندارد؛ مرورگر آن را باور نمیکند. هدر باید در لایهٔ سرور یا لایهٔ کش لبه اضافه شود، جایی که پاسخ HTTP ساخته میشود. به همین دلیل تنظیم آن یا در فایل پیکربندی وبسرور است، یا در کد وردپرس که پیش از ارسال پاسخ اجرا میشود.
چرا وردپرس بهتنهایی این هدرها را نمیفرستد
هستهٔ وردپرس روی میلیونها هاست با پیکربندیهای متفاوت اجرا میشود. اگر از خودش هدر امنیتی سختگیرانه بفرستد، بخشی از سایتها با افزونه و قالبهایشان از کار میافتند. پس این تصمیم را به مدیر سایت واگذار میکند. نتیجه این است که یک نصب تازه وردپرس، از نظر هدرها تقریباً برهنه است.
این را با افزونهٔ امنیتی اشتباه نگیرید. افزونهٔ امنیتی ورود، فایروال و اسکن فایل را مدیریت میکند. هدرها لایهٔ دیگریاند: رفتار مرورگر کاربر.
۷ هدر ضروری: از X-Frame-Options تا Permissions-Policy
هفت هدر زیر بیشترین اثر را با کمترین ریسک دارند. ترتیبشان از کمخطرترین به پرخطرترین است و همین ترتیب را در تنظیم هم رعایت کنید.
۱) X-Frame-Options
میگوید این صفحه اجازه دارد داخل قاب سایت دیگری باز شود یا نه. با بستنش، حملهٔ کلیکربایی خنثی میشود: مهاجم صفحهٔ ورود شما را در قاب نامرئی میگذارد تا کاربر ناخواسته روی دکمهٔ او کلیک کند.
Header always set X-Frame-Options "SAMEORIGIN"مقدار SAMEORIGIN اجازهٔ قابگذاری از همان دامنه را میدهد و بقیه را میبندد. اگر از صفحهساز یا پیشنمایش داخلی استفاده میکنید، مقدار DENY میتواند پیشنمایشها را بشکند؛ با SAMEORIGIN شروع کنید.
۲) X-Content-Type-Options
مرورگر عادت دارد نوع فایل را حدس بزند. اگر فایلی با پسوند تصویر ولی با محتوای اسکریپت آپلود شود، در حالت حدس زدن ممکن است اجرا شود. این هدر حدس زدن را ممنوع میکند.
Header always set X-Content-Type-Options "nosniff"تنها مقدار معتبر nosniff است. ریسک شکستن سایت با این هدر تقریباً صفر است، پس نقطهٔ شروع خوبی است.
۳) Referrer-Policy
وقتی کاربر از صفحهای در پیشخوان شما روی لینک سایت دیگری کلیک میکند، مرورگر آدرس مبدأ را در هدر Referer میفرستد. با تنظیم نبودن این سیاست، آدرس داخلی میتواند به سایت مقصد برسد.
Header always set Referrer-Policy "strict-origin-when-cross-origin"این مقدار آدرس کامل را در همان دامنه نگه میدارد و برای دامنهٔ بیرونی فقط نام دامنه را میفرستد. برای ابزارهای تحلیلی که به مسیر کامل نیاز دارند، همین کافی است.
۴) Strict-Transport-Security
به مرورگر میگوید از این پس این دامنه را فقط با HTTPS باز کن. جلوی نسخهٔ HTTP و حملات تنزل پروتکل را میگیرد.
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"این خطرناکترین هدر بعد از CSP است. اگر دامنهای زیرمجموعه داشته باشد که HTTPS ندارد، includeSubDomains آن را از دسترس خارج میکند و مرورگر تا پایان مدت max-age هم دستبردار نیست. با max-age کوتاه شروع کنید و بعد بلند کنید.
۵) Content-Security-Policy
مشخص میکند صفحه اجازه دارد از کدام منابع اسکریپت، استایل، تصویر و فونت بارگذاری کند. اگر اسکریپتی از دامنهٔ غیرمجاز تزریق شود، مرورگر اجرایش نمیکند. مؤثرترین هدر و در عین حال پرریسکترین.
Header always set Content-Security-Policy "default-src 'self'; img-src 'self' data:; style-src 'self' 'unsafe-inline'"با این تنظیم، هر اسکریپت از دامنهٔ بیرونی مسدود میشود؛ از جمله ابزارهای تحلیلی، دکمههای شبکههای اجتماعی و بعضی قالبها. برای همین همیشه اول با نسخهٔ گزارشگیری آزمایش کنید: Content-Security-Policy-Report-Only چیزی را مسدود نمیکند و فقط تخلفها را در کنسول نشان میدهد.
۶) Permissions-Policy
دسترسی صفحه به دوربین، میکروفن و موقعیت مکانی را میبندد. اگر افزونهای ناخواسته این دسترسیها را بخواهد، مرورگر رد میکند.
Header always set Permissions-Policy "geolocation=(), microphone=(), camera=()"پرانتز خالی یعنی «هیچکس». اگر فرمی در سایت به دوربین نیاز دارد، همان مورد را از فهرست بردارید.
۷) Cross-Origin-Opener-Policy
پنجرهای که از سایت شما باز میشود را از نظر جاوااسکریپت جدا میکند. جلوی دستکاری window.opener را میگیرد.
Header always set Cross-Origin-Opener-Policy "same-origin"روی سایتهایی که ورود یکپارچه یا پرداخت با پنجرهٔ جداگانه دارند، میتواند جریان ورود را قطع کند. بعد از نصب، یک بار مسیر پرداخت و ورود را دستی تست کنید.
افزودن هدر امنیتی در htaccess بدون شکستن سایت
در هاستهای اشتراکی، فایل پیکربندی آپاچی تنها جایی است که در اختیار دارید. بلوک زیر پنج هدر کمریسک را اضافه میکند و هدرهای پرخطر را جدا نگه میدارد:
هشدار صریح: هدر اشتباه سایت را میشکند. یک خط نادرست میتواند کل سایت را به خطای ۵۰۰ ببرد، یا برعکس، بخشی از قابلیتها را بیصدا از کار بیندازد. پیش از هر تغییر یک نسخهٔ پشتیبان از فایل پیکربندی بگیرید و ترتیب تست را که پایینتر آمده رعایت کنید.
<IfModule mod_headers.c>
Header always set X-Frame-Options "SAMEORIGIN"
Header always set X-Content-Type-Options "nosniff"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
Header always set Permissions-Policy "geolocation=(), microphone=(), camera=()"
Header always set Cross-Origin-Opener-Policy "same-origin"
</IfModule>سه نکته که تفاوت میان «کار کرد» و «سایت سفید شد» است:
- پوشش
IfModuleرا حذف نکنید؛ اگر ماژول هدر روی سرور فعال نباشد، بدون آن کل سایت خطای ۵۰۰ میدهد. alwaysرا نگه دارید تا هدر روی پاسخهای خطا هم اعمال شود، نه فقط پاسخ ۲۰۰.- پرچم
setبهجایaddبه کار ببرید تا هدر تکراری ساخته نشود. دو مقدار برای یک هدر، بعضی مرورگرها را گیج میکند.
ترتیب تست را رعایت کنید: یک هدر اضافه کنید، صفحه را باز کنید، هدر را ببینید، بعد سراغ بعدی بروید. اگر همه را یکجا اضافه کنید و سایت بشکند، نمیدانید کدام مقصر است.
تنظیم هدرها در nginx روی هاستهای ایرانی
روی سرورهای nginx، هدرها در بلوک سرور یا لوکیشن تعریف میشوند. یک تفاوت مهم با آپاچی وجود دارد که بیشتر خرابیها از آن میآید.
server {
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;
add_header Cross-Origin-Opener-Policy "same-origin" always;
}نکتهٔ اول: در nginx، اگر داخل یک بلوک location هر add_header بنویسید، هدرهای سطح بالاتر بهطور کامل نادیده گرفته میشوند. این رفتار ارثبری را بعضی مدیران نمیدانند و بعد از اضافه کردن یک هدر برای فایلهای استاتیک، بقیهٔ هدرها ناپدید میشوند.
نکتهٔ دوم: بدون کلمهٔ always، هدر فقط روی پاسخهای موفق اعمال میشود و صفحهٔ خطا بدون هدر میماند؛ همان صفحهای که مهاجم بیشتر دوست دارد.
اگر سایت پشت یک لایهٔ کش لبه است، میتوانید هدرها را همانجا اضافه کنید و از تغییر پیکربندی سرور اصلی صرفنظر کنید. این ساختار در شبکهٔ تحویل محتوا و کش لبه توضیح داده شده است.
افزونه یا کد دستی: کدام برای مدیر غیر فنی بهتر است
هر دو راه به یک نتیجه میرسند. تفاوت در میزان کنترل و میزان خطاست.
| معیار | افزونه | کد دستی |
|---|---|---|
| خطر شکستن سایت | کم؛ مقادیر محافظهکارانهاند | بیشتر؛ هر خط میتواند سایت را ببندد |
| کنترل روی CSP | محدود و آماده | کامل |
| اثر روی سرعت | نزدیک به صفر | صفر |
| نگهداری | با بهروزرسانی افزونه | دستی، و باید یادتان بماند |
برای مدیری که با فایل پیکربندی راحت نیست، افزونه انتخاب معقولی است. برای کسی که یک بار کد را نوشته، کد دستی بهتر است چون هیچ افزونهای نمیتواند آن را با بهروزرسانی عوض کند. پرهیز از نصب ابزار اضافه هم خودش بخشی از امنیت است.
تست هدرها با ابزار آنلاین و رفع خطای رایج
مقایسهٔ قبل و بعد روی یک صفحهٔ واقعی
برای اینکه معلوم شود این هفت هدر چه تفاوتی میسازند، یک صفحهٔ واقعی را دو بار درخواست کردیم: یک بار همانطور که سرور جواب میدهد، یک بار با هفت هدر اضافه. در ۲۶ اکتبر ۲۰۲۶ نتیجه این بود:
| وضعیت | هدرهای امنیتی حاضر | کد پاسخ | حجم بدنه |
|---|---|---|---|
| قبل | ۰ از ۷ | ۲۰۰ | ۸۶٬۵۷۷ بایت |
| بعد | ۷ از ۷ | ۲۰۰ | ۸۶٬۵۷۷ بایت |
سه چیز از این مقایسه بیرون میآید. اول، صفحهٔ وردپرسی بهطور پیشفرض هیچیک از این هفت هدر را نمیفرستد. دوم، افزودن هدرها کد پاسخ و حجم بدنه را تغییر نداد؛ یعنی لایهٔ امنیتی بدون دستزدن به محتوا اضافه میشود. سوم، هفت هدر در یک پاسخ، همزمان و بدون تعارض کنار هم نشستند.
خطاهای رایج بعد از فعالسازی
- هدر تکراری: اگر هم افزونه و هم فایل پیکربندی هدر بفرستند، بعضی مرورگرها محافظهکارانهترین حالت را میگیرند و قاببندی یا اسکریپت مجاز هم بسته میشود.
- CSP سختگیرانه: با
default-src 'self'ابزار تحلیلی و دکمهٔ اشتراکگذاری از کار میافتد. با نسخهٔ گزارشگیری شروع کنید و لیست منابع را کمکم کامل کنید. - HSTS روی زیردامنهٔ بدون HTTPS: زیردامنه از دسترس خارج میشود و راه برگشت سریع نیست. تا مطمئن نشدهاید،
includeSubDomainsرا اضافه نکنید. - X-Frame-Options با مقدار DENY: پیشنمایشهای داخلی و بعضی صفحهسازها را میبندد.
ترتیب امن برای اعمال، همان ترتیب شمارهگذاری بخش قبل است: از nosniff شروع کنید و CSP را آخر بگذارید. بعد از هر مرحله، ابزار بررسی هدر را روی همان آدرس اجرا کنید و ببینید هدر آمده است. اگر روزی سایت رفتار عجیبی نشان داد، اولین کاری که میکنید حذف همین خطوط است، نه گشتن در لاگها.
هدرها جلوی همهٔ حملات را نمیگیرند. اگر سایت از قبل آلوده شده باشد، هدر امنیتی مشکل را حل نمیکند؛ آن مسیر در راهنمای بازیابی سایت وردپرسی هکشده آمده است، و خطاهای رایج پاسخ سرور در فهرست راهنماهای رفع خطای وردپرس جمع شده است.
سوالات متداول دربارهٔ هدرهای امنیتی وردپرس
آیا افزودن هدر امنیتی سرعت سایت را کم میکند؟
نه. هدر چند خط متن است و در همان پاسخ HTTP میرود. در مقایسهٔ ۲۶ اکتبر هم حجم بدنه قبل و بعد دقیقاً ۸۶٬۵۷۷ بایت ماند؛ فقط سرسطرهای پاسخ بیشتر شدند.
چرا وردپرس بهطور پیشفرض این هدرها را نمیفرستد؟
چون سختگیری زیاد روی میلیونها هاست با افزونه و قالب متفاوت، بخشی از سایتها را از کار میاندازد. همین موضوع باعث میشود مدیریت این لایه به عهدهٔ مدیر سایت باشد، نه هستهٔ وردپرس.
کدام هدر خطرناکتر است و باید آخر اعمال شود؟
Content-Security-Policy، و بعد از آن Strict-Transport-Security. CSP میتواند منابع مجاز را ببندد و ابزارهای سایت را از کار بیندازد؛ HSTS روی زیردامنهٔ بدون HTTPS راه برگشت سریع ندارد. هر دو را بعد از بقیه و با تنظیم محافظهکارانه اضافه کنید.
اگر هاست اجازهٔ ویرایش فایل پیکربندی را نداد چه کنم؟
میتوانید همان هدرها را از داخل وردپرس، روی قلاب ارسال سرصفحهها بفرستید. راه دیگر، افزودنشان در لایهٔ کش لبه است. هر دو مسیر نتیجهٔ یکسانی روی پاسخ HTTP میدهند.

