Если вы пишете на JavaScript, то наверняка слышали, что безопасность — это важно. Но что это значит на практике? В этой статье мы разберем, как защитить ваше приложение от типичных атак, не углубляясь в дебри криптографии. Вы узнаете, какие ошибки чаще всего допускают разработчики, и как их избежать. Будет много кода, примеров и немного житейских аналогий.

Digital-студия WNDER

Почему JavaScript — это лакомый кусок для хакеров

JavaScript — это язык, который работает в браузере у каждого пользователя. Он может обращаться к DOM, отправлять запросы на сервер, хранить данные в localStorage. Если неаккуратно написать код, злоумышленник может перехватить управление. Например, вставить вредоносный скрипт через поле ввода, украсть куки или подменить данные.

Представьте, что ваше приложение — это дом. JavaScript — это окна и двери. Если вы оставите их открытыми, любой прохожий сможет зайти и что-то украсть. Наша задача — закрыть все щели и поставить сигнализацию.

Основные угрозы и как от них защититься

Чаще всего разработчики сталкиваются с такими проблемами:

  • XSS (межсайтовый скриптинг) — когда злоумышленник внедряет свой скрипт в страницу.
  • CSRF (подделка межсайтовых запросов) — когда от имени пользователя отправляются нежелательные запросы.
  • Утечка данных — когда чувствительная информация попадает в неправильные руки.
  • Инъекции — когда код выполняется непреднамеренно.

Давайте разберем каждую угрозу и способы защиты.

Защита от XSS

XSS возникает, когда вы вставляете пользовательский ввод прямо в HTML без обработки. Например:

// Плохо: вставляем ввод напрямую
const userInput = '';
document.getElementById('output').innerHTML = userInput;

В этом случае браузер выполнит код внутри тега img. Чтобы избежать этого, нужно экранировать ввод или использовать textContent вместо innerHTML:

// Хорошо: используем textContent
document.getElementById('output').textContent = userInput;

Если вам все же нужно вставить HTML, используйте библиотеки для санитизации, например, DOMPurify.

Правило: Никогда не доверяйте пользовательскому вводу. Всегда обрабатывайте его перед вставкой в DOM.

Защита от CSRF

CSRF — это когда злоумышленник отправляет запрос от имени пользователя, используя его куки. Например, если пользователь залогинен в банке, а на другом сайте есть форма, которая отправляет запрос на перевод денег. Чтобы защититься, используйте CSRF-токены.

Токен — это случайная строка, которую сервер отправляет клиенту и проверяет при каждом запросе. Вот как это может выглядеть:



// На клиенте отправляем токен с каждым запросом
fetch('/transfer', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json',
        'CSRF-Token': csrfToken
    },
    body: JSON.stringify({ amount: 100 })
});

Сервер должен проверить токен и отклонить запрос, если он не совпадает.

Защита от утечек данных

Часто данные утекают из-за того, что мы храним их не там, где нужно. Например, не стоит хранить пароли в localStorage. Для этих целей есть специальные механизмы — куки с флагом HttpOnly, которые недоступны для JavaScript. Это значит, что даже если злоумышленник внедрит скрипт, он не сможет прочитать куки.

Также следует избегать передачи чувствительных данных в URL-параметрах. Лучше использовать POST-запросы.

Инъекции

Инъекции в JavaScript обычно связаны с eval() или new Function(). Эти функции выполняют строки как код, и если строка содержит пользовательский ввод, это опасно.

// Плохо: используем eval
const userCode = 'alert(1)';
eval(userCode);

Вместо этого используйте безопасные методы, например, JSON.parse для разбора данных.

Безопасность на уровне зависимостей

Вы используете npm-пакеты? Тогда вы знаете, что они могут содержать уязвимости. Проверяйте свои зависимости с помощью npm audit:

npm audit fix

Это покажет, какие пакеты имеют известные проблемы, и предложит обновления.

ИнструментНазначение
npm auditПроверка уязвимостей в зависимостях
SnykМониторинг безопасности в реальном времени
OWASP Dependency-CheckПоиск известных CVE в библиотеках

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

  • Используйте строгий режим ('use strict') — он предотвращает некоторые ошибки.
  • Обрабатывайте ошибки с помощью try/catch, но не выводите детали в консоль.
  • Не используйте глобальные переменные — они могут быть переопределены.
  • Проверяйте ввод на стороне сервера, а не только на клиенте.
  • Используйте HTTPS, чтобы шифровать данные при передаче.
Лайфхак: Включите Content Security Policy (CSP) — это заголовок, который ограничивает, откуда браузер может загружать скрипты. Так вы заблокируете многие XSS-атаки.

Что в итоге

Безопасность — это не одноразовое действие, а постоянный процесс. Начните с простых шагов: экранируйте ввод, используйте токены, проверяйте зависимости. Это уже значительно снизит риски.

Помните: ваш код — это крепость. Чем больше слоев защиты, тем сложнее злоумышленнику проникнуть внутрь. И не забывайте про обновления — они закрывают известные дыры.

Если вы хотите углубиться в тему, изучите OWASP Top 10 — это список самых критичных уязвимостей веб-приложений. Но даже без этого вы уже знаете достаточно, чтобы писать безопасный код на JavaScript.

Студия WNDER