Security Headers בוורדפרס מוסיפים שכבת הגנה נוספת מפני מתקפות נפוצות, בלי שתצטרכו להוסיף או לשנות דבר בקוד האפליקציה שלכם.
לאבטחת אתרים או אפליקציות Web יש כמה היבטים שצריך לקחת בחשבון. נקודת פתיחה טובה לחיזוק אבטחת אתרי וורדפרס היא הוספת Security Headers. Security Headers חסרים הם אחד הממצאים הנפוצים ביותר בדו"חות pentest של וורדפרס.
מה הם Security Headers?
Security Headers הם כותרות תגובה (HTTP Response Headers) שמורות לדפדפן איך להתנהג כשהוא מטפל בתוכן האתר שלכם. הם עוזרים למנוע מתקפות שונות, כולל Clickjacking, Cross-Site Scripting (XSS) והתקפות שדרוג פרוטוקול, על ידי הגבלת הפעולות שהדפדפן רשאי לבצע.
בפוסט זה נעבור על ה-Security Headers החשובים ביותר ונראה איך להוסיף אותם לאתר שלכם, בין אם אתם מריצים שרת Apache ובין אם שרת NGINX.
חשוב לציין כי ההגדרות שמופיעות בפוסט זה אינן בהכרח מתאימות לכל אתר. בדקו כל header בנפרד, וודאו שאין שגיאות בקונסול אחרי כל שינוי (כמובן).
הגדרה שגויה של Security Headers עלולה לגרום לשגיאת שרת 500 או לשבור חלקים באתר. בצעו תמיד גיבוי של קובץ .htaccess או nginx.conf לפני ביצוע שינויים, וודאו שיש לכם גישת FTP או מנהל קבצים, בכדי שתוכלו לשחזר אם האתר נופל.
למידע מעמיק על כל header והפרמטרים שלו, ראו את תיעוד MDN בנושא HTTP Security Headers.
Security Headers מומלצים
אפשר לחלק את ה-headers לשתי קבוצות. הבסיס הבטוח (X-Content-Type-Options, X-Frame-Options, Referrer-Policy, X-XSS-Protection ו-HSTS שמרני) עובד כמעט בכל אתר וורדפרס, ולרוב אינו שובר דבר.
ה-headers המתקדמים (Content-Security-Policy, Permissions-Policy וה-headers מסוג cross-origin) חזקים יותר, אבל עלולים לשבור פונקציונליות אמיתית, כמו הטמעות צד שלישי, תשלום מהיר, התחברות דרך רשתות חברתיות ונכסים מ-CDN, ולכן כדאי לבדוק כל אחד מהם לפני שאתם מסתמכים עליו.
א. HTTP Strict Transport Security (HSTS)
HTTP Strict Transport Security (HSTS) מורה לדפדפנים להתחבר לאתר שלכם רק דרך HTTPS, ולעולם לא דרך HTTP רגיל. מדובר בהגנה שמונעת התקפות שדרוג פרוטוקול וגניבת Cookies.
האתר שלכם צריך כבר לפעול עם תעודת SSL תקינה ובאופן מלא על HTTPS לפני הפעלת HSTS.
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;הערך max-age=31536000 אומר שהדפדפן יזכור את המדיניות למשך שנה. ההנחיה includeSubDomains מחילה את אותה מדיניות גם על כל תתי-הדומיינים, לכן השתמשו בה רק אם כולם תומכים ב-HTTPS.
מגדירים HSTS בפעם הראשונה? התחילו עם max-age קצר, למשל 300 עבור 5 דקות, והגדילו אותו בהדרגה אחרי שווידאתם שהכול עובד.
ב. X-Frame-Options
X-Frame-Options מגן על הגולשים מפני מתקפות Clickjacking. בלי header זה, תוקף יכול לטעון את האתר שלכם בתוך iframe באתר שלו ולגרום למשתמשים ללחוץ על אלמנטים מוסתרים.
הסיכון גבוה במיוחד כשהמשתמש מחובר לאזור שדורש אימות באתר שלכם (אגב).
<IfModule mod_headers.c>
Header always set X-Frame-Options "SAMEORIGIN"
</IfModule>add_header X-Frame-Options "SAMEORIGIN" always;הערך SAMEORIGIN מאפשר לאתר שלכם לטעון את עצמו בתוך iframe, דבר שימושי לתצוגות מקדימות בממשק הניהול של וורדפרס, אבל חוסם דומיינים אחרים מלעשות זאת.
שימו לב כי אנחנו משתמשים כאן ב-set ולא ב-append. set מחליף כל X-Frame-Options שתוסף, פרוקסי או CDN אולי כבר שולחים, בעוד append עלול ליצור header כפול וסותר, כזה שהדפדפן פשוט יתעלם ממנו.
עוד נקודה חשובה: X-Frame-Options מוחלף בהדרגה על ידי ההנחיה frame-ancestors ב-Content-Security-Policy (ראו סעיף ד׳ בהמשך). דפדפנים מודרניים מעדיפים את frame-ancestors על פני X-Frame-Options. לתאימות מרבית, השתמשו בשניהם, ואותה דוגמת CSP שבהמשך כבר כוללת frame-ancestors 'self'.
ג. X-Content-Type-Options
הגדרת ה-header מסוג X-Content-Type-Options מונעת מהדפדפן לנחש, או "לרחרח", את סוג ה-MIME של קובץ. בלי header זה, דפדפן עלול לפרש קובץ זדוני כ-JavaScript או HTML.
Header always set X-Content-Type-Options nosniffadd_header X-Content-Type-Options "nosniff" always;מדובר באחד ה-headers הפשוטים ביותר להוספה, וכמעט שאין בו סיכון לשבירת האתר.
ד. Content-Security-Policy
ה-header מסוג Content Security Policy (CSP) הוא החזק ביותר, וגם המורכב ביותר, מבין ה-Security Headers. הוא מורה לדפדפן בדיוק מאילו מקורות מותר לטעון סקריפטים, סגנונות, תמונות, פונטים ומשאבים אחרים.
CSP מחמיר יכול למנוע ביעילות מתקפות XSS. עם זאת, תבניות ותוספים בוורדפרס נשענים לא מעט על סקריפטים וסגנונות inline, מה שמקשה על יישום מדיניות מחמירה בלי לשבור פונקציונליות.
נקודת פתיחה ריאלית לרוב אתרי וורדפרס:
Header always set Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https:; style-src 'self' 'unsafe-inline' https:; img-src 'self' https: data:; font-src 'self' https: data:; connect-src 'self' https:; frame-src 'self' https:; media-src 'self' https:; object-src 'none'; base-uri 'self'; frame-ancestors 'self';"add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https:; style-src 'self' 'unsafe-inline' https:; img-src 'self' https: data:; font-src 'self' https: data:; connect-src 'self' https:; frame-src 'self' https:; media-src 'self' https:; object-src 'none'; base-uri 'self'; frame-ancestors 'self';" always;ההנחיות unsafe-inline ו-unsafe-eval מחלישות את הגנת ה-CSP, אבל כרגע הן נדרשות עבור רוב אתרי וורדפרס בכדי לתפקד. ליבת וורדפרס, Gutenberg ותוספים רבים תלויים בסקריפטים inline. הסרת הנחיות אלה כנראה תשבור את האתר שלכם. השתמשו בהן כפשרה מעשית, והדקו את המדיניות עם הזמן ככל שוורדפרס תשפר את תמיכת ה-CSP שלה.
קל לפספס שתי הנחיות באותה מדיניות, אבל הן מאוד חשובות. frame-src ו-media-src מוגדרות ל-'self' https:, כך שהטמעות ימשיכו לעבוד. בלעדיהן, שתיהן חוזרות ל-default-src 'self', מה שחוסם בשקט כל הטמעה חיצונית: YouTube, Vimeo, Google Maps ונגני אודיו ווידאו.
object-src 'none' ו-base-uri 'self' הן שתי תוספות פשוטות עם ערך גבוה. הן חוסמות הזרקת אובייקטים ותוספים ישנים, וגם חטיפת תגית <base>, כמעט בלי סיכון באתר רגיל.
רוצים לבדוק את ה-CSP לפני אכיפה? השתמשו ב-Content-Security-Policy-Report-Only במקום. אותו header מתעד הפרות בקונסול הדפדפן בלי לחסום דבר, כך שתוכלו לראות מה היה נשבר (בין היתר).
ה. Referrer-Policy
ה-header מסוג Referrer-Policy שולט בכמות מידע ה-referrer שהדפדפן שולח כשגולשים מהאתר שלכם לאתר אחר.
Header always set Referrer-Policy "strict-origin-when-cross-origin"add_header Referrer-Policy "strict-origin-when-cross-origin" always;הערך strict-origin-when-cross-origin שולח את הכתובת המלאה עבור בקשות מאותו מקור, אבל רק את הדומיין עבור בקשות חוצות-מקור. מדובר באיזון טוב בין פרטיות לפונקציונליות, כי הוא שומר על נתוני אנליטיקס בלי לחשוף נתיבי עמודים מלאים לאתרים חיצוניים.
ו. Permissions-Policy
ה-header מסוג Permissions-Policy (לשעבר Feature-Policy) שולט באילו תכונות ו-APIs של הדפדפן האתר שלכם יכול להשתמש, כמו מצלמה, מיקרופון, מיקום גיאוגרפי ו-APIs של תשלום.
רוב אתרי וורדפרס אינם זקוקים לגישה לתכונות אלה, כך שהשבתתן מצמצמת את שטח ההתקפה:
Header always set Permissions-Policy "camera=(), microphone=(), geolocation=(), payment=(), browsing-topics=()"add_header Permissions-Policy "camera=(), microphone=(), geolocation=(), payment=(), browsing-topics=()" always;הסוגריים הריקים () משביתים כל תכונה לחלוטין, ו-browsing-topics=() מוציאה את האתר מ-Topics API של Google. אם אתם באמת משתמשים באחת מהן, למשל אתר חנות שצריך מיקום גיאוגרפי, אפשרו רק אותה: geolocation=(self).
יש נקודה אחת שכדאי לשים לב אליה בווקומרס: Apple Pay ו-Google Pay עובדים דרך Payment Request API. לכן, אם אתם מציעים אותם, הסירו את payment=() מהרשימה, או השתמשו ב-payment=(self), אחרת כפתורי התשלום המהיר פשוט ייעלמו.
ז. X-XSS-Protection (מיושן)
ה-header מסוג X-XSS-Protection נועד להפעיל את מסנן ה-XSS המובנה בדפדפן. עם זאת, header זה מיושן והוסר מכל הדפדפנים המודרניים. Chrome הסיר אותו בגרסה 78, Firefox מעולם לא תמך בו, ו-Edge הסיר אותו בגרסה 17.
בהמשך התברר כי אותו מסנן XSS סבל גם מפגמי אבטחה משלו, ואפשר היה לנצל אותו ליצירת דליפות מידע חוצות-אתרים. הגישה המומלצת היא להשמיט header זה לחלוטין או להשבית אותו במפורש:
Header always set X-XSS-Protection "0"add_header X-XSS-Protection "0" always;השתמשו ב-Content-Security-Policy במקום להגנה מפני XSS. אם בעבר היה לכם X-XSS-Protection: 1; mode=block בהגדרות, אפשר להסיר אותו בבטחה.
דוגמת הגדרה מלאה
אני ממליץ להטמיע את ה-headers בשני שלבים: קודם הדביקו את הבסיס הבטוח וודאו שהאתר תקין, ורק אחר כך הוסיפו את ה-headers המתקדמים אחד אחד.
לפני שאתם מדביקים, שימו לב גם למיקום. ב-.htaccess (של Apache או LiteSpeed) הוסיפו אותם מחוץ לבלוק # BEGIN WordPress / # END WordPress. וורדפרס משכתבת את הבלוק הזה בכל שמירה של קישורים קבועים (Permalinks), כך שכל מה שנמצא בתוכו נמחק.
ב-NGINX הוסיפו את ההנחיות ל-server block, ואז טענו אותו מחדש עם sudo nginx -s reload. שרתי Apache ו-LiteSpeed קולטים שינויים ב-.htaccess באופן מיידי (כמובן).
הבסיס הבטוח (התחילו כאן)
בלוק זה בטוח כמעט בכל אתר וורדפרס. הוא משתמש ב-HSTS שמרני, עדיין בלי includeSubDomains, ורק ב-headers שכמעט אף פעם אינם משפיעים על הפונקציונליות:
<IfModule mod_headers.c>
Header always set Strict-Transport-Security "max-age=31536000" env=HTTPS
Header always set X-Content-Type-Options nosniff
Header always set X-Frame-Options "SAMEORIGIN"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
Header always set X-XSS-Protection "0"
</IfModule>הגדרה מלאה (הוסיפו לאחר בדיקה)
ברגע שהבסיס באוויר והאתר עובד, הוסיפו את ה-headers המתקדמים. הוסיפו את Content-Security-Policy ואת Permissions-Policy אחד בכל פעם, ועקבו אחרי הקונסול. אלה ה-headers שהכי עלולים לשבור הטמעות, תשלומים או התחברות. שדרגו את HSTS ל-includeSubDomains רק אחרי שווידאתם שכל תת-דומיין עובד על HTTPS:
<IfModule mod_headers.c>
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains" env=HTTPS
Header always set X-Content-Type-Options nosniff
Header always set X-Frame-Options "SAMEORIGIN"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
Header always set X-XSS-Protection "0"
Header always set Permissions-Policy "camera=(), microphone=(), geolocation=(), payment=(), browsing-topics=()"
Header always set Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https:; style-src 'self' 'unsafe-inline' https:; img-src 'self' https: data:; font-src 'self' https: data:; connect-src 'self' https:; frame-src 'self' https:; media-src 'self' https:; object-src 'none'; base-uri 'self'; frame-ancestors 'self';"
</IfModule>נקודה לגבי env=HTTPS: הוא שולח HSTS רק דרך HTTPS, אבל מאחורי Cloudflare או load balancer שמסיים את ה-SSL, Apache לרוב אינו מגדיר את המשתנה HTTPS, ואז אותו header פשוט לא נשלח. אם זה קורה, התנו זאת במקום על "expr=%{HTTP:X-Forwarded-Proto} == 'https'".
קיבלתם שגיאת 500 אחרי הוספת header? הסירו אותו והחזירו את השאר אחד בכל פעם. האשם הוא כמעט תמיד הנחיה אחת שאינה נתמכת או mod_headers שחסר.
ח. Cross-Origin Headers (מתקדם)
שלושה headers חדשים יחסית עוזרים לבודד את האתר מהתקפות cross-origin כמו Spectre:
Cross-Origin-Opener-Policy (COOP) מונע מאתרים אחרים לקבל הפניה לאובייקט ה-window שלכם דרך חלונות קופצים. Cross-Origin-Resource-Policy (CORP) שולט באילו מקורות מותר לטעון את המשאבים שלכם. (יש גם header שלישי, COEP, שמחמיר עוד יותר, אבל ברוב אתרי וורדפרס עדיף להשאיר אותו כבוי.)
Header set Cross-Origin-Opener-Policy "same-origin"
Header set Cross-Origin-Resource-Policy "same-origin"add_header Cross-Origin-Opener-Policy "same-origin" always;
add_header Cross-Origin-Resource-Policy "same-origin" always;headers אלה שוברים יותר ממה שנדמה. Cross-Origin-Opener-Policy: same-origin מנתק את window.opener, מה שמפיל חלונות התחברות של רשתות חברתיות ("התחברות עם Google") וגם חלק מחלונות התשלום הקופצים. Cross-Origin-Resource-Policy: same-origin חוסם את התמונות, הפונטים והסקריפטים שלכם כשהם נטענים מתת-דומיין של CDN (אגב, cdn.example.com הוא cross-origin ביחס ל-www.example.com, כך שרוב הגדרות ה-CDN מושפעות).
דלגו על COEP, והוסיפו COOP ו-CORP רק אם אינכם משתמשים בהתחברות דרך רשתות חברתיות, חלונות קופצים חוצי-מקור או תת-דומיין של CDN.
בדיקת ה-Security Headers
אחרי שהוספתם את ה-headers, ודאו שהם עובדים כמו שצריך. תוכלו לבדוק את האתר שלכם ב-securityheaders.com בכדי לקבל ציון ולראות אילו headers קיימים.

