Чек-лист безопасности веб-приложений для разработчиков

Это практический, готовый к аудиту чек-лист, сопоставленный с уровнями верификации OWASP ASVS 4.0.3 и идентификаторами тестов WSTG, которыми реально пользуется пентестер. Каждый пункт — конкретный контроль, который можно внедрить, увидеть в диффе и протестировать в CI, а не лозунг. Идите сверху вниз; каждый непроставленный флажок считайте открытой находкой.

Аутентификация и управление сессиями

Сбои аутентификации соответствуют OWASP Top 10 A07:2021 и главам ASVS V2 (Authentication) и V3 (Session Management). Цель — сделать кражу учётных данных, brute force и фиксацию сессии структурно невозможными, а не просто затруднёнными. Проверяйте каждый пункт по WSTG-ATHN и WSTG-SESS.

  • Храните пароли с памяте-затратной KDF: Argon2id (≥19 MiB, t=2, p=1) либо bcrypt со стоимостью ≥10 / scrypt — никогда MD5, SHA-1 или несолёный SHA-256 (ASVS V2.4).
  • Требуйте минимум 12 символов, разрешайте весь диапазон Unicode и пробелы и проверяйте новые пароли по базе утечек (API k-анонимности HIBP) — не навязывайте правила сложности и принудительную ротацию (ASVS V2.1, NIST SP 800-63B).
  • Ограничивайте частоту попыток входа с экспоненциальной задержкой на аккаунт и на IP-адрес; возвращайте идентичные ответы и тайминги для верных и неверных логинов, чтобы предотвратить перебор пользователей (WSTG-ATHN-03).
  • Генерируйте идентификаторы сессии через CSPRNG (≥128 бит энтропии) и пересоздавайте идентификатор сессии при каждой смене привилегий — входе, выходе и step-up — чтобы устранить session fixation (WSTG-SESS-03).
  • Устанавливайте cookie сессии как HttpOnly, Secure и SameSite=Lax или Strict; ограничивайте их префиксом __Host- без явного атрибута Domain (ASVS V3.4).
  • Применяйте на стороне сервера и таймаут по бездействию, и абсолютное время жизни сессии; аннулируйте токен сессии на сервере при выходе, а не только на клиенте.
  • Предлагайте устойчивый к фишингу MFA — WebAuthn/FIDO2 или TOTP — и никогда SMS как единственный второй фактор; требуйте повторный MFA перед чувствительными действиями (ASVS V2.2, V2.7).
  • Делайте токены сброса пароля одноразовыми, короткоживущими (≤1 час), случайными и доставляемыми вне основного канала; аннулируйте все активные сессии при смене пароля (WSTG-ATHN-09).

Контроль доступа и авторизация

Broken Access Control — это A01:2021, риск номер один. Большинство таких багов — логические изъяны, которые не найдёт ни один сканер, поэтому нужны явная серверная проверка и контроль на уровне каждого объекта. Тестируйте по WSTG-ATHZ (IDOR, эскалация привилегий, path traversal).

  • Проверяйте авторизацию на сервере для каждого запроса; по умолчанию запрещайте и никогда не полагайтесь на скрытый элемент UI, отключённую кнопку или клиентскую проверку роли как на контроль.
  • Проверяйте владение на уровне объекта при каждом доступе — получите ресурс, затем подтвердите, что аутентифицированный субъект вправе действовать с этим конкретным ID — чтобы предотвратить IDOR / BOLA (WSTG-ATHZ-04).
  • Используйте непредсказуемые или косвенные ссылки на объекты (UUIDv4 или маппинг на пользователя), но считайте это защитой в глубину, а не заменой проверки владения выше.
  • Централизуйте авторизацию в одном слое middleware/политик (например, движок ABAC/RBAC), а не разбрасывайте разрозненные if по контроллерам.
  • Блокируйте пути эскалации привилегий: убедитесь, что пользователь не может задать себе роль, tenant_id или флаг is_admin через mass-assignment на эндпоинтах создания/обновления (WSTG-ATHZ-02).
  • Применяйте защиту от CSRF на всех изменяющих состояние запросах — синхронизирующий токен либо cookie SameSite плюс валидация Origin/Referer для чувствительных к cross-site действий (WSTG-SESS-05).
  • Валидируйте и канонизируйте пути файлов и импортируемые URL, чтобы заблокировать directory traversal (../) и SSRF к внутренним эндпоинтам метаданных вроде 169.254.169.254 (WSTG-ATHZ-01, A10:2021).

