Главное Авторские колонки Вакансии Вопросы
117 0 В избр. Сохранено
Авторизуйтесь
Вход с паролем

Content Security Policy: почему этот заголовок спасает от XSS, но его игнорируют 80% сайтов

За 10 лет в веб-разработке я видел, как отличные сайты ломались из-за одной пропущенной строчки в конфиге. Рассказываю про Content Security Policy — инструмент, который блокирует внедрение чужих скриптов, и как его внедрить без поломки продакшена.
Мнение автора может не совпадать с мнением редакции

Что такое Content Security Policy

CSP — это HTTP-заголовок, который говорит браузеру: «Загружай скрипты, стили и картинки только с этих адресов». Всё остальное блокируется на корню. XSS-атака? Инжект стороннего скрипта? Без явного разрешения в CSP это просто не сработает.

По данным Google, XSS остаётся в топ-3 уязвимостей веб-приложений. При этом CSP существует с 2012 года. Почему его до сих пор мало кто использует? Страх сломать продакшен. Я тоже его испытывал, пока не нашёл правильный подход.

Базовая настройка через nginx

Я работаю в основном с nginx, поэтому добавляю заголовок прямо в конфиг. Вот конфигурация, с которой начинаю на любом новом проекте:

add_header Content-Security-Policy «default-src ’self’; script-src ’self’; style-src ’self’; img-src ’self’ data:; font-src ’self’; frame-ancestors ’none’; base-uri ’self’;» always;

Это строгий вариант: всё грузится только с текущего домена, фреймы запрещены, инлайн-скрипты тоже. Для простого сайта без сторонних виджетов — идеально.

Но реальность сложнее. Практически любой современный сайт использует Google Analytics, Яндекс.Метрику, Google Fonts, виджеты обратного звонка, карты. Тогда белый список растёт. Вот пример для типичного корпоративного сайта на Bitrix:

add_header Content-Security-Policy «default-src ’self’; script-src ’self’ https://mc.yandex.ru https://www.google-analytics.com https://ssl.google-analytics.com; style-src ’self’ ’unsafe-inline’ https://fonts.googleapis.com; img-src ’self’ data: https://mc.yandex.ru https://www.google-analytics.com; font-src ’self’ https://fonts.gstatic.com data:; frame-src https://www.youtube.com; frame-ancestors ’none’; report-uri /csp-report;» always;

Главный лайфхак: Report-Only

Вот что я делаю всегда, когда внедряю CSP на работающий сайт. Сначала включаю заголовок Content-Security-Policy-Report-Only. Он работает точно так же, но не блокирует ресурсы — только отправляет отчёты о нарушениях.

Схема простая: две недели в режиме Report-Only, собираем логи, понимаем, что нужно добавить в белый список, и только потом переключаемся на боевой CSP. Так я не ломаю сайт и не срываю аналитику.

Для приёма отчётов нужен простой скрипт на бэкенде. Я использую минимальный PHP-обработчик, который пишет JSON-логи в файл. После недели сбора обычно понятно, какие домены нужно добавить.

WordPress и Bitrix: особенности

WordPress — отдельная боль. Огромное количество плагинов добавляет инлайн-скрипты прямо в HTML, часто без настроек. Редактор Gutenberg сам требует разрешений, которые делают CSP мягче. На WordPress я обычно иду на компромисс: разрешаю unsafe-inline для стилей, но держу строгий список для скриптов.

На Bitrix ситуация лучше, но есть нюансы. Компонент карт, виджет онлайн-консультанта из Bitrix24, модуль оплаты — всё это тянет внешние ресурсы. На одном B2B-портале я потратил три дня на составление корректного CSP. Особенно пришлось повозиться с CloudPayments — их скрипты грузятся с нескольких CDN-доменов, которые ещё и меняются.

Типичные ошибки при внедрении

Разрешают всё через звёздочку. Встречал конфиги вида script-src *. Это бессмысленно — вы разрешаете скрипты откуда угодно.

Забывают про data: URI. Некоторые библиотеки используют их для шрифтов или картинок. Если не добавить data: в font-src — сломается вёрстка.

Не тестируют в разных браузерах. Chrome и Firefox реализуют CSP немного по-разному. Safari вообще отдельная история.

Паникуют из-за аналитики. Маркетологи боятся, что Метрика перестанет работать. Решается добавлением двух доменов в белый список — это 10 минут работы.

Связка с другими заголовками

CSP работает лучше в команде. Я всегда настраиваю его вместе с HSTS, X-Frame-Options, X-Content-Type-Options и Referrer-Policy. Проверить всё это можно на securityheaders.com — цель минимум A. На моих проектах обычно A или A+.

Вывод

CSP — не замена SSL и не замена firewall. Это отдельный слой защиты, который стоит практически ничего, но экономит миллионы при инциденте. Настроить можно за вечер. Не настроить — значит оставить дверь открытой.

0
В избр. Сохранено
Авторизуйтесь
Вход с паролем