
Кросс-сайтовый скриптинг (XSS) — это класс уязвимостей, при котором атакующий внедряет вредоносный код (обычно JavaScript) в контент, который затем отображается доверенным пользователям. В результате злоумышленник может украсть сессионные токены, подменять содержимое страницы, выполнять действия от имени пользователя или перенаправлять на фишинговые страницы.
Важно: браузеры опираются на политику одного происхождения (Same-Origin Policy, SOP), но XSS эксплуатирует то, что браузер не всегда способен отличить легитимный HTML/JS от вредоносного.
Факты: XSS стабильно входит в топ уязвимостей и в 2021 году занимал второе место в списке CWE Top 25 по опасности.
Как XSS работает — кратко
- SOP (Same-Origin Policy) ограничивает доступ между разными доменами. XSS обходит защиту, заставляя браузер выполнить вредоносный код в контексте доверенного сайта.
- Атакующий вставляет скрипт в поля ввода, комментарии, URL-параметры или в базу данных (если приложение выводит данные без экранирования).
- При загрузке страницы браузер выполняет скрипт и код получает доступ к DOM, кукам (если не защищены), localStorage и т.д.
Типы XSS:
- Reflected XSS — вредоносный код возвращается в ответе и выполняется сразу при переходе по ссылке.
- Stored XSS — код сохраняется на сервере (в базе данных) и выполняется при просмотре контента другими пользователями.
- DOM-based XSS — уязвимость на стороне клиента: манипуляция DOM ведёт к выполнению вредоносного кода.
Основные принципы защиты (в одном предложении каждый)
- Очищайте и валидируйте любой ввод — никогда не доверяйте данным от клиента.
- Кодируйте (escape) все данные перед вставкой в HTML, атрибуты, JavaScript и в URL.
- Применяйте безопасные заголовки: Content-Security-Policy, X-Content-Type-Options, Referrer-Policy и др.
- Ограничьте доступ к кукам через HttpOnly, Secure и SameSite.
- Используйте проверенные шаблонизаторы и библиотеки для экранирования вывода.
Ниже — системное руководство для разработчиков и инженеров, с примерами кода, рекомендациями по библиотекам и тестами.
1. Санитизация и валидация ввода
Атакующему нужно доставить вредоносные данные в ваше приложение и заставить сервер/клиент отобразить их. Поэтому первая защита — очищать и валидировать входящие данные.
- Используйте whitelisting (разрешённые форматы) вместо blacklist. Если поле должно быть email — принимайте только email.
- Для простых проверок удобно использовать validator и подобные библиотеки.
Пример: экранирование HTML с помощью validator.escape:
import validator from "validator";
let userInput = "Jane ";
let sanitizedInput = validator.escape(userInput);
console.log(sanitizedInput);
// Вывод: Jane <script onload="alert('XSS hack');"></script>Дополнительно: для контента HTML, который нужно сохранить (например, WYSIWYG), используйте библиотеки типа DOMPurify (на стороне клиента) или sanitize-html (на сервере) с явно настроенными разрешёнными тегами и атрибутами.
2. Кодирование вывода (Output Encoding)
Всегда кодируйте данные перед вставкой в контекст:
- Внутри HTML — HTML-экранирование.
- В атрибутах — дополнительное экранирование кавычек и т.д.
- В JavaScript-литералах — экранирование специальных символов.
- В URL — encodeURIComponent.
Хорошие шаблонизаторы (Pug, EJS с авто-экранированием или React на сервере) по умолчанию экранируют вывод. Не отключайте авто-экранирование без веской причины.
3. Защита по заголовкам и CSP
Content Security Policy (CSP) ограничивает, откуда можно загружать скрипты, стили и другие ресурсы. CSP существенно снижает риск XSS, особенно для reflected и stored XSS.
Пример настроек через helmet:
import express from "express";
import helmet from "helmet";
const app = express();
app.use(helmet());
// Дополнительно настраиваем CSP
app.use(
helmet.contentSecurityPolicy({
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'", "https://trustedscripts.example.com"],
objectSrc: ["'none'"],
upgradeInsecureRequests: [],
},
})
);CSP — мощный инструмент, но требует тестирования (в строгом режиме может ломать легитимный функционал).
4. HTTP-only, Secure и SameSite куки
Куки с флагом HttpOnly недоступны через JavaScript — это защищает сессионные идентификаторы от кражи через XSS.
Пример установки куки через express-session:
app.use(session({
secret: "секретная_фраза",
cookie: {
httpOnly: true,
secure: true, // требует HTTPS
sameSite: "lax", // или 'strict' в зависимости от UX
},
}));Важно: secure требует HTTPS в проде. sameSite помогает снизить риск CSRF.
5. Используйте безопасные шаблонизаторы и избегайте unsafe-eval
- Не вставляйте сырые строки HTML через innerHTML без предварительной очистки.
- Избегайте eval, new Function и похожих конструкций.
- На фронте применяйте DOMPurify для контента, генерируемого пользователем.
6. Логика на стороне сервера и принцип наименьших привилегий
- Не храните или не логируйте секреты в открытом виде.
- Ограничьте доступ к административным интерфейсам.
- Проводите ревью изменений, которые меняют вывод HTML/JS.
- CSP + Subresource Integrity (SRI) для внешних скриптов.
- Content Security Policy в режиме отчёта (report-only) для тестирования.
- Web Application Firewall (WAF) как дополнительный уровень защиты (не заменяет корректную разработку).
- Автоматизированные сканеры безопасности и SAST/DAST в CI.
Важно: никакой один механизм не даёт 100% гарантии — защита должна быть многослойной.
Критерии приёмки (минимум):
- Все пользовательские поля проходят валидацию и/или санитизацию.
- Шаблонизатор экранирует вывод по умолчанию или ручной вывод помечен и проверен.
- Наличие CSP в предельной/тихо-отчётной конфигурации и план тестирования.
- Куки сессии имеют httpOnly и secure в продовой среде.
- Unit/Integration тесты покрывают сценарии XSS и автоматические тесты в CI.
Минимальные тест-кейсы:
- Попытаться вставить в форму и убедиться, что при отображении страница не выполняет alert.
- Попытаться внедрить событие в атрибут, например: “ onerror=… “, и проверить, что атрибуты экранируются.
- Тест CSP: попытаться загрузить скрипт с другого домена и убедиться, что блокируется.
Разработчик:
- Очищает ввод по контракту API.
- Не использует innerHTML без очистки.
- Добавляет тесты на XSS.
DevOps / SRE:
- Настроил HTTPS, HSTS и secure cookies.
- Включил заголовки безопасности (helmet).
- Развернул CSP и мониторинг нарушений.
Тестировщик:
- Выполняет ручные и автоматические XSS-тесты.
- Проверяет политику CSP и отчёты.
Команда безопасности:
- Проводит периодическую проверку зависимостей.
- Настраивает SAST/DAST и triage уязвимостей.
- Изолировать источник: временно отключить функционал, принимающий ввод (если возможно).
- Заблокировать подозрительные аккаунты/IP и сохранить логи (с учётом GDPR).
- Провести форензику: какие записи вывели вредоносный код, кто пострадал, какие данные могли быть скомпрометированы.
- Внедрить патч: санитизация/экранирование/исправление шаблонов.
- Развернуть фиксы в тестовом окружении, затем в проде через проверенный процесс CI/CD.
- Уведомить пострадавших, если были утечки персональных данных (учитывать требования законодательства).
- Провести ретроспективу и обновить SOP.
- Высокий риск: Stored XSS в публичных комментариях — mitigation: строгая санитизация + CSP + модерация.
- Средний риск: Reflected XSS в поиске — mitigation: кодирование вывода + автоматические тесты.
- Низкий риск: DOM XSS в вспомогательных скриптах — mitigation: избегать unsafe DOM-операций, DOMPurify.
- XSS: внедрение и исполнение вредоносного скрипта в контексте доверённого сайта.
- CSP: механизм браузера, ограничивающий источники ресурсов.
- HttpOnly: флаг куки, запрещающий доступ через JavaScript.
- DOMPurify / sanitize-html: библиотеки для безопасной очистки HTML.
- CSP в строгом режиме может блокировать сторонние виджеты (аналитика, чат). Решение: постепенное внедрение в report-only и whitelist доверенных источников.
- Сильная валидация может отвергать допустимые пользовательские данные (WYSIWYG) — в этом случае применять контекстную санитизацию с явным списком разрешённых тегов.
- XSS — обычная, но решаемая проблема: комбинируйте валидацию, кодирование вывода, заголовки безопасности и проверенные библиотеки.
- Тестируйте и автоматизируйте проверки в CI, поддерживайте процесс реагирования на инциденты.
- Документируйте решения и обязанности для каждой роли: разработчик, SRE, тестировщик, безопасность.
Дополнительные материалы: начните с обзора CSP, изучите DOMPurify и sanitize-html, включите helmet в middleware Express.
Похожие материалы
Как собрать Mini-ITX ПК — пошаговое руководство
sar: анализ производительности Linux (sysstat)
Сохранить скриншот в PDF на Windows 10
Изменить или удалить пароль книги Excel
Как находить скидки и бесплатные приложения для Android