Всеосяжний посібник з Content Security Policy (CSP) та інших заголовків безпеки фронтенду для захисту веб-додатків від атак та підвищення безпеки користувачів.
Заголовки безпеки фронтенду: Освоєння Content Security Policy (CSP)
У сучасному цифровому середовищі, де веб-додатки стають все більш складними та взаємопов'язаними, захист від загроз безпеці має першочергове значення. Хоча безпеці бекенду часто приділяється значна увага, безпека фронтенду є не менш важливою. Заголовки безпеки фронтенду діють як перша лінія оборони, надаючи механізм для інструктування браузера щодо його поведінки та захисту користувачів від різноманітних атак. Серед цих заголовків Content Security Policy (CSP) виділяється як потужний інструмент для пом'якшення широкого спектра ризиків.
Що таке заголовки безпеки фронтенду?
Заголовки безпеки фронтенду — це заголовки HTTP-відповідей, які веб-сервер надсилає браузеру. Ці заголовки містять інструкції щодо того, як браузер має обробляти отриманий контент. Вони допомагають запобігти поширеним атакам, таким як:
- Міжсайтовий скриптинг (XSS): Впровадження шкідливих скриптів у довірені веб-сайти.
- Клікджекінг: Обман користувачів з метою змусити їх натиснути на щось відмінне від того, що вони бачать.
- Атаки «людина посередині»: Перехоплення комунікації між користувачем і сервером.
До найважливіших заголовків безпеки фронтенду належать:
- Content Security Policy (CSP): Визначає джерела, з яких браузеру дозволено завантажувати ресурси.
- Strict-Transport-Security (HSTS): Змушує браузер використовувати HTTPS для всіх комунікацій з веб-сайтом.
- X-Frame-Options: Запобігає вбудовуванню веб-сайту в iframe, що пом'якшує атаки клікджекінгу.
- X-XSS-Protection: Вмикає вбудований у браузер фільтр XSS. (Примітка: Часто замінюється CSP, але все ще може забезпечити додатковий рівень захисту).
- Referrer-Policy: Контролює кількість інформації про джерело переходу (referrer), що надсилається із запитами.
- Feature-Policy (тепер Permissions-Policy): Дозволяє розробникам вибірково вмикати та вимикати функції та API браузера.
Глибоке занурення в Content Security Policy (CSP)
Content Security Policy (CSP) — це заголовок HTTP-відповіді, який контролює ресурси, які user agent може завантажувати для даної сторінки. По суті, він створює білий список джерел схваленого контенту, значно знижуючи ризик атак XSS. Чітко визначаючи джерела, з яких можуть завантажуватися такі ресурси, як скрипти, таблиці стилів, зображення та шрифти, CSP значно ускладнює зловмисникам впровадження шкідливого коду на ваш веб-сайт.
Як працює CSP
CSP працює, надаючи браузеру список схвалених джерел для різних типів контенту. Коли браузер стикається з ресурсом, що порушує CSP, він блокує ресурс і повідомляє про порушення. Цей механізм блокування запобігає виконанню шкідливого коду, навіть якщо зловмиснику вдалося впровадити його в HTML.
Директиви CSP
Директиви CSP — це основні компоненти політики CSP. Вони визначають дозволені джерела для різних типів ресурсів. Деякі з найбільш часто використовуваних директив:
- default-src: Встановлює джерело за замовчуванням для всіх типів ресурсів. Це резервна директива, яка застосовується, коли інші, більш конкретні директиви не визначені.
- script-src: Визначає дозволені джерела для JavaScript.
- style-src: Визначає дозволені джерела для таблиць стилів CSS.
- img-src: Визначає дозволені джерела для зображень.
- font-src: Визначає дозволені джерела для шрифтів.
- media-src: Визначає дозволені джерела для аудіо та відео.
- object-src: Визначає дозволені джерела для плагінів, таких як Flash. (Загалом, краще уникати дозволу плагінів, якщо це можливо).
- frame-src: Визначає дозволені джерела для фреймів (iframes).
- connect-src: Визначає дозволені джерела для мережевих запитів (AJAX, WebSockets).
- base-uri: Обмежує URL-адреси, які можна використовувати в елементі
<base>. - form-action: Обмежує URL-адреси, на які можна надсилати форми.
- frame-ancestors: Визначає дійсних батьківських елементів, які можуть вбудовувати сторінку за допомогою
<frame>,<iframe>,<object>,<embed>, або<applet>. Ця директива забезпечує захист від клікджекінгу. - upgrade-insecure-requests: Вказує user-агентам розглядати всі незахищені URL-адреси сайту (завантажені через HTTP) так, ніби вони були замінені на захищені URL-адреси (завантажені через HTTPS). Ця директива призначена для веб-сайтів, які знаходяться в процесі міграції з HTTP на HTTPS.
- report-uri: Вказує URL, на який браузер повинен надсилати звіти про порушення CSP. Застаріла на користь `report-to`.
- report-to: Вказує назву групи, визначену в заголовку `Report-To`. Це дозволяє більш тонко контролювати звітування, включаючи вказівку кількох кінцевих точок для звітів.
Значення джерел у CSP
Значення джерел визначають, звідки дозволено завантажувати ресурси. Деякі поширені значення джерел:
- *: Дозволяє контент з будь-якого джерела (Уникайте використання в продакшені!).
- 'self': Дозволяє контент з того ж джерела (схема, хост і порт), що й захищений документ.
- 'none': Забороняє контент з будь-якого джерела.
- 'unsafe-inline': Дозволяє використання вбудованого JavaScript та CSS (Уникайте використання в продакшені!).
- 'unsafe-eval': Дозволяє використання динамічної оцінки коду (наприклад,
eval(),Function()) (Уникайте використання в продакшені!). - 'strict-dynamic': Вказує, що довіра, явно надана скрипту, присутньому в розмітці (супроводжуваному nonce або хешем), повинна поширюватися на всі скрипти, завантажені цим предком.
- 'unsafe-hashes': Дозволяє певні вбудовані обробники подій. Це, як правило, не рекомендується через складність і обмежену користь.
- data:: Дозволяє завантажувати ресурси з URL-адрес даних (наприклад, вбудовані зображення). Використовуйте з обережністю.
- mediastream:: Дозволяє використовувати `mediastream:` URI як джерело медіа.
- blob:: Дозволяє використовувати `blob:` URI як джерело медіа.
- filesystem:: Дозволяє завантажувати ресурси з файлової системи.
- https://example.com: Дозволяє контент з певного домену та порту.
- *.example.com: Дозволяє контент з будь-якого субдомену example.com.
- nonce-{random-value}: Дозволяє скрипти або стилі з відповідним атрибутом nonce. Це вимагає генерації випадкового значення nonce на стороні сервера для кожного запиту.
- sha256-{hash-value}: Дозволяє скрипти або стилі з відповідним хешем SHA256, SHA384 або SHA512.
Режими CSP: Примусовий та Режим звітування
CSP можна розгорнути у двох режимах:
- Примусовий режим: У цьому режимі браузер блокує будь-які ресурси, що порушують CSP. Це рекомендований режим для продакшен-середовищ. CSP надсилається за допомогою заголовка `Content-Security-Policy`.
- Режим лише для звітів: У цьому режимі браузер повідомляє про порушення CSP, але не блокує ресурси. Це корисно для тестування та оцінки CSP перед його примусовим впровадженням. CSP надсилається за допомогою заголовка `Content-Security-Policy-Report-Only`.
Впровадження CSP: Покроковий посібник
Впровадження CSP може здатися складним, але, дотримуючись структурованого підходу, ви можете ефективно захистити свій веб-додаток.
1. Почніть з політики в режимі звітування
Почніть з розгортання CSP у режимі лише для звітів. Це дозволить вам відстежувати порушення, не порушуючи функціональність вашого веб-сайту. Налаштуйте директиву report-uri або report-to для надсилання звітів про порушення на призначену кінцеву точку.
Приклад заголовка (Режим звітування):
Content-Security-Policy-Report-Only: default-src 'self'; report-uri /csp-report
2. Проаналізуйте звіти про порушення
Уважно проаналізуйте звіти про порушення, щоб визначити, які ресурси блокуються і чому. Це допоможе вам зрозуміти залежності ресурсів вашого веб-сайту та виявити потенційні вразливості безпеки.
Звіти про порушення зазвичай надсилаються у вигляді JSON-навантаження на налаштовану кінцеву точку report-uri або report-to. Ці звіти містять інформацію про порушення, таку як заблокований URI, порушена директива та URI документа.
3. Уточніть політику CSP
На основі звітів про порушення уточніть свою політику CSP, щоб дозволити легітимні ресурси, зберігаючи при цьому надійний рівень безпеки. Додайте конкретні значення джерел для ресурсів, які блокуються. Розгляньте можливість використання nonce або хешів для вбудованих скриптів і стилів, щоб уникнути використання 'unsafe-inline'.
4. Перейдіть до примусового режиму
Коли ви впевнені, що ваша політика CSP не блокує легітимні ресурси, перейдіть до примусового режиму. Це заблокує будь-які решту порушень і забезпечить надійний рівень захисту від атак XSS.
Приклад заголовка (Примусовий режим):
Content-Security-Policy: default-src 'self'; script-src 'self' https://example.com; style-src 'self' 'unsafe-inline'; img-src 'self' data:; report-uri /csp-report
5. Моніторте та підтримуйте політику CSP
CSP — це не рішення, яке можна налаштувати і забути. Важливо постійно контролювати вашу політику CSP і оновлювати її в міру розвитку вашого веб-сайту та появи нових загроз безпеці. Регулярно переглядайте звіти про порушення та за потреби коригуйте політику.
Практичні приклади CSP
Розглянемо кілька практичних прикладів CSP для різних сценаріїв:
Приклад 1: Базова CSP для простого сайту
Ця CSP дозволяє контент з того ж джерела та зображення з будь-якого джерела.
Content-Security-Policy: default-src 'self'; img-src *
Приклад 2: CSP з конкретними джерелами для скриптів та стилів
Ця CSP дозволяє скрипти з того ж джерела та з певного CDN, а стилі з того ж джерела та вбудовані стилі.
Content-Security-Policy: default-src 'self'; script-src 'self' https://cdn.example.com; style-src 'self' 'unsafe-inline'
Приклад 3: CSP з nonce для вбудованих скриптів
Ця CSP вимагає унікальний nonce для кожного вбудованого скрипта.
Content-Security-Policy: default-src 'self'; script-src 'self' 'nonce-r4nd0mn0nc3'
HTML:
<script nonce="r4nd0mn0nc3">console.log('Hello, world!');</script>
Важливо: Значення nonce має генеруватися динамічно на сервері для кожного запиту. Це запобігає повторному використанню nonce зловмисниками.
Приклад 4: CSP, що обмежує frame-ancestors для запобігання клікджекінгу
Ця CSP забороняє вбудовування сторінки в iframe на будь-якому домені, крім `https://example.com`.
Content-Security-Policy: frame-ancestors 'self' https://example.com
Приклад 5: Більш сувора CSP з використанням 'strict-dynamic' та 'self' як запасного варіанту
Ця CSP використовує `strict-dynamic` для сучасних браузерів, підтримуючи при цьому старіші браузери, які його не підтримують. Вона також містить `report-uri` для моніторингу порушень.
Content-Security-Policy: default-src 'self'; script-src 'strict-dynamic' 'nonce-{random-nonce}' 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; report-uri /csp-report
Не забудьте замінити `{random-nonce}` на динамічно згенероване значення nonce на стороні сервера.
CSP та односторінкові додатки (SPA)
Впровадження CSP в SPA може бути складним через динамічну природу цих додатків. SPA часто значною мірою покладаються на JavaScript для генерації та маніпулювання DOM, що може призвести до порушень CSP, якщо не обробляти це обережно.
Ось кілька порад щодо впровадження CSP в SPA:
- Уникайте
'unsafe-inline'та'unsafe-eval': Цих директив слід уникати, коли це можливо, у SPA. Вони значно послаблюють безпеку вашого додатка. - Використовуйте Nonce або хеші: Використовуйте nonce або хеші для вбудованих скриптів та стилів. Це рекомендований підхід для SPA.
- Розгляньте Trusted Types: Trusted Types — це API браузера, який допомагає запобігти DOM-based XSS вразливостям. Його можна використовувати разом з CSP для подальшого посилення безпеки.
- Використовуйте CSP-сумісний фреймворк: Деякі фронтенд-фреймворки (наприклад, React з певними конфігураціями, Angular та Vue.js) надають функції, які допомагають легше впровадити CSP.
Інші важливі заголовки безпеки фронтенду
Хоча CSP є наріжним каменем безпеки фронтенду, інші заголовки відіграють вирішальну роль у забезпеченні комплексної стратегії захисту:
Strict-Transport-Security (HSTS)
Заголовок Strict-Transport-Security (HSTS) вказує браузеру завжди використовувати HTTPS для з'єднання з веб-сайтом. Це запобігає атакам «людина посередині», які намагаються знизити рівень з'єднання до HTTP.
Приклад заголовка:
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
max-age: Визначає тривалість (у секундах), протягом якої браузер повинен пам'ятати про доступ до сайту лише через HTTPS. Для продакшен-середовищ рекомендується значення 31536000 секунд (1 рік).includeSubDomains: Вказує, що політика HSTS застосовується до всіх субдоменів домену.preload: Дозволяє включити домен до списку HSTS-увімкнених доменів, який попередньо завантажується в браузери. Це вимагає подання вашого домену до списку попереднього завантаження HSTS, який підтримується Google.
X-Frame-Options
Заголовок X-Frame-Options запобігає атакам клікджекінгу, контролюючи, чи можна вбудовувати веб-сайт в iframe.
Приклад заголовка:
X-Frame-Options: DENY
Можливі значення:
DENY: Забороняє відображення сторінки в iframe, незалежно від джерела.SAMEORIGIN: Дозволяє відображати сторінку в iframe, лише якщо джерело iframe збігається з джерелом сторінки.ALLOW-FROM uri: Дозволяє відображати сторінку в iframe, лише якщо джерело iframe збігається з вказаним URI. Примітка: Цей параметр застарів і може не підтримуватися всіма браузерами.
Примітка: Директива frame-ancestors у CSP надає більш гнучкий та потужний спосіб контролю вбудовування і, як правило, є кращим вибором, ніж X-Frame-Options.
X-XSS-Protection
Заголовок X-XSS-Protection вмикає вбудований у браузер фільтр XSS. Хоча CSP є більш надійним рішенням для запобігання атакам XSS, цей заголовок може забезпечити додатковий рівень захисту, особливо для старих браузерів, які можуть не повністю підтримувати CSP.
Приклад заголовка:
X-XSS-Protection: 1; mode=block
1: Вмикає XSS-фільтр.0: Вимикає XSS-фільтр.mode=block: Вказує браузеру блокувати сторінку, якщо виявлено атаку XSS.report=uri: Вказує URL, на який браузер повинен надсилати звіт, якщо виявлено атаку XSS.
Referrer-Policy
Заголовок Referrer-Policy контролює обсяг інформації про джерело переходу, що надсилається із запитами. Інформація про джерело переходу може використовуватися для відстеження користувачів між веб-сайтами, тому її контроль може покращити конфіденційність користувачів.
Приклад заголовка:
Referrer-Policy: strict-origin-when-cross-origin
Деякі поширені значення:
no-referrer: Ніколи не надсилати заголовок Referer.no-referrer-when-downgrade: Не надсилати заголовок Referer на джерела без TLS (HTTPS).origin: Надсилати в заголовку Referer лише джерело (схему, хост і порт).origin-when-cross-origin: Надсилати джерело для міждоменних запитів і повний URL для запитів з того ж джерела.same-origin: Надсилати заголовок Referer для запитів з того ж джерела, але не для міждоменних запитів.strict-origin: Надсилати лише джерело, коли рівень безпеки протоколу залишається тим самим (HTTPS до HTTPS), але не надсилати заголовок на менш безпечне призначення (HTTPS до HTTP).strict-origin-when-cross-origin: Надсилати джерело при виконанні запиту з того ж джерела. Для міждоменних запитів надсилати джерело лише тоді, коли рівень безпеки протоколу залишається тим самим (HTTPS до HTTPS), але не надсилати заголовок на менш безпечне призначення (HTTPS до HTTP).unsafe-url: Надсилати повний URL в заголовку Referer, незалежно від джерела. Використовуйте з особливою обережністю, оскільки це може розкрити конфіденційну інформацію.
Permissions-Policy (раніше Feature-Policy)
Заголовок Permissions-Policy (раніше відомий як Feature-Policy) дозволяє розробникам вибірково вмикати та вимикати функції та API браузера. Це може допомогти зменшити поверхню атаки вашого додатка та покращити конфіденційність користувачів.
Приклад заголовка:
Permissions-Policy: geolocation=()
Цей приклад вимикає API геолокації для веб-сайту.
Інші функції, якими можна керувати за допомогою Permissions-Policy:
cameramicrophonegeolocationaccelerometergyroscopemagnetometerusbmidipaymentfullscreen
Налаштування заголовків безпеки на різних платформах
Спосіб налаштування заголовків безпеки залежить від веб-сервера або платформи, яку ви використовуєте. Ось кілька поширених прикладів:
Apache
Ви можете налаштувати заголовки безпеки в Apache, додавши їх до файлу .htaccess або до файлу конфігурації сервера (httpd.conf).
Приклад конфігурації .htaccess:
<IfModule mod_headers.c>
Header set Content-Security-Policy "default-src 'self'; script-src 'self' https://cdn.example.com; style-src 'self' 'unsafe-inline'; img-src 'self' data:; report-uri /csp-report"
Header set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
Header set X-Frame-Options "DENY"
Header set X-XSS-Protection "1; mode=block"
Header set Referrer-Policy "strict-origin-when-cross-origin"
</IfModule>
Nginx
Ви можете налаштувати заголовки безпеки в Nginx, додавши їх до блоку server у файлі конфігурації Nginx (nginx.conf).
Приклад конфігурації Nginx:
server {
listen 443 ssl;
server_name example.com;
add_header Content-Security-Policy "default-src 'self'; script-src 'self' https://cdn.example.com; style-src 'self' 'unsafe-inline'; img-src 'self' data:; report-uri /csp-report";
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload";
add_header X-Frame-Options "DENY";
add_header X-XSS-Protection "1; mode=block";
add_header Referrer-Policy "strict-origin-when-cross-origin";
...
}
Node.js (Express)
Ви можете налаштувати заголовки безпеки в Node.js, використовуючи проміжне програмне забезпечення, наприклад Helmet.
Приклад з використанням Helmet:
const express = require('express');
const helmet = require('helmet');
const app = express();
app.use(helmet());
// Customize CSP if needed
app.use(helmet.contentSecurityPolicy({
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'", "https://cdn.example.com"],
styleSrc: ["'self'", "'unsafe-inline'"],
imgSrc: ["'self'", "data:"],
reportUri: '/csp-report'
},
}));
app.get('/', (req, res) => {
res.send('Hello World!');
});
app.listen(3000, () => {
console.log('Server listening on port 3000');
});
Cloudflare
Cloudflare дозволяє налаштовувати заголовки безпеки за допомогою їхніх Page Rules або Transform Rules.
Тестування ваших заголовків безпеки
Після впровадження заголовків безпеки важливо перевірити їх, щоб переконатися, що вони працюють правильно. Кілька онлайн-інструментів можуть допомогти вам проаналізувати заголовки безпеки вашого веб-сайту:
- SecurityHeaders.com: Простий та ефективний інструмент для аналізу заголовків безпеки.
- Mozilla Observatory: Комплексний інструмент для тестування безпеки веб-сайту, включаючи заголовки безпеки.
- WebPageTest.org: Дозволяє переглядати HTTP-заголовки у діаграмі waterfall.
Висновок
Заголовки безпеки фронтенду, особливо Content Security Policy (CSP), є важливими для захисту веб-додатків від різноманітних атак та підвищення безпеки користувачів. Ретельно впроваджуючи та підтримуючи ці заголовки, ви можете значно знизити ризик XSS, клікджекінгу та інших вразливостей безпеки. Пам'ятайте, що потрібно починати з політики в режимі лише для звітів, аналізувати звіти про порушення, уточнювати політику, а потім переходити до примусового режиму. Регулярно контролюйте та оновлюйте ваші заголовки безпеки, щоб ваш веб-сайт залишався захищеним у міру його розвитку та появи нових загроз.
Застосовуючи проактивний підхід до безпеки фронтенду, ви можете створювати більш безпечні та надійні веб-додатки, які захищають ваших користувачів та ваш бізнес.