Назад до блогу

Security headers: HSTS, CSP, X-Frame-Options та інші

· 7 хв читання

Коротко: Security HTTP-заголовки - це рядки, які сервер додає до кожної HTTP-відповіді, щоб сказати браузеру, як поводитися з вашим сайтом. Правильно налаштовані усувають цілі класи атак (XSS, clickjacking, MITM) - і вони безкоштовні.

Коротко: Security HTTP-заголовки - це рядки, які сервер додає до кожної HTTP-відповіді, щоб сказати браузеру, як поводитися з вашим сайтом. Правильно налаштовані усувають цілі класи атак (XSS, clickjacking, MITM) - і вони безкоштовні.

Чому вони важливі

Програма може бути ідеально захищена backend-side, але без правильних заголовків все ще вразлива до browser-side атак: cross-site scripting (XSS), clickjacking, protocol downgrade, MIME confusion. Security-заголовки переносять захист у браузер.

Strict-Transport-Security (HSTS)

Примушує HTTPS для всіх майбутніх відвідувань. Після першого HTTPS-візиту браузер запам'ятовує домен і сам переписує будь-яке http://-посилання на https://, навіть якщо користувач клікне на погану відповідь.

Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
  • max-age=63072000 = діє 2 роки
  • includeSubDomains = правило діє і для всіх піддоменів (увага: якщо у вас HTTP-only піддомен, зламає його)
  • preload = дозволяє включення до HSTS preload списку, вбудованого в Chrome / Firefox / Safari

Увага: HSTS з preload видаляється зі списку 6+ місяців. Не включайте preload до того, як перевірите, що HTTPS працює стабільно і для всіх піддоменів.

Content-Security-Policy (CSP)

Найпотужніший, але і найскладніший для налаштування заголовок. Whitelist того, звідки браузер може завантажувати скрипти, стилі, зображення, iframe-и. Без CSP атакувальник, здатний інжектувати <script> тег, може виконати будь-який JS - з CSP лише код із схвалених джерел.

Content-Security-Policy: default-src 'self'; script-src 'self' 'sha256-...'; img-src 'self' data: https://cdn.example.com; style-src 'self' 'unsafe-inline'; frame-ancestors 'none'

Звичайні директиви:

  • default-src 'self' = за замовчуванням дозволяти лише ресурси з мого домену
  • script-src = JS-джерела (вкажіть hash або nonce для inline-скриптів)
  • style-src = CSS-джерела
  • img-src = зображення
  • connect-src = AJAX, WebSocket, EventSource
  • frame-ancestors 'none' = ніхто не може вбудувати сторінку в iframe (краще, ніж X-Frame-Options)
  • report-uri /csp-report = браузер надсилає JSON при кожному порушенні (ви ловите в backend і логуєте)

X-Frame-Options

Старіша альтернатива frame-ancestors. Захищає від clickjacking - атакувальник вставляє вашу сторінку як iframe і перекриває невидимими кнопками.

X-Frame-Options: DENY

Значення: DENY (ніхто), SAMEORIGIN (лише мій домен), ALLOW-FROM uri (deprecated).

X-Content-Type-Options

X-Content-Type-Options: nosniff

Вимикає MIME sniffing - браузер поважатиме Content-Type, який повернув сервер. Без цього атакувальник може завантажити файл з неправильним типом (наприклад, зображення, яке насправді HTML зі скриптом) і браузер може виконати як web page.

Referrer-Policy

Referrer-Policy: strict-origin-when-cross-origin

Керує, скільки інформації про попередню сторінку браузер надсилає в Referer заголовку при кліку. Default у сучасних браузерах вже strict-origin-when-cross-origin, але явний декларативний заголовок забезпечує консистентність.

Permissions-Policy

Вимикає API, які вам не потрібні - камеру, мікрофон, GPS, geolocation. Атакувальник через XSS не може запитати ці API.

Permissions-Policy: camera=(), microphone=(), geolocation=(), payment=()

Практична конфігурація в nginx

server {
  listen 443 ssl http2;
  server_name example.com;

  add_header Strict-Transport-Security "max-age=63072000; includeSubDomains" always;
  add_header X-Content-Type-Options "nosniff" always;
  add_header X-Frame-Options "DENY" always;
  add_header Referrer-Policy "strict-origin-when-cross-origin" always;
  add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;

  # CSP розгалужена - визначте відповідно до вашого додатку
  add_header Content-Security-Policy "default-src 'self'; script-src 'self'; ..." always;
}

Ключ - always - без нього nginx пропускає заголовки при error response (4xx, 5xx).

Аудит поточного стану

Найпростіше через online tool. Наш header check покаже вам, які заголовки відсутні і які неправильні. Для ретельного аудиту й securityheaders.com дає A-F оцінку.

Висновок

Security-заголовки - одна з найкращих інвестицій за співвідношенням зусилля до вигоди в галузі security - зазвичай півгодини налаштування в reverse proxy проти цілої категорії browser-side атак. Аудит раз у півроку в рамках регулярного обслуговування - розумний мінімум.

Безкоштовний аудит security headers

Без реєстрації, результат за три секунди.

Протестувати сайт →


Спробуйте ePulz.io безкоштовно - 7 днів без банківської картки.

Створити акаунт