Валидация ввода и кодирование вывода

Injection — это A03:2021. Устойчивое решение — разделение кода и данных на каждой границе интерпретатора: SQL, шелл ОС, LDAP, XML и DOM браузера. Валидируйте ввод по намерению, но реальную защиту стройте на контекстном кодировании вывода и параметризации (WSTG-INPV).

  • Используйте параметризованные запросы / prepared statements или проверенный ORM для всего доступа к БД; никогда не собирайте SQL конкатенацией строк, а любой динамический идентификатор (таблица/колонка) проверяйте по allowlist (WSTG-INPV-05).
  • Валидируйте весь ввод по позитивному allowlist — тип, длину, формат и диапазон — на границе доверия; где возможно, отклоняйте, а не санитизируйте (ASVS V5.1).
  • Применяйте контекстное кодирование вывода для защиты от XSS: кодирование HTML-сущностей в теле HTML, кодирование атрибутов в атрибутах и кодирование JavaScript/URL в их контекстах — предпочитайте авто-экранирующие шаблонизаторы (WSTG-CLNT-01).
  • Избегайте выполнения команд ОС с пользовательским вводом; если неизбежно — используйте API с массивом аргументов (execFile, а не shell=True) и никогда не пропускайте данные через интерпретатор шелла (WSTG-INPV-12).
  • Отключайте разбор внешних сущностей XML (XXE) в каждом парсере XML/SOAP/SVG — задайте FEATURE_SECURE_PROCESSING и запретите DOCTYPE (A05:2021, WSTG-INPV-07).
  • Отклоняйте небезопасную десериализацию: никогда не десериализуйте недоверенные данные в произвольные типы; используйте ограниченный схемой формат вроде JSON с явным маппингом полей (A08:2021).
  • Внедрите серверный контроль загрузки файлов: проверяйте тип содержимого по magic bytes, ограничивайте размер, храните вне web root и отдавайте с Content-Disposition: attachment.
  • Валидируйте цели редиректов по allowlist, чтобы предотвратить open redirect, применяемый в фишинге (WSTG-CLNT-04).

Заголовки безопасности (CSP, HSTS и другие)

Заголовки HTTP-ответов — дешёвая и высокорычажная защита в глубину против XSS, кликджекинга и понижения протокола. Отсутствие заголовков относится к A05:2021 Security Misconfiguration; проверяйте через WSTG-CONF-07 и сканер вроде securityheaders.com или Mozilla Observatory.

  • Разверните строгий Content-Security-Policy: предпочитайте script-src на основе nonce или hash с 'strict-dynamic', задайте object-src 'none' и base-uri 'none', избегайте 'unsafe-inline' — выкатывайте сначала через Content-Security-Policy-Report-Only.
  • Установите Strict-Transport-Security: max-age=31536000; includeSubDomains; preload и подайте домен в список HSTS preload, чтобы заблокировать SSL-stripping.
  • Отправляйте X-Content-Type-Options: nosniff в каждом ответе, чтобы остановить MIME sniffing.
  • Предотвращайте кликджекинг через frame-ancestors 'none' (или явный allowlist) в CSP; оставьте X-Frame-Options: DENY как запасной вариант для старых браузеров.
  • Задайте Referrer-Policy: strict-origin-when-cross-origin, чтобы не утекали полные URL (и токены в них) к третьим сторонам.
  • Ограничьте возможности браузера через Permissions-Policy (например, geolocation=(), camera=(), microphone=()) и установите Cross-Origin-Opener-Policy: same-origin.
  • Настраивайте CORS явно: отражайте только проверенные origin, никогда не сочетайте Access-Control-Allow-Origin: * с Allow-Credentials: true и валидируйте заголовок Origin на сервере (WSTG-CLNT-07).

Безопасность зависимостей и цепочки поставок