תוכלו גם לבדוק headers בכלי המפתחים של הדפדפן. פתחו את לשונית Network, לחצו על בקשת המסמך הראשית, והסתכלו בקטע Response Headers בכדי לוודא שה-headers שלכם אכן נשלחים.
שאלות נפוצות
שאלות נפוצות בנושא Security Headers בוורדפרס:
לסיכום
Security Headers הם אחת ההשקעות הזולות ביותר באבטחת וורדפרס: כמה שורות ב-.htaccess, ואתם סוגרים משפחה שלמה של התקפות. התחילו מהבסיס הבטוח, ודאו ששום דבר לא נשבר, ורק אחר כך הוסיפו את CSP ואת Permissions-Policy תוך מעקב אחרי הקונסול.
הכלל המרכזי פשוט: הוסיפו header אחד בכל פעם, בדקו, ושמרו גיבוי. אם משהו נשבר, תמיד תוכלו לשחזר.
Security Headers הם רק שכבה אחת בהקשחת אבטחת וורדפרס. שקלו גם הפעלת אימות דו-שלבי, אבטחת ה-REST API ושינוי כתובת ההתחברות כצעדי הקשחה נוספים.
שאלות, תיקונים ושיפורים יתקבלו בברכה בתגובות.



ההגדרות המומלצות של securityheaders.com מחמירות מדי ולא מתאימות לאתר וורדפרס.
וורדפרס צריך לאפשר גם JS ו־CSS מ־inline ולפעמים גם eval. ייתכן מאוד שאתה גם משתמש במשאבים מאתרים אחרים ותרצה לאפשר גם אותם. הגדרות סבירות תהיינה משהו כמו:
כדאי להיזהר עם ההגדרות האלה כי קל לשבור את האתר אם הן מחמירות מדי.
Permissions-Policy קובע הרשאות גישה לחומרה וברוב האתרים שלא צריכים גישה הוא יהיה:
תודה רבה על המידע חתול 🙂
אתה כנראה צודק וההגדרות מחמירות למרבית האתרים. אני אשנה את הפוסט בהתאם, אך האם תוכל לשלוח גם את השינויים שהצעת לשרתי apache? (התגיות אמורות לעבוד עכשיו).
הקוד כללי ונכון גם ל־apache. ב־nginx צריך להוסיף לפניו add_header וב־apache צריך להוסיף Header set
אבל למה בכלל להשתמש ב־apache?
מעניין, תודה.
פוסט מצויין! אני חוזרת אליו שוב ושוב.
עזר לי לסיים בקלות כמה דוחות אבטחת מידע על פרויקטים שונים.
תודה!
כיף לשמוע 🙂
אם יש לך טיפים משלך את מוזמנת לשתף…
היי,
אני משתמשת בפוסט הזה שוב ושוב בהצלחה רבה. אין מילים!!!
יש כמה HEADER'ים נוספים שהייתי שמחה להרחבה אודותיהם ועל התחביר הנכון:
Header set Permissions-Policy
Access-Control-Allow-Credentials
תודה!