XSS уязвимости и защита

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

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

  1. Reflected XSS — внедрение скрипта происходит через URL или данные формы, которые моментально отражаются в ответе сервера.
  2. Stored XSS — вредоносный код сохраняется на сервере (например, в базе данных) и выполняется при последующем отображении контента другим пользователям.
  3. DOM-based XSS — скрипт внедряется и выполняется исключительно на стороне клиента через манипуляции с DOM, без участия сервера.

Каждый тип XSS требует внимательного подхода к обработке данных и построению пользовательского интерфейса.

Особенности XSS в Vue.js

Vue.js по умолчанию предоставляет защиту от XSS через механизм автоматического экранирования данных. Любые данные, вставляемые в шаблон с помощью двойных фигурных скобок {{ }}, автоматически преобразуются в безопасный HTML, что предотвращает внедрение вредоносных скриптов.

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

<template>
  <div>
    {{ userInput }}
  </div>
</template>

<script>
export default {
  data() {
    return {
      userInput: '<script>alert("XSS")</script>'
    }
  }
}
</script>

В этом случае на странице будет отображён текст <script>alert("XSS")</script>, а не выполнен скрипт.

Опасные практики

Использование директивы v-html позволяет рендерить HTML-код из строки, но снимает защиту Vue.js от XSS. Любой пользовательский ввод, переданный в v-html, становится потенциально опасным.

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

<template>
  <div v-html="userInput"></div>
</template>

<script>
export default {
  data() {
    return {
      userInput: '<img src=x oner ror=alert("XSS")>'
    }
  }
}
</script>

В этом случае скрипт будет выполнен при рендеринге.

Рекомендация: перед использованием v-html необходимо тщательно фильтровать или очищать данные, используя библиотеки вроде DOMPurify:

import DOMPurify from 'dompurify';

export default {
  data() {
    return {
      rawHtml: '<img src=x oner ror=alert("XSS")>'
    }
  },
  computed: {
    sanitizedHtml() {
      return DOMPurify.sanitize(this.rawHtml);
    }
  }
}
<div v-html="sanitizedHtml"></div>

Обработка пользовательского ввода

Для предотвращения XSS важно отделять данные от представления. Все данные, получаемые от пользователей, должны быть строго проверены и экранированы перед выводом в шаблон.

Методы защиты включают:

  • Экранирование HTML — автоматическая функция Vue.js через {{ }}.
  • Фильтрация тегов и атрибутов — с помощью специализированных библиотек.
  • Валидация данных на сервере — предотвращение сохранения потенциально опасного контента.

Пример безопасной обработки данных формы:

<template>
  <form @submit.prevent="submitForm">
    <input v-model="userComment" />
    <button type="submit">Отправить</button>
  </form>
  <div>{{ safeComment }}</div>
</template>

<script>
import DOMPurify from 'dompurify';

export default {
  data() {
    return {
      userComment: ''
    }
  },
  computed: {
    safeComment() {
      return DOMPurify.sanitize(this.userComment);
    }
  },
  methods: {
    submitForm() {
      console.log("Отправка комментария:", this.safeComment);
    }
  }
}
</script>

Защита от DOM-based XSS

DOM-based XSS возникает при небезопасной манипуляции DOM с использованием данных из URL или других внешних источников. В Vue.js это часто проявляется через динамические свойства или методы, напрямую вставляющие значения в innerHTML или подобные атрибуты.

Примеры безопасной практики:

  • Избегать document.querySelector(...).innerHTML = userInput.
  • Использовать реактивные свойства Vue и v-bind вместо прямого изменения DOM.
  • Применять библиотеки для очистки данных, если динамический HTML неизбежен.
<template>
  <div v-bind:title="sanitizedTitle">{{ sanitizedTitle }}</div>
</template>

<script>
import DOMPurify from 'dompurify';

export default {
  data() {
    return {
      userTitle: '<script>alert("XSS")</script>'
    }
  },
  computed: {
    sanitizedTitle() {
      return DOMPurify.sanitize(this.userTitle);
    }
  }
}
</script>

Итоги по безопасности в Vue.js

  • Автоматическое экранирование через {{ }} защищает от большинства XSS-атак.
  • v-html и прямые манипуляции DOM требуют обязательной очистки данных.
  • Серверная валидация и фильтрация пользовательского ввода повышают общий уровень безопасности.
  • Использование библиотек вроде DOMPurify обеспечивает безопасный рендер динамического контента без снятия защиты Vue.js.

Комплексное соблюдение этих принципов позволяет создать веб-приложения на Vue.js с минимальными рисками XSS-уязвимостей.