Уязвимые и устаревшие компоненты — это A06:2021; здесь живут инциденты класса SolarWinds и Log4Shell. Дисциплина в том, чтобы точно знать, что вы поставляете, проверять целостность и патчить по расписанию. Ориентируйтесь на SLSA и NIST SSDF.

  • Запускайте автоматический SCA (Dependabot, npm audit, OWASP Dependency-Check, Trivy) в CI и обрывайте сборку при известных эксплуатируемых (из списка KEV) или высокой критичности CVE.
  • Фиксируйте зависимости на точных версиях и коммитьте lockfile (package-lock.json, poetry.lock, go.sum), чтобы сборки были воспроизводимыми и верифицировались по хешу.
  • Генерируйте и храните SBOM (CycloneDX или SPDX) для каждого релиза, чтобы за минуты после нового CVE ответить на вопрос «затронуты ли мы?».
  • Проверяйте транзитивные зависимости и следите за typosquatting / dependency confusion; резервируйте имена внутренних пакетов и настройте registry на приоритет приватного индекса.
  • Проверяйте целостность артефактов подписями (Sigstore/cosign) и фиксируйте сторонние GitHub Actions на полный SHA коммита, а не на изменяемый тег.
  • Подпишитесь на бюллетени безопасности ключевых фреймворков и задайте SLA — например, критические CVE патчатся за 72 часа, высокие — за 7 дней.
  • Удаляйте неиспользуемые зависимости и мёртвые фичи; каждый пакет, который вы не поставляете, — это поверхность атаки, которую вам не нужно защищать.

Управление секретами

Захардкоженные учётные данные — извечная находка (CWE-798) и часть A05:2021. Секреты не должны попадать в исходники, образы и логи; их следует внедрять во время выполнения, ротировать и ограничивать минимальными привилегиями. Проверяйте по ASVS V6 (Stored Cryptography) и V2.10 (учётные данные сервисов).

  • Держите секреты вне системы контроля версий; сканируйте репозиторий и всю историю git с помощью gitleaks или trufflehog и внедрите сканер секретов в pre-commit / CI как блокирующий гейт мержа.
  • Храните секреты в выделенном менеджере (HashiCorp Vault, AWS Secrets Manager, GCP Secret Manager) или зашифрованном хранилище платформы — внедряйте через окружение или примонтированный том во время выполнения, никогда не запекайте их в образы контейнеров.
  • Ротируйте учётные данные по расписанию и немедленно при подозрении на утечку; предпочитайте короткоживущие, динамически выдаваемые учётные данные (dynamic secrets Vault, облачные IAM-роли / OIDC-федерация) долгоживущим статическим ключам.
  • Ограничивайте каждый секрет минимальными привилегиями — отдельный пользователь БД на сервис только с нужными грантами — чтобы одна утечка не скомпрометировала всю систему.
  • Никогда не логируйте секреты, токены или полные заголовки авторизации; добавьте фильтры редактирования в конвейер логирования и проверьте, что они работают.
  • Шифруйте секреты в покое управляемым KMS и держите ключевой материал вне той же границы доверия, что и защищаемые им данные.

Логирование, мониторинг и обнаружение

Сбои логирования и мониторинга безопасности — это A09:2021: нельзя реагировать на то, чего не видишь. Логируйте значимые для безопасности события структурированно и в защищённом от подделки виде и подключайте их к оповещениям. Проверяйте по ASVS V7 и сигнатурам атак, выведенным из WSTG.

  • Логируйте все события аутентификации (успех и провал), отказы контроля доступа, отклонения валидации ввода и действия администратора — с указанием кто, что, когда и откуда, в структурированном JSON (ASVS V7.1).
  • Никогда не логируйте чувствительные данные — пароли, токены сессий, полные номера карт, секреты — и нейтрализуйте log injection кодированием недоверенных значений (CWE-117).
  • Отправляйте логи за пределы хоста в централизованное хранилище только-на-добавление (SIEM), чтобы захвативший машину атакующий не мог стереть следы; храните согласно требованиям комплаенса.
  • Оповещайте о сигналах безопасности почти в реальном времени: всплески brute-force, серии отказов авторизации, создание нового админа и известные паттерны атак — с маршрутом on-call.
  • Включайте ID корреляции/запроса между сервисами, чтобы инцидент можно было восстановить end-to-end.
  • Тестируйте своё обнаружение: проведите атаку (или учение purple team) и убедитесь, что событие действительно поднимает алерт — непротестированное логирование это театр.
  • Синхронизируйте часы (NTP) и записывайте метки времени в UTC, чтобы межсистемные таймлайны были надёжны при форензике.

TLS и безопасность транспорта

Cryptographic Failures — это A02:2021. Все данные в передаче должны шифроваться современным, правильно настроенным TLS; валидный сертификат необходим, но недостаточен. Тестируйте через WSTG-CRYP-01, testssl.sh и SSL Labs, целясь в оценку A+.

  • Отдавайте всё по HTTPS и перенаправляйте HTTP на HTTPS; вместе с HSTS preload не допускайте отката на plaintext.
  • Поддерживайте только TLS 1.2 и TLS 1.3; отключите SSLv3, TLS 1.0 и TLS 1.1 и уберите наборы шифров export/NULL/RC4/3DES (WSTG-CRYP-01).
  • Предпочитайте AEAD-наборы шифров (AES-GCM, ChaCha20-Poly1305) и включайте forward secrecy только через обмен ключами ECDHE.
  • Используйте сертификаты доверенного CA с ключом RSA ≥2048 бит или ECDSA P-256; автоматизируйте выпуск и продление (ACME/Let's Encrypt), чтобы сертификаты никогда молча не истекали.
  • Включите OCSP stapling и рассмотрите DNS-записи CAA, чтобы ограничить, какие CA могут выпускать сертификаты для вашего домена.
  • Терминируйте TLS и для внутреннего трафика между сервисами (mTLS где практично) — не считайте внутреннюю сеть доверенной.
  • Для нативных/мобильных клиентов рассмотрите certificate pinning и всегда проверяйте полную цепочку и имя хоста — никогда не отключайте проверку «чтобы заработало».

Главное

  • Проверяйте каждое решение контроля доступа и авторизации на сервере, на уровне объекта — Broken Access Control (A01) это риск номер один, и эти логические изъяны сканер за вас не найдёт.
  • Побеждайте injection (A03) параметризованными запросами и контекстным кодированием вывода, а не фильтрацией по blocklist.
  • Разверните строгий CSP на основе nonce плюс HSTS preload, X-Content-Type-Options и frame-ancestors — дешёвые заголовки, притупляющие XSS, понижение протокола и кликджекинг.
  • Держите секреты вне кода, ротируйте их и предпочитайте короткоживущие динамически выдаваемые учётные данные статическим ключам.
  • Нельзя реагировать на то, что не логируешь: структурированное, защищённое от подделки логирование безопасности с протестированными оповещениями закрывает A09.
  • Сопоставляйте работу с уровнями OWASP ASVS и идентификаторами тестов WSTG, чтобы «безопасно» стало проверяемым, а не декларативным.

Частые вопросы

В чём разница между OWASP ASVS и OWASP Top 10?+

Top 10 — это документ для повышения осведомлённости, ранжирующий десять наиболее критичных категорий риска (например, A01 Broken Access Control). ASVS — детальный тестируемый стандарт верификации с сотнями конкретных требований по трём уровням доверия (L1–L3). Используйте Top 10 для коммуникации риска, а ASVS как реальный инженерный чек-лист.

Какой уровень ASVS должно достигать моё приложение?+

Уровень 1 — минимум для любого приложения и по большей части проверяем методами black-box. Уровень 2 — стандарт для приложений с чувствительными данными; большинству бизнес-приложений следует целиться в L2. Уровень 3 — для систем наивысшего доверия (платежи, здоровье, критическая инфраструктура) и требует глубокого ревью дизайна.

Может ли чек-лист заменить пентест?+

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

Как часто запускать сканирование зависимостей?+

Непрерывно. Встройте SCA (Dependabot, Trivy, OWASP Dependency-Check) в каждый прогон CI, чтобы новый код проверялся при коммите, и запускайте плановые сканы основных веток, чтобы свежераскрытые CVE в уже смерженных зависимостях ловились даже когда никто не деплоит.

Хотите проверить этот чек-лист на своём работающем приложении? MonMyIP проводит структурированную оценку на базе ASVS/WSTG и выдаёт приоритизированный отчёт по устранению с доказательной базой. Закажите пентест веб-приложения с определённым скоупом.