Аудит безопасности

Intro.js — это лёгкая и удобная библиотека для создания интерактивных пошаговых инструкций по интерфейсу веб-приложений. Её использование требует особого внимания с точки зрения безопасности, так как любая клиентская библиотека, внедряемая в проект, потенциально увеличивает поверхность атаки. Важные аспекты включают защиту от XSS, безопасное подключение скриптов и контроль доступа к DOM-элементам.


Подключение библиотеки и безопасные практики

Библиотеку следует подключать через доверенные источники, например, через официальные CDN Intro.js или локально, чтобы исключить возможность подмены скрипта злоумышленником:

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/intro.js/minified/introjs.min.css">
<script src="https://cdn.jsdelivr.net/npm/intro.js/minified/intro.min.js"></script>

При локальном подключении необходимо убедиться, что файлы находятся в защищённой директории и не подвержены модификации извне. Рекомендуется использовать Subresource Integrity (SRI) для проверки целостности скриптов и стилей при загрузке с внешних ресурсов:

<script src="https://cdn.jsdelivr.net/npm/intro.js/minified/intro.min.js"
        integrity="sha384-<hash_value>"
        crossorigin="anonymous"></script>

Инициализация и управление шагами

Intro.js позволяет создавать пошаговые инструкции через атрибуты data-intro и data-step на элементах DOM:

<button data-step="1" data-intro="Это кнопка запуска">Запуск</button>
<div data-step="2" data-intro="Здесь отображаются результаты">Результаты</div>

Инициализация выполняется следующим образом:

const intro = introJs();
intro.setOptions({
    nextLabel: 'Далее',
    prevLabel: 'Назад',
    skipLabel: 'Пропустить',
    doneLabel: 'Готово',
    hidePrev: true
});
intro.start();

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


Защита от XSS при использовании Intro.js

Содержимое подсказок (data-intro) по умолчанию интерпретируется как HTML. Для предотвращения межсайтового скриптинга (XSS) рекомендуется:

  1. Использовать только статический текст или экранированные данные.
  2. При динамическом формировании текста подсказок применять безопасное экранирование:
function escapeHtml(unsafe) {
    return unsafe
         .replace(/&/g, "&amp;")
         .replace(/</g, "&lt;")
         .replace(/>/g, "&gt;")
         .replace(/"/g, "&quot;")
         .replace(/'/g, "&#039;");
}

const userInput = "<script>alert('XSS')</script>";
intro.setOptions({
    steps: [
        { element: '#userStep', intro: escapeHtml(userInput) }
    ]
});
  1. Исключить возможность вставки <script>, on* атрибутов или inline-стилей через пользовательский ввод.

Контроль доступа к шагам и ролям

При использовании Intro.js в приложениях с разными уровнями прав важно проверять доступ к определённым шагам интерфейса. Пример с ограничением шагов для обычного пользователя:

const steps = [
    { element: '#adminPanel', intro: 'Панель администратора', visibleForRoles: ['admin'] },
    { element: '#userDashboard', intro: 'Панель пользователя', visibleForRoles: ['admin', 'user'] }
];

const userRole = getCurrentUserRole();

const filteredSteps = steps.filter(step => step.visibleForRoles.includes(userRole));

intro.setOptions({ steps: filteredSteps });
intro.start();

Такой подход предотвращает показ информации, недоступной текущему пользователю.


Защита от фишинга и подмены интерфейса

Intro.js создаёт визуальные оверлеи и подсказки поверх элементов. Злоумышленник может попытаться подменить контент страницы или подсказки, чтобы обмануть пользователя. Для снижения риска:

  • Проверять целостность DOM перед запуском интро:
const requiredElements = ['#loginButton', '#dashboard'];
const allPresent = requiredElements.every(sel => document.querySelector(sel));
if (allPresent) {
    intro.start();
} else {
    console.warn('Некоторые элементы отсутствуют, интро не запускается');
}
  • Запускать Intro.js только на доверенных страницах, избегая динамически загружаемых чужих фреймов.

Логи и аудит действий пользователя

Для целей аудита безопасности полезно фиксировать запуск интро и переходы по шагам, особенно если интерактивные подсказки связаны с управлением критическими функциями:

intro.onchange(function(targetElement) {
    logAction({
        element: targetElement.id,
        step: intro._currentStep,
        timestamp: new Date().toISOString()
    });
});

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


Настройка безопасных стилей и кастомизации

Intro.js поддерживает кастомизацию через CSS. Важно:

  • Не использовать динамические стили, основанные на пользовательском вводе.
  • Ограничивать внедрение внешних стилей через !important, чтобы предотвратить перекрытие защитных элементов интерфейса.
  • Минимизировать использование inline-стилей с непроверенными данными.

Обновления и поддержка библиотеки

Для поддержания безопасности необходимо регулярно обновлять Intro.js до актуальной версии. В новых версиях исправляются:

  • Уязвимости XSS
  • Проблемы с управлением фокусом
  • Некорректная обработка динамических шагов

Следует мониторить официальный репозиторий библиотеки и использовать только стабильные релизы.


Контроль событий и предотвращение обхода

Intro.js позволяет использовать обратные вызовы (onbeforechange, oncomplete). Для безопасного применения:

  • Проверять условия доступа перед переходом на следующий шаг.
  • Блокировать обход, если шаг требует авторизации или наличия данных:
intro.onbeforechange(function(targetElement) {
    if (!userHasAccess(targetElement.id)) {
        return false; // отменяет переход
    }
});
  • Ограничивать выполнение критических функций только после прохождения всех безопасных проверок.

Практика безопасного использования Intro.js

  • Подключать библиотеку через SRI или локально.
  • Экранировать динамические подсказки.
  • Контролировать доступ к шагам по ролям.
  • Проверять целостность DOM перед запуском интро.
  • Логировать действия пользователей для аудита.
  • Регулярно обновлять библиотеку до последних безопасных версий.

Эти меры формируют надёжную базу для безопасного внедрения интерактивных инструкций с помощью Intro.js в любом веб-приложении.