Налаштування захисту від XSS для сайту
XSS — клас атак, при якому зловмисник внедряє вредоносний JavaScript у сторінки, які видять інші користувачі. Наслідки: крадіжка сесій та cookies, перехоплення форм введення, дефейс сторінок, редирект на фішингові сайти.
Три вектори XSS
Reflected XSS — вредоносна навантаження передається через URL-параметри та негайно відображається. Приклад: https://example.ua/search?q=<script>alert(document.cookie)</script>.
Stored XSS — навантаження зберігається в базі даних (коментарі, профіль користувача) і виконується у кожного, хто переглядає сторінку.
DOM-based XSS — навантаження обробляється JavaScript на клієнтській стороні без участі сервера. Небезпечна тим, що серверні фільтри її не видять.
Екранування вивода
Основний інструмент захисту — контекстне екранування при виводі даних.
PHP/Blade (Laravel):
{{ $userInput }} {{-- автоматично екранує: & < > " ' --}}
{!! $trustedHtml !!} {{-- RAW вивід — тільки для доверених даних --}}
React екранує JSX-значення за замовчуванням:
// Безпечно
<div>{userInput}</div>
// Небезпечно — використовувати тільки з санованим контентом
<div dangerouslySetInnerHTML={{ __html: sanitizedHtml }} />
Vue:
<!-- Безпечно -->
<span>{{ userInput }}</span>
<!-- Небезпечно -->
<span v-html="userInput"></span>
Санування HTML-контенту
Якщо користувачі можуть вводити форматований текст (WYSIWYG-редактори), потрібна бібліотека санування:
// DOMPurify — стандарт для браузерної санації
import DOMPurify from 'dompurify';
const cleanHtml = DOMPurify.sanitize(userInput, {
ALLOWED_TAGS: ['b', 'i', 'em', 'strong', 'a', 'p', 'ul', 'li'],
ALLOWED_ATTR: ['href', 'target'],
ALLOW_DATA_ATTR: false,
});
На сервері (PHP):
// HTMLPurifier
$config = HTMLPurifier_Config::createDefault();
$config->set('HTML.Allowed', 'b,i,em,strong,a[href|title],p,ul,li');
$purifier = new HTMLPurifier($config);
$clean = $purifier->purify($userInput);
Заголовки безпеки
Content-Security-Policy — головна захист від XSS на рівні браузера (див. окремий розділ по CSP).
X-XSS-Protection — застарілий заголовок, сучасні браузери його ігнорують. CSP повністю замінює його.
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "DENY" always;
Cookie з флагами безпеки
Навіть при успішній XSS-атаці атакуючий не отримає сессійний cookie, якщо він захищений:
// PHP
setcookie('session', $value, [
'httponly' => true, // недоступен через document.cookie
'secure' => true, // тільки по HTTPS
'samesite' => 'Strict' // не відправляється при cross-site запитах
]);
# Nginx — додати флаги до Set-Cookie
proxy_cookie_path / "/; HttpOnly; Secure; SameSite=Strict";
Валідація на вході
Не полягайтесь тільки на екануванні виходу — валідуйте дані на вході:
// Laravel Validator
$validated = $request->validate([
'name' => 'required|string|max:255|regex:/^[a-zA-Zа-яёА-ЯЁ\s\-]+$/u',
'website' => 'nullable|url',
'comment' => 'required|string|max:5000',
]);
DOM-based XSS: небезпечні паттерни
// Небезпечно
document.getElementById('output').innerHTML = location.hash.slice(1);
eval(userData);
setTimeout(userCallback, 1000); // якщо userCallback — рядок
// Безпечно
document.getElementById('output').textContent = location.hash.slice(1);
Особливої уваги потребують: innerHTML, outerHTML, document.write, eval, Function(), setTimeout/setInterval зі рядковими аргументами.
Тестування
Інструменти для перевірки:
- OWASP ZAP — автоматичний сканер
- Burp Suite Community — ручне тестування
- DOM XSS Scanner — розширення браузера
- Browser DevTools: вкладка Security, перевірка CSP-заголовків
Строк реалізації
- Аудит існуючого кода на XSS-уразливості: 1–3 дня
- Виправлення знайдених проблем: 2–5 днів (залежить від обсягу)
- Настройка CSP + інструментарій: 3–5 днів







