Безпека
Повідомлення про вразливості
При надходженні повідомлення про вразливість, воно негайно стає нашим головним занепокоєнням, тому наш працівник кидає все і береться за нього. Щоб повідомити про вразливість, будь ласка, надішліть повідомлення на електронну пошту security@vuejs.org.
Попри те, що нові вразливості виявляються рідко, ми також рекомендуємо завжди використовувати найновіші версії Vue та його офіційні супутні бібліотеки, щоб гарантувати, що ваш додаток залишається максимально безпечним.
Правило №1: Ніколи НЕ використовуйте ненадійні шаблони
Основне правило безпеки під час використання Vue — ніколи не використовуйте ненадійний вміст, як шаблон компонента. Це еквівалентно дозволу довільного виконання JavaScript у вашій програмі – і, що ще гірше, це може призвести до зламу сервера, якщо код виконується під час рендерингу на стороні сервера. Ось приклад такого використання:
js
Vue.createApp({
template: `<div>` + userProvidedString + `</div>` // НІКОЛИ ЦЬОГО НЕ РОБІТЬ
}).mount('#app')
Шаблони Vue компілюються в JavaScript, а вирази всередині них виконуватимуться як частина процесу рендерингу. Попри те, що вирази виконуються у певному контексті рендерингу, через комплексність можливих середовищ виконання для такої інфраструктури як Vue, недоцільно повністю захищатися від потенційно шкідливого виконання коду, через величезні накладні витрати для продуктивності. Найпростіший спосіб уникнути таких проблем – переконатися, що вміст шаблонів Vue завжди є вірогідний та повністю контролюється вами.
Що робить Vue, щоб захистити вас
HTML вміст
При використанні шаблонів або render-функцій вміст буде екрануватися автоматично. Це означає, що для шаблону:
template
<h1>{{ userProvidedString }}</h1>
якщо userProvidedString
містить:
js
'<script>alert("hi")</script>'
то він буде екранований в наступний HTML:
template
<script>alert("hi")</script>
Таким чином, запобігаючи ін'єкції шкідливого сценарію. Екранування виконується за допомогою нативного API браузера, такого як textContent
, тому вразливість можлива лише у випадку, якщо сам браузер вразливий.
Прив'язування атрибутів
Аналогічно, динамічні прив'язки до атрибутів також автоматично екрануються. Це означає, що для шаблону:
template
<h1 :title="userProvidedString">
hello
</h1>
якщо userProvidedString
містить:
js
'" onclick="alert(\'hi\')'
то він буде екранований в наступний HTML:
template
" onclick="alert('hi')
Тим самим запобігаючи передчасному закриттю атрибуту title
для додавання нового, довільного HTML. Екранування виконується за допомогою нативного API браузера, такого як setAttribute
, тому вразливість можлива лише у випадку, якщо сам браузер вразливий.
Потенційні небезпеки
У будь-якому вебдодатку дозволити виконання несанкціонованого вмісту, наданого користувачами, такого як HTML, CSS або JavaScript, є потенційно небезпечним, тому цього слід уникати, де це можливо. Хоча бувають випадки, коли певний ризик може бути прийнятним.
Наприклад, деякі сервіси, такі як CodePen і JSFiddle, дозволяють виконувати контент користувача, але в такому контексті де це очікується й ізолюється всередині iframe. У тих випадках, коли важлива функція за своєю природою потребує певного рівня вразливості, вся команда повинна зважити на необхідність цієї функції з урахуванням найгірших сценаріїв, які можуть привнести її використання.
Ін'єкція HTML
Як сказано раніше, Vue автоматично екранує HTML-вміст, щоб запобігти випадковій ін'єкції HTML у додаток. Однак у тих випадках, коли ви впевнені у безпеці HTML, ви можете явно рендерити вміст HTML:
Використовуючи шаблон:
template<div v-html="userProvidedHtml"></div>
Використовуючи render-функцію:
jsh('div', { innerHTML: this.userProvidedHtml })
Використовуючи render-функцію з JSX:
jsx<div innerHTML={this.userProvidedHtml}></div>
Увага
Запам'ятайте, що наданий користувачем HTML ніколи не може вважатися безпечним на 100%, якщо він не знаходиться в ізольованому iframe, або в тій частині програми, де лише користувач, який написав цей HTML, може отримати до нього доступ. Крім того, дозволити користувачам писати свої власні шаблони Vue може привести до аналогічних небезпек.
Ін'єкція URL
У такій URL-адресі:
template
<a :href="userProvidedUrl">
натисніть мене
</a>
Існує потенційна проблема безпеки, якщо URL-адресу не було "дезінфіковано", щоб запобігти виконанню JavaScript за допомогою javascript:
. Існують такі бібліотеки, як sanitize-url, які допоможуть у цьому, але зауважте: якщо ви іноді виконуєте очищення URL-адрес в інтерфейсі, у вас вже є проблема безпеки. Надані користувачем URL-адреси завжди повинні очищатися серверною частиною перед тим, як навіть зберігатися в базі даних. Тоді проблема уникне для кожного клієнта, який підключається до вашого API, включно з рідними мобільними програмами. Також зауважте, що навіть з очищеними URL-адресами Vue не може гарантувати, що вони ведуть до безпечних місць призначення.
Ін'єкція стилів
Подивимося цей приклад:
template
<a
:href="sanitizedUrl"
:style="userProvidedStyles"
>
натисніть мене
</a>
Припустимо, що sanitizedUrl
був дезінфікований і це дійсно справжній URL, а не JavaScript. Але використовуючи userProvidedStyles
, зловмисники досі можуть додати CSS для "click jack", тобто стилізувати посилання прозорим блоком, наприклад, поверх кнопки «Входу в систему». У такому разі, якщо https://user-controlled-website.com/
створено так, що, візуально повторює сторінку авторизації програми, тоді з'являється можливість перехоплення логінів і паролів користувачів.
Можете собі уявити, як дозволений наданий користувачем вміст для елемента <style>
може створити ще більшу вразливість, надаючи користувачеві повний контроль над тим, як стилізувати всю сторінку. Ось чому Vue запобігає рендерити теги стилю всередині шаблонів, наприклад:
template
<style>{{ userProvidedStyles }}</style>
Щоб повністю захистити своїх користувачів від clickjacking, ми рекомендуємо надавати повний контроль над CSS лише всередині iframe ізольованого програмного середовища. Крім того, якщо користувачеві надається контроль за допомогою прив'язки стилю, ми рекомендуємо використовувати його об'єктний синтаксис і дозволяти користувачеві вказувати лише значення для конкретних властивостей, які можна змінювати безпечно, наприклад:
template
<a
:href="sanitizedUrl"
:style="{
color: userProvidedColor,
background: userProvidedBackground
}"
>
натисніть мене
</a>
Ін'єкція JavaScript
Наполегливо не рекомендуємо рендерити елементи <script>
за допомогою Vue, оскільки шаблони та функції рендерингу ніколи не повинні мати побічних ефектів. Однак це не єдиний спосіб включити рядки, які будуть оцінюватися як JavaScript під час виконання.
Кожен елемент HTML може мати атрибути, чиї значення приймають рядки JavaScript, наприклад onclick
, onfocus
і onmouseenter
. Прив'язка JavaScript користувачем до будь-якого з цих атрибутів є потенційною загрозою для безпеки, тому подібного слід уникати.
Увага
Запам'ятайте, що JavaScript, що надається користувачем, ніколи не може вважатися безпечним на 100%, якщо не знаходиться в ізольованому iframe або в тій частині додатку, де тільки користувач, який написав цей JS, може отримати до нього доступ.
Іноді ми отримуємо звіти про вразливості про те, як можна виконувати міжсайтовий сценарій (XSS) у шаблонах Vue. Загалом, ми не вважаємо такі випадки справжніми вразливими місцями, оскільки немає практичного способу захистити розробників від двох сценаріїв, які дозволять XSS:
Розробник явно вказує Vue рендерити наданий користувачем необроблений вміст у шаблонах Vue. Це за своєю суттю небезпечно, і Vue не має можливості відстежувати це.
Розробник монтує Vue на всю HTML-сторінку, яка, як виявилося, містить як вміст відрендериний сервером, так і наданий користувачем. Загалом це та сама проблема, що й #1, але іноді розробники можуть робити це, не усвідомлюючи. Це може призвести до можливих уразливостей, коли зловмисник надає HTML, безпечний як звичайний HTML, але небезпечний як шаблон Vue. Найкраще ніколи не монтувати Vue на вузлах, які можуть містити вміст, відрендериний сервером і наданий користувачем.
Найкращі практики
Загальне правило полягає в тому, що якщо ви дозволяєте виконувати необроблений, наданий користувачами вміст (як HTML, JavaScript або навіть CSS), ви можете бути відкритими для атак. Ця порада справді актуальна незалежно від того, чи використовується Vue, інший фреймворк чи навіть без фреймворку.
Крім вищенаведених рекомендацій з розділу Потенційних небезпек, рекомендуємо також ознайомитись з такими ресурсами:
Потім використовуйте отримані знання, щоб також переглянути вихідний код ваших залежностей на наявність потенційно небезпечних шаблонів, якщо будь-який із них містить сторонні компоненти або іншим чином впливає на те, що рендериться в DOM.
Координація з Backend
Уразливості безпеки HTTP, такі як підробка міжсайтових запитів (CSRF/XSRF) або використання міжсайтових скриптів (XSSI), в основному націлені на Backend, тому Vue тут мало чим може допомогти. Тим не менш, рекомендуємо координувати дії з командою розробників Backend, щоб краще дізнатися, як слід взаємодіяти з API, наприклад відправляючи CSRF-токени при відправленні форм.
Додаток з рендерингом на стороні серверу (SSR)
Під час використання SSR існують додаткові проблеми з безпекою, тому обов'язково дотримуйтесь найкращих практик, викладених у нашій SSR документації, щоб уникнути вразливостей.