07.04.2025 10:25
Практики secure coding: как избежать типовых уязвимостей
Не доверяйте входным данным
Любые данные извне потенциально небезопасны. Это касается не только форм и HTTP-запросов, но и файлов, заголовков, куков, аргументов командной строки и даже содержимого базы данных.
• Валидируйте все входные данные: по типу, длине, диапазону значений и формату.
• Применяйте подход белых списков — разрешайте только явно допустимые значения.
• При работе с JSON используйте валидаторы: Ajv, Joi, zod и аналогичные.
Контролируйте вывод
(XSS) XSS остаётся одной из наиболее распространённых уязвимостей в веб-приложениях. Любой вывод пользовательских данных в HTML должен быть безопасным.
• Экранируйте все пользовательские данные перед отображением.
• Избегайте использования innerHTML, атрибутов и inline-скриптов для вставки данных.
• Внедрите Content Security Policy (CSP), чтобы ограничить выполнение несанкционированного кода.
Ошибки и логи
Подробные сообщения об ошибках полезны на этапе разработки, но могут стать источником утечек информации для злоумышленников.
• Отключайте подробные сообщения об ошибках в продакшене.
• Исключайте из логов чувствительные данные: пароли, токены, ключи доступа.
• Логируйте достаточно для диагностики, но ничего, что может помочь атакующему.
Храните секреты правильно
Секреты — это не только пароли, но и API-ключи, токены, данные конфигурации и подключения.
• Никогда не храните секреты в исходном коде или .env-файлах, находящихся под контролем версий.
• Используйте специализированные системы управления секретами: HashiCorp Vault, AWS Secrets Manager, Doppler и другие.
• Шифруйте секреты как при хранении, так и при передаче.
Минимизируйте поверхность атаки
Чем меньше открытых точек входа, тем сложнее взломать систему.
• Удаляйте неиспользуемые эндпоинты и dev-инструменты перед релизом.
• Внедряйте разграничение доступа по ролям и уровням привилегий.
• Скрывайте внутренние API и административные интерфейсы за аутентификацией и сетевыми фильтрами.
Обновляйте зависимости
Уязвимости часто проникают через сторонние библиотеки, даже если собственный код написан безопасно.
• Настройте автоматическое обновление и мониторинг зависимостей.
• Используйте инструменты типа npm audit, pip-audit, Snyk, Renovate.
• Обращайте внимание на транзитивные зависимости и репутацию источников.
Разделяйте аутентификацию и авторизацию
Аутентификация отвечает на вопрос кто вы, а авторизация — что вам разрешено делать. Оба аспекта критически важны.
• Проводите все проверки прав доступа на серверной стороне.
• Не полагайтесь на клиентскую логику для ограничения доступа.
• Используйте модели управления доступом: RBAC, ABAC — в зависимости от сложности проекта.
Избегайте самодельной криптографии Криптография — область, в которой «написать самому» почти всегда означает создать уязвимость.
• Используйте проверенные библиотеки и протоколы.
• Не генерируйте ключи или токены вручную, особенно с помощью ненадёжных генераторов (Math.random(), rand() и т.п.).
• Для аутентификации и авторизации применяйте стандартизированные решения: OAuth, OpenID Connect, JWT (с проверенными реализациями).
Безопасность — это не тормоз разработки, а защита вашего времени, бюджета и репутации. Типовые уязвимости редко возникают из-за злонамеренных действий — гораздо чаще они появляются из-за спешки, привычки или отсутствия базовой гигиены кода. Инвестируйте в безопасность на этапе разработки — и это избавит вас от множества проблем в будущем.