Безопасность веб-приложений: частые уязвимости и защита от них

Безопасность веб приложений сводится к управлению рисками: закрыть типовые уязвимости (OWASP), выстроить надёжную аутентификацию/сессии, исключить инъекции и XSS, исправить контроль доступа и закрепить всё процессами (CI/CD, мониторинг). Практика - это повторяемые проверки, автоматизация и регулярное тестирование безопасности веб приложений до релиза и после изменений.

Краткая картина основных угроз и сценариев атак

  • Утечки данных из-за ошибок контроля доступа (IDOR, обход ролей, прямые ссылки на объекты).
  • Инъекции (SQL/NoSQL/OS/шаблонные) через параметры, заголовки, файлы и интеграции.
  • XSS в пользовательском контенте и в рендеринге шаблонов, кража токенов/сессий, подмена действий.
  • Захват аккаунтов через слабые пароли, отсутствие MFA, неверную обработку сессий и cookie.
  • Ошибки конфигурации и зависимостей: открытые админки, debug, уязвимые библиотеки, неверные заголовки безопасности.
  • Сбои в цепочке поставки: небезопасные пайплайны, секреты в репозитории, подмена артефактов.

OWASP Top 10: что реально встречается и как это эксплуатируют

OWASP Top 10 - это практичная таксономия наиболее распространённых классов уязвимостей в веб-приложениях. Она полезна для того, чтобы одинаково говорить о рисках, строить чек-листы и планировать аудит безопасности веб приложения по категориям: доступ, инъекции, конфигурация, зависимости, логирование и т.д.

Важно понимать границы: Top 10 - не "список конкретных багов", а набор классов. Уязвимость конкретного проекта появляется только при сочетании кода, конфигурации, данных и процессов (например, безопасный код + небезопасный деплой всё равно даст дыру).

Типовая эксплуатация выглядит так: атакующий находит вход (параметр, endpoint, файл, интеграцию), проверяет поведение (ошибки, различия ответов, тайминги), затем закрепляется (сессия/токен) и расширяет доступ (IDOR/привилегии/инъекция).

Класс уязвимости Признаки в приложении/логах Рабочие контрмеры
Broken Access Control (IDOR, обход ролей) Доступ к чужим объектам при смене ID; разные ответы 200/403 для близких URL; скачки ролей без админ-действий Проверки авторизации на сервере для каждого объекта; policy/guard на уровне домена; тесты на матрицу ролей
Инъекции (SQL/NoSQL/OS/Template) Ошибки парсера/СУБД; аномальные символы в параметрах; неожиданные задержки; всплеск 500 Параметризация/ORM без конкатенации; allowlist для команд/полей; экранирование по контексту; минимальные привилегии БД
XSS (reflected/stored/DOM) Подозрительные payload в полях ввода; жалобы на редиректы/попапы; нестандартные запросы к сторонним доменам Контекстное экранирование; CSP; запрет опасного HTML или строгая санитизация; HttpOnly/SameSite cookies
Ошибки аутентификации/сессий Подбор паролей, всплеск 401/403; частые логины с разных IP; сессии живут слишком долго MFA; rate limiting; хэширование паролей устойчивыми алгоритмами; ротация и привязка сессий; безопасные cookie
Security misconfiguration / уязвимые зависимости Доступный /debug, /metrics; стек-трейсы; устаревшие версии библиотек; лишние открытые порты Hardening окружений; SBOM/скан зависимостей; запрет debug в prod; заголовки безопасности; принцип минимизации

Практический чек-лист для ориентира по OWASP-классам

  • Сопоставьте свои функции с категориями OWASP и заведите задачи на покрытие тестами (unit/integration/security).
  • Определите "критические потоки": логин, платежи, смена email/пароля, загрузка файлов, админка.
  • Заставьте сервер быть источником истины: не доверяйте клиенту роли, цене, правам, флагам.
  • Включите безопасные дефолты в шаблонах/фреймворке (экранирование, CSRF, secure cookies).

Аутентификация и управление сессиями: надёжность и уязвимые паттерны

Аутентификация отвечает на вопрос "кто пользователь", а сессия/токен - "какое состояние доверия сейчас действует". Слабое звено обычно не в "криптографии", а в логике: где хранятся токены, как долго живут, как отзываются, что происходит при смене пароля, и какие действия разрешены без повторной проверки.

  • Идентификация: логин/почта/телефон → нормализация и единые правила сравнения, чтобы не было дублей и обходов.
  • Проверка секрета: пароль/ключ → хранение только хэшей, защита от перебора (rate limit, lockout по риску).
  • Выдача сессии: cookie или bearer-токен → атрибуты Secure/HttpOnly/SameSite, ограничение домена/пути.
  • Срок жизни: короткий access + обновляемый refresh, ротация refresh при каждом использовании.
  • Отзыв: принудительный logout, отзыв по компрометации, отзыв при смене пароля/почты.
  • Повышение привилегий: для критических операций требуйте re-auth или step-up (MFA).

