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 (с проверенными реализациями).

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