Вы пишете на JavaScript и думаете, что безопасность — это не ваша забота? Ошибаетесь. Почти 70% веб-приложений имеют уязвимости, и большинство из них связаны с фронтендом. В этой статье мы разберём, как писать код так, чтобы злоумышленник не украл данные ваших пользователей и не превратил ваш сайт в зомби-сеть.
Почему JavaScript — лакомая цель для хакеров
JavaScript выполняется прямо в браузере пользователя. Это значит, что любой может открыть консоль разработчика и посмотреть, как работает ваш код. А ещё — найти дыры. Самое частое: вы вставляете данные от пользователя прямо в HTML без проверки. Или храните секретные ключи в открытом виде. Или доверяете данным с клиента так, будто это святое писание.
Давайте разберём основные угрозы и как от них защититься.
XSS: когда ваш сайт начинает работать на хакера
XSS (Cross-Site Scripting) — это как если бы в ваш дом залез вор и начал выдавать себя за вас. Злоумышленник вставляет свой JavaScript-код на вашу страницу, и он выполняется в браузере жертвы. Может украсть куки, пароли, перенаправить на фишинговый сайт.
Пример уязвимого кода:
// ПЛОХО: прямое использование данных пользователя
const userInput = document.getElementById('comment').value;
document.getElementById('output').innerHTML = userInput;
Если пользователь введёт <script>alert('взлом')</script>, скрипт выполнится. Вот как надо:
// ХОРОШО: экранирование или textContent
const userInput = document.getElementById('comment').value;
document.getElementById('output').textContent = userInput;
// или использовать библиотеку для очистки, например DOMPurify
Также всегда устанавливайте заголовок Content-Security-Policy (CSP). Он запрещает выполнение сторонних скриптов.
CSRF: как заставить пользователя сделать то, чего он не хочет
CSRF (Cross-Site Request Forgery) — это когда злоумышленник заставляет вашего пользователя отправить запрос от его имени. Например, перевести деньги или сменить пароль. Пользователь просто заходит на вредоносный сайт, а тот шлёт запрос на ваш сервер, используя куки жертвы.
Защита проста: используйте токены CSRF. Сервер генерирует случайный токен, вставляет его в форму, а при отправке проверяет. Если токен не совпадает — отказ.
Пример на Node.js с Express:
const csrf = require('csurf');
const csrfProtection = csrf({ cookie: true });
app.get('/form', csrfProtection, (req, res) => {
res.render('form', { csrfToken: req.csrfToken() });
});
app.post('/process', csrfProtection, (req, res) => {
// обрабатываем данные
});
В форме на клиенте добавьте скрытое поле с токеном:
<form action="/process" method="POST">
<input type="hidden" name="_csrf" value="{{csrfToken}}">
<!-- остальные поля -->
</form>
Инъекции в JavaScript: не только SQL
Инъекции бывают разные: SQL, NoSQL, командные. В JavaScript-приложениях часто страдают запросы к базам данных, если вы склеиваете строки. Например, в MongoDB:
// ПЛОХО: конкатенация строк
const query = { username: req.body.username, password: req.body.password };
// Если злоумышленник передаст { "$ne": null }, он войдёт без пароля
Правильно использовать параметризованные запросы или ORM. В Mongoose:
// ХОРОШО: явное приведение типов
const username = String(req.body.username);
const password = String(req.body.password);
const user = await User.findOne({ username, password });
Всегда проверяйте типы данных. Не доверяйте тому, что приходит с клиента.
Безопасность зависимостей: ваш node_modules — мина
Средний проект на JavaScript тянет сотни пакетов. Каждый из них может содержать уязвимость. В 2021 году пакет ua-parser-js был взломан и воровал криптовалюту. Как защититься?
- Регулярно запускайте
npm auditи исправляйте проблемы. - Используйте
npm outdatedдля проверки устаревших пакетов. - Подключайте только проверенные библиотеки с активным сообществом.
- Фиксируйте версии в package-lock.json.
Вот таблица с основными инструментами для проверки зависимостей:
| Инструмент | Что делает | Как использовать |
|---|---|---|
| npm audit | Находит уязвимости в зависимостях | npm audit |
| Snyk | Сканирует код и зависимости | npx snyk test |
| OWASP Dependency-Check | Проверяет на известные CVE | Интеграция в CI/CD |
Практические советы для ежедневной работы
Вот несколько привычек, которые сделают ваш код безопаснее:
- Используйте
constиletвместоvar— меньше шансов случайно перезаписать переменную. - Всегда проверяйте входные данные на стороне сервера, даже если уже проверили на клиенте.
- Храните секреты (ключи API, пароли) в переменных окружения, а не в коде.
- Настройте HTTPS и HSTS. Без шифрования любой может перехватить трафик.
- Ограничьте права пользователей в базе данных — не давайте root-доступ приложению.
- Логируйте подозрительные действия, но не пишите в логи пароли и токены.
Что в итоге
Безопасность в JavaScript — это не пара трюков, а образ мышления. Всегда спрашивайте себя: «А что, если пользователь пришлёт что-то неожиданное?» Экранируйте вывод, проверяйте вход, используйте токены, следите за зависимостями. И помните: безопасность — это процесс, а не галочка в чек-листе.
Начните с малого: сегодня замените innerHTML на textContent и запустите npm audit. Завтра настроите CSP. Через месяц ваш проект станет крепче, а вы — спокойнее.