Мини-пример проверки cookie-политик (команды для диагностики)

curl -I https://example.com/login
# Ищите Set-Cookie и атрибуты:
# Secure; HttpOnly; SameSite=Lax/Strict (или обоснованный None + Secure)

Практический чек-лист по сессиям и логину

  • Проверьте, что сессия регенерируется после логина и смены привилегий (защита от фиксации сессии).
  • Убедитесь, что logout действительно отзывает сессию/refresh (не только удаляет cookie на клиенте).
  • Настройте rate limiting на логин/восстановление/OTP и мониторинг аномалий (всплески 401/403).
  • Для критичных действий используйте step-up (повтор пароля/MFA) и отдельные политики времени жизни.

Инъекции в разных системах: SQL, NoSQL, командная и шаблонная инъекции

Инъекция - это выполнение нежелательной команды/запроса из-за смешивания данных и управляющих конструкций. Она встречается не только в SQL: то же происходит в NoSQL-фильтрах, в shell-командах, в шаблонизаторах и даже в поисковых DSL, если приложение склеивает строки и доверяет вводу.

  1. SQL-инъекция через конкатенацию: динамические WHERE/ORDER BY из параметров запроса (особенно сортировка/фильтры).
  2. NoSQL-инъекция: пользовательский ввод попадает в JSON-условия (например, операторы сравнения/логики).
  3. Командная инъекция: формирование команд для конвертации/архивации/вызова утилит из строк.
  4. Шаблонная инъекция (SSTI): пользовательский шаблон/часть шаблона исполняется сервером.
  5. Инъекция в интеграциях: параметры уходят в внешние API/шины/очереди и потом интерпретируются как команды.

Короткие примеры фикса

  • SQL: только параметризованные запросы; для ORDER BY - allowlist колонок, а не плейсхолдер.
  • OS команды: избегайте shell; вызывайте бинарь с массивом аргументов; allowlist опций и путей.
  • Шаблоны: запрет рендеринга пользовательских шаблонов; режимы sandbox; экранирование по контексту.

Практический чек-лист по инъекциям

  • Найдите места, где строки "склеиваются" для запросов/команд/DSL, и замените на параметризацию/allowlist.
  • Ограничьте права сервисного аккаунта БД и применяйте отдельные роли для read/write/админ-операций.
  • Добавьте негативные тесты на инъекции в интеграционные тесты (на уровне репозиториев/DAO).
  • Логируйте безопасно: не пишите сырые payload целиком там, где они могут стать вторичным вектором.

Межсайтовый скриптинг (XSS) и защита клиентской поверхности

XSS возникает, когда данные пользователя попадают в HTML/JS/DOM без корректного экранирования по контексту. Даже при "правильном backend" XSS часто появляется на фронтенде: при ручном использовании innerHTML, небезопасных шаблонных вставках, рендеринге HTML из Markdown и виджетах.

Что помогает в реальных проектах

  • Контекстное экранирование: HTML-атрибуты, текст, URL, JS-строки - это разные контексты.
  • Санитизация HTML только для разрешённого подмножества тегов/атрибутов (allowlist), если HTML нужен по требованиям.
  • CSP: политика контента, которая режет инлайновые скрипты и неподписанные источники.
  • HttpOnly cookies: уменьшают эффект кражи сессии через JS (но не решают XSS как класс).

Ограничения и типовые ловушки

  • "Экранирование один раз на входе" не работает: один и тот же текст может оказаться в разных контекстах вывода.
  • CSP не спасает, если разрешены опасные источники или используется unsafe-inline/unsafe-eval.
  • Санитизация без строгого allowlist часто обходится через экзотические теги/атрибуты и особенности парсинга.
  • DOM XSS появляется без участия сервера: достаточно небезопасной обработки location, hash, querystring.

Практический чек-лист по XSS

  • Запретите или жёстко ограничьте любые вставки HTML (innerHTML/outerHTML) и замените на безопасный рендеринг.
  • Проверьте места, где вы строите URL/атрибуты из пользовательских данных (href/src/style).
  • Настройте CSP и проверьте, что приложение реально работает без unsafe-inline в production.
  • Добавьте регрессионные тесты на XSS в критических формах (комментарии, профили, описания, админ-панели).

Контроль доступа: модели, ошибки в авторизации и способы защиты

Контроль доступа определяет, что пользователь может делать с конкретным ресурсом. Ошибка здесь обычно выглядит "незаметно": эндпоинт работает, тесты проходят, но проверка выполняется не там, не для того объекта или опирается на данные, которые можно подменить.

  • Проверка только на UI: кнопка скрыта, но API принимает запрос (классический IDOR).
  • Проверка роли без проверки владения: "user" может читать/менять чужой объект, если знает ID.
  • Путаница tenant/организации: объект проверяется на существование, но не на принадлежность текущему tenant.
  • Сложные исключения: "админ видит всё" внедрён патчами по коду, появляются обходы и несогласованности.
  • Миф: 404 вместо 403 решает проблему: это маскировка; настоящая защита - корректная авторизация.

