Security Headers

כותרות HTTP לאבטחה מהווים שכבת הגנה יסודית ולעתים קרובות בלתי מנוצלת עבור אפליקציות ווב מודרניות, ופועלים כהנחיות המורות לדפדפנים להפעיל מנגנוני הגנה מובנים כנגד מגוון רחב של וקטורי תקיפה נפוצים. כותרות תגובת HTTP אלו פועלים כמדיניות אבטחה דקלרטיבית, ומגדירים כללים לגבי אופן שבו הדפדפן צריך לעבד ולרנדר את תוכן העמוד, לשלוט בהרצת סקריפטים, לנהל cookies ולקיים אינטראקציה עם משאבים של צדדים שלישיים. כאשר מוגדרות כראוי, כותרות כמו Content-Security-Policy (CSP), Strict-Transport-Security (HSTS), X-Frame-Options ו- X-Content-Type-Options יוצרות מחסומים משמעותיים כנגד תקיפות Cross-Site Scripting (XSS), clickjacking, MIME sniffing, דיגרוד פרוטוקול והזרקת קוד זדוני. היישום הנכון של כותרות אלו מהווה אחת הדרכים היעילות ביותר ל-hardening של אפליקציות ווב, משום שהוא אינו דורש שינויים בקוד האפליקציה ומספק הגנה מיידית כנגד מחלקות שלמות של פגיעויות. מחקרים מראים שהרוב המכריע של האתרים עדיין אינו מיישם כראוי כותרות אלו, ומשאיר את המשתמשים שלו חשופים לתקיפות שניתן היה למתן עם תצורות פשוטות יחסית בשרת ה-ווב. הזנחה זו קריטית במיוחד בהתחשב בכך ש כלי סריקת אבטחה אוטומטיים מעריכים את הנוכחות והתצורה התקינה של כותרות אלו כמדדים ראשוניים למצב האבטחה של אפליקציה.

Content-Security-Policy (CSP)

CSP מונע XSS על ידי הגדרת whitelist של מקורות מהימנים עבור scripts, styles, images ומשאבים אחרים.

      # CSP קשיחה (מומלץ)
      Content-Security-Policy:
      default-src 'self';
      script-src 'self' 'nonce-';
      style-src 'self' 'nonce-';
      img-src 'self' https: data:;
      font-src 'self';
      connect-src 'self' https://api.example.com;
      frame-ancestors 'none';
      base-uri 'self';
      form-action 'self';
      # CSP עם report-only (מצב בדיקה)
      Content-Security-Policy-Report-Only:
      default-src 'self';
      report-uri /csp-violation-report
      

דירקטיבות CSP קריטיות

  • default-src: Fallback עבור דירקטיבות אחרות
  • script-src: Whitelist עבור הרצת JavaScript
  • style-src: מקורות CSS מותרים
  • frame-ancestors: מונע clickjacking
  • upgrade-insecure-requests: כופה HTTPS

Strict-Transport-Security (HSTS)

HSTS כופה דפדפנים להשתמש תמיד ב-HTTPS, ומונע downgrade attacks ו-SSL stripping.

      # HSTS עם preload ותת-דומיינים
      Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
      # שלבים ל-HSTS preload:
      1. להגדיר כותרת HSTS עם preload
      2. להגיש את הדומיין ב-hstspreload.org
      3. הדומיין ייכלל ב-preload lists של הדפדפנים
      

X-Frame-Options

מונע clickjacking על ידי שליטה באם העמוד יכול להיות מרונדר ב-frame/iframe.

      # לדחות כל framing (הבטוח ביותר)
      X-Frame-Options: DENY
      # לאפשר רק את אותו ה-origin
      X-Frame-Options: SAMEORIGIN
      # לאפשר דומיין ספציפי (מיושן - יש להשתמש ב-CSP frame-ancestors)
      X-Frame-Options: ALLOW-FROM https://trusted.com
      

X-Content-Type-Options

מונע תקיפות MIME sniffing על ידי כפיית הדפדפן לכבד את ה-Content-Type המוצהר.

      # להשבית MIME sniffing
      X-Content-Type-Options: nosniff
      

Referrer-Policy

שולט בכמות ה-referrer information הנשלחת ב-requests.

      # מדיניות מומלצת
      Referrer-Policy: strict-origin-when-cross-origin
      # אפשרויות:
      # - no-referrer: לעולם אל תשלח referrer
      # - no-referrer-when-downgrade: ללא referrer ב-HTTPS→HTTP
      # - same-origin: לשלוח רק לאותו ה-origin
      # - strict-origin: לשלוח רק את ה-origin (ללא path)
      

Permissions-Policy

שולט באילו browser features ו-APIs העמוד רשאי להשתמש (מחליף את Feature-Policy).

      # להשבית תכונות מסוכנות
      Permissions-Policy:
      geolocation=(),
      microphone=(),
      camera=(),
      payment=(),
      usb=(),
      interest-cohort=()
      

תצורה לפי שרת

Nginx

      # nginx.conf
      add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
      add_header X-Frame-Options "DENY" always;
      add_header X-Content-Type-Options "nosniff" always;
      add_header Referrer-Policy "strict-origin-when-cross-origin" always;
      add_header Content-Security-Policy "default-src 'self';" always;
      add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;
      

Apache

      # .htaccess או httpd.conf
      Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
      Header always set X-Frame-Options "DENY"
      Header always set X-Content-Type-Options "nosniff"
      Header always set Referrer-Policy "strict-origin-when-cross-origin"
      Header always set Content-Security-Policy "default-src 'self';"
      

Node.js/Express

      // להשתמש ב-middleware של Helmet
      const helmet = require('helmet');
      app.use(helmet());
      // תצורה מותאמת אישית
      app.use(helmet.contentSecurityPolicy({
      directives: {
      defaultSrc: ["'self'"],
      scriptSrc: ["'self'", "'nonce-'"],
      styleSrc: ["'self'", "'nonce-'"],
      }
      }));
      

בדיקת Security Headers

  • securityheaders.com: סריקה ודירוג A+
  • Mozilla Observatory: ניתוח מקיף
  • Chrome DevTools: כרטיסיית Network → Headers
  • curl: curl -I https://example.com

מלכודות נפוצות

  • CSP מתירנית מדי עם 'unsafe-inline' ו-'unsafe-eval'
  • HSTS ללא includeSubDomains משאיר תת-דומיינים פגיעים
  • כותרות מוגדרות אך לא מוחלות (חסר הדגל always)
  • לבדוק רק את דף הבית - הכותרות צריכות להיות בכל הדפים

צ'קליסט מלא

  • [OK] Content-Security-Policy קשיחה מוגדרת
  • [OK] HSTS עם max-age של שנה + includeSubDomains
  • [OK] X-Frame-Options: DENY או CSP frame-ancestors
  • [OK] X-Content-Type-Options: nosniff
  • [OK] Referrer-Policy מוגדרת
  • [OK] Permissions-Policy משביתה תכונות שאינן בשימוש
  • [OK] הכותרות נבדקו ב-securityheaders.com (דירוג A+)
  • [OK] CSP נבדקה תחילה ב-report-only mode