Безопасность веб приложений сводится к управлению рисками: закрыть типовые уязвимости (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, если приложение склеивает строки и доверяет вводу.
- SQL-инъекция через конкатенацию: динамические WHERE/ORDER BY из параметров запроса (особенно сортировка/фильтры).
- NoSQL-инъекция: пользовательский ввод попадает в JSON-условия (например, операторы сравнения/логики).
- Командная инъекция: формирование команд для конвертации/архивации/вызова утилит из строк.
- Шаблонная инъекция (SSTI): пользовательский шаблон/часть шаблона исполняется сервером.
- Инъекция в интеграциях: параметры уходят в внешние 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
Быстрые практические советы, которые дают максимальный эффект
- Включите скан зависимостей в CI и блокируйте сборку по политике (severity/allowlist).
- Разграничьте окружения: отдельные ключи, отдельные базы, запрет debug/админ-эндпоинтов в production.
- Логируйте события безопасности: логин/выход, смена пароля, ошибки авторизации, операции с правами.
- Добавьте WAF/Rate limiting на периметре для замедления перебора и базовых атак на публичные формы.
- Запланируйте регулярный пентест веб приложения после крупных изменений (а не раз в "когда-нибудь").
Практический чек-лист по 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. Зафиксируйте критерии успеха: сценарии компромисса, а не просто список находок.



