XSS уязвимости

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

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

  1. Reflected XSS (Отражённый) Скрипт внедряется в запрос, например через URL или форму, и моментально возвращается сервером в ответ. Такой XSS активируется при переходе на специально подготовленную ссылку.

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

  3. DOM-based XSS (На стороне клиента) Скрипт внедряется и выполняется полностью в браузере, чаще всего через манипуляции с innerHTML, document.write, eval или другими опасными методами DOM.


Механизм работы XSS

XSS работает за счёт внедрения HTML и JavaScript в контент страницы. Основные цели злоумышленника:

  • Кража сессионных токенов и учетных данных.
  • Перенаправление на фишинговые страницы.
  • Манипуляции с DOM, подмена содержимого страницы.
  • Выполнение действий от имени пользователя, если сайт доверяет авторизованным пользователям.

Пример отражённого XSS:

<form action="/search" method="GET">
  <input type="text" name="query">
  <button type="submit">Поиск</button>
</form>

Если сервер возвращает введённый текст без фильтрации:

<p>Результаты для: <?php echo $_GET['query']; ?></p>

Пользователь, перейдя по ссылке:

https://example.com/search?query=<script>alert('XSS')</script>

увидит выполнение JavaScript.


Уязвимые места и практики кода

Основные источники XSS:

  • Вывод данных без экранирования. Любой пользовательский ввод, вставляемый в HTML или атрибуты тегов, должен быть безопасно закодирован.
  • Использование innerHTML и document.write с пользовательскими данными. Эти методы напрямую вставляют HTML и скрипты.
  • Ошибки при работе с шаблонами. Многие шаблонизаторы имеют встроенные функции экранирования, но их нужно явно применять.
  • Отсутствие проверки URL и ссылок. Любой параметр GET или POST может быть источником вредоносного скрипта.

Методы защиты от XSS

  1. Экранирование данных (Output Encoding) Вставка пользовательских данных в HTML, атрибуты, URL и JavaScript должна быть безопасной. Например, в HTML:
function escapeHTML(str) {
  return str.replace(/[&<>"']/g, function(match) {
    return ({
      '&': '&amp;',
      '<': '&lt;',
      '>': '&gt;',
      '"': '&quot;',
      "'": '&#39;'
    })[match];
  });
}
  1. Использование безопасных методов DOM Методы textContent, setAttribute, appendChild безопаснее, чем innerHTML.
const div = document.createElement('div');
div.textContent = userInput; // безопасно
document.body.appendChild(div);
  1. Content Security Policy (CSP) Политики CSP позволяют ограничить источники скриптов и стилей, предотвращая выполнение инъекционного кода.
Content-Security-Policy: default-src 'self'; script-src 'self';
  1. Валидация на стороне сервера Проверка всех входных данных, фильтрация специальных символов, ограничение форматов (например, числа, email, даты).

  2. Использование библиотек с защитой от XSS Современные фронтенд-фреймворки (React, Vue, Angular) по умолчанию экранируют данные в шаблонах. В чистом JavaScript требуется применять ручное экранирование.


Примеры опасных паттернов

  1. Внедрение в атрибуты HTML:
<img src="x" oner ror="alert('XSS')" />
  1. Внедрение через URL:
window.location = "jav * ascript:alert('XSS')";
  1. Использование eval или Function:
eval(userInput); // крайне опасно

Любой из этих методов позволяет выполнять произвольный код и должен быть заменён безопасными альтернативами.


Рекомендации по безопасному кодированию

  • Все пользовательские данные обрабатываются как потенциально опасные.
  • Минимизировать использование innerHTML, eval, document.write.
  • Применять строгие политики CSP.
  • Сохранять пользовательский ввод только в безопасных форматах и экранировать при выводе.
  • Проводить регулярные тесты на XSS, включая автоматические сканеры и ручное тестирование.

Эти практики создают многоуровневую защиту и снижают риск XSS-атак, делая приложение безопасным для пользователей и устойчивым к распространённым методам эксплуатации.