Практический чек-лист по авторизации

  • Вынесите авторизацию в единый слой (policy/guard) и применяйте её для каждого запроса и каждого объекта.
  • Соберите матрицу прав (роль × действие × ресурс) и покройте её интеграционными тестами.
  • Проверьте все endpoint'ы на "горизонтальное" и "вертикальное" повышение привилегий.
  • Для multi-tenant явно проверяйте tenant_id на каждом запросе к данным.

Инфраструктура и процессы: безопасный CI/CD, деплой и мониторинг

Защита веб приложений ломается, когда секреты утекают из пайплайна, артефакт подменяется, а уязвимые зависимости попадают в прод без контроля. Процессная безопасность - это минимальные права, воспроизводимые сборки и сигнализация о подозрительных событиях в рантайме.

Мини-кейс: как закрыть "секреты в репозитории" и подмену артефакта

Безопасность веб-приложений: самые частые уязвимости и как от них защититься - иллюстрация
# Идея: сборка только в CI, секреты - только из менеджера секретов,
# деплой - только подписанных артефактов.

steps:
  - checkout (без секретов в git)
  - run: dependency scan (fail on policy)
  - run: tests + security smoke tests
  - build: produce artifact
  - sign: artifact (key in CI secure storage)
  - deploy: verify signature + fetch runtime secrets from vault

Быстрые практические советы, которые дают максимальный эффект

  1. Включите скан зависимостей в CI и блокируйте сборку по политике (severity/allowlist).
  2. Разграничьте окружения: отдельные ключи, отдельные базы, запрет debug/админ-эндпоинтов в production.
  3. Логируйте события безопасности: логин/выход, смена пароля, ошибки авторизации, операции с правами.
  4. Добавьте WAF/Rate limiting на периметре для замедления перебора и базовых атак на публичные формы.
  5. Запланируйте регулярный пентест веб приложения после крупных изменений (а не раз в "когда-нибудь").

Практический чек-лист по CI/CD и мониторингу

  • Уберите секреты из кода/конфигов, включите проверки на утечки (pre-commit/CI), используйте менеджер секретов.
  • Закрепите принцип минимальных привилегий для CI-агентов, сервис-аккаунтов и доступов к продакшену.
  • Настройте алерты на всплески 401/403/500, а также на массовые операции с объектами (скачивание/экспорт).
  • Сделайте базовый "security smoke" перед релизом: authz, инъекции, XSS на ключевых формах.

Самопроверка перед релизом: минимум, который стоит сделать всегда

  • Прогнали аудит безопасности веб приложения по критическим потокам и закрыли найденные high-risk баги.
  • Провели тестирование безопасности веб приложений на API: авторизация на объектном уровне, инъекции, XSS.
  • Проверили cookie/токены: Secure/HttpOnly/SameSite, ротация refresh, отзыв сессий при смене пароля.
  • Скан зависимостей и конфигураций в CI зелёный; секретов в репозитории нет; debug в prod выключен.
  • Есть план и окно на пентест веб приложения после существенных изменений в архитектуре/бизнес-логике.

Разбор типичных вопросов разработчиков по защите приложений

С чего начать, если нужно быстро улучшить безопасность веб приложений?

Начните с контроля доступа на уровне объектов, инъекций и управления сессиями: это чаще всего приводит к реальному компромиссу данных. Параллельно включите скан зависимостей и базовые алерты по 401/403/500.

Чем отличается защита веб приложений от "поставили WAF и успокоились"?

WAF снижает шум и часть массовых атак, но не исправляет ошибки логики и авторизации. Основная защита - в корректных проверках на сервере, безопасной работе с данными и в процессах релиза.

Когда нужен аудит безопасности веб приложения, а когда достаточно автоматических сканеров?

Сканеры хорошо ловят типовые классы проблем и регрессии, но плохо понимают бизнес-логику и матрицу прав. Аудит нужен при сложной авторизации, финансовых операциях, multi-tenant и после существенных изменений.

Как организовать тестирование безопасности веб приложений в команде без выделенного AppSec?

Вынесите security-чек-листы в Definition of Done, добавьте пару негативных интеграционных тестов на authz и инъекции, включите скан зависимостей в CI. Назначьте владельцев за критические потоки и ведите угрозы в бэклоге.

Что чаще ломают в сессиях: JWT или cookie?

Ломают не формат, а хранение и жизненный цикл: слишком долгие токены, отсутствие отзыва, неправильные атрибуты cookie, утечки в логах. Выбирайте схему, где вы можете управлять ротацией и отзывом.

Как правильно планировать пентест веб приложения, чтобы он был полезным?

Безопасность веб-приложений: самые частые уязвимости и как от них защититься - иллюстрация

Дайте тестерам карту ролей, список критических эндпоинтов и тестовые данные, а также доступ к staging, максимально похожему на prod. Зафиксируйте критерии успеха: сценарии компромисса, а не просто список находок.

Прокрутить вверх