OWASP Top 10: редакция 2025
OWASP Top 10 — не исчерпывающий чек-лист, а рейтинг наиболее значимых классов рисков, обновляемый по реальным данным. Действующая редакция — 2025 года, она заменила версию 2021 года. Знать актуальный список полезно хотя бы потому, что многие кандидаты по инерции пересказывают устаревшую версию.
Список 2025 года: A01 Broken Access Control — нарушение контроля доступа; A02 Security Misconfiguration — небезопасная конфигурация; A03 Software Supply Chain Failures — сбои в цепочке поставок ПО; A04 Cryptographic Failures — ошибки криптографии; A05 Injection; A06 Insecure Design — небезопасный дизайн; A07 Authentication Failures — сбои аутентификации; A08 Software or Data Integrity Failures — нарушение целостности ПО или данных; A09 Security Logging and Alerting Failures — недостатки логирования и оповещения; A10 Mishandling of Exceptional Conditions — неправильная обработка исключительных ситуаций.
Что изменилось по сравнению с 2021 годом и стоит отметить в разговоре. Небезопасная конфигурация поднялась на второе место. Тема уязвимых зависимостей выросла в полноценную категорию про цепочку поставок и заняла третье место. Появилась новая категория про обработку исключительных ситуаций. Инъекции опустились ниже — параметризованные запросы и ORM сделали своё дело, но категория никуда не делась. SSRF как отдельный пункт растворился внутри контроля доступа.
Две категории заслуживают отдельного внимания, потому что показывают смену акцента. Insecure Design говорит о том, что часть проблем невозможно исправить кодом — они заложены в замысел, и лечатся моделированием угроз на этапе проектирования. А категория про логирование и оповещение напоминает, что незамеченная атака ничем не лучше успешной: без логов аутентификации и алертов на аномалии взлом обнаруживают месяцами.
Контроль доступа — риск номер один
Broken Access Control занимает первое место не случайно: это ошибка бизнес-логики, и её не ловят ни сканеры, ни компилятор.
Самый распространённый вид — небезопасная прямая ссылка на объект: эндпоинт GET /orders/{id} проверяет, что пользователь аутентифицирован, но не проверяет, что заказ принадлежит именно ему. Перебор идентификаторов выдаёт чужие данные. Отсюда правило: проверка владения ресурсом обязана быть на сервере в каждом запросе, а не в UI, и не заменяется тем, что «клиент не покажет чужую ссылку».
Второй частый вид — проверка прав только на фронтенде: кнопка спрятана, но эндпоинт открыт. Любой инструмент вроде curl обходит такую защиту мгновенно.
Правильная модель — запрет по умолчанию: доступ разрешается явно, а не запрещается перечислением. Новый эндпоинт при этом закрыт, пока для него не описано правило, — противоположный подход неизбежно оставляет дыры при добавлении функциональности. Сюда же относится проверка на уровне данных: запрос в базу должен фильтровать по владельцу, а не выбирать всё и отсеивать в приложении.
Отдельно стоит помнить про SSRF, который теперь входит в эту категорию: если приложение ходит по URL, полученному от пользователя, оно может быть использовано для обращения к внутренним адресам. Защита — список разрешённых адресов, а не список запрещённых.
Аутентификация, авторизация и JWT
Разграничение, с которого начинается любой разговор: аутентификация отвечает на вопрос «кто ты» (проверка личности), авторизация — «что тебе можно» (проверка прав). Коды ответов различают их же: 401 — не аутентифицирован, 403 — аутентифицирован, но прав не хватает.
Пароли хранят только в виде хеша, посчитанного функцией, специально предназначенной для паролей: bcrypt, scrypt или argon2. Их отличие от SHA-256 принципиальное: они намеренно медленные и настраиваемые по стоимости, что делает перебор дорогим. Соль генерируется на каждый пароль и хранится рядом. Использование быстрых хешей общего назначения для паролей — классическая ошибка категории Cryptographic Failures.
Про JWT ждут понимания компромисса. Самодостаточный токен не требует похода в хранилище сессий и потому хорошо масштабируется, но именно поэтому его нельзя отозвать: пока не истёк срок, токен действителен, даже если пользователь заблокирован. Стандартное решение — короткоживущий access-токен (минуты) плюс refresh-токен, хранимый на сервере и отзываемый. Ответ «сделаем список отозванных токенов» тоже приемлем, но стоит признать, что он возвращает состояние на сервер и тем самым отменяет главное преимущество.
Технические ловушки JWT, которые проверяют отдельно: алгоритм подписи обязан быть зафиксирован на сервере, иначе возможна подмена на none или на симметричный алгоритм с публичным ключом в роли секрета; полезная нагрузка лишь закодирована base64, а не зашифрована, поэтому класть туда персональные данные нельзя; хранение токена в localStorage делает его доступным при XSS, поэтому предпочтительнее httpOnly-cookie с флагами Secure и SameSite.
Для сессий на cookie обратная сторона — CSRF, поскольку браузер прикладывает cookie автоматически. Защита — SameSite и CSRF-токен. Токены в заголовке Authorization этой проблемой не страдают, но зато уязвимы к XSS. Понимание этой симметрии компромиссов и есть содержательный ответ на «что лучше, сессии или JWT».
Секреты и цепочка поставок
Секреты не хранят в репозитории — ни в коде, ни в конфигурации, ни в истории коммитов. Важная деталь: удалить секрет новым коммитом недостаточно, он остаётся в истории git, поэтому попавший в репозиторий секрет считается скомпрометированным и подлежит ротации, а не удалению.
Правильное место — менеджер секретов с контролем доступа, аудитом и ротацией. Секреты доставляются в приложение переменными окружения или примонтированным томом. Сюда же относится ротация: секрет, который никогда не менялся, при утечке действует бессрочно.
Цепочка поставок в редакции 2025 года поднялась на третье место, и это отражает реальность: значительная часть кода в проде написана не вами. Практический минимум — фиксация версий зависимостей (lock-файл), автоматическая проверка на известные уязвимости в сборке, генерация перечня компонентов (SBOM) и осторожность с транзитивными зависимостями. История с Log4Shell — самая наглядная иллюстрация того, как уязвимость в одной библиотеке становится проблемой всей отрасли.
Смежная категория — целостность ПО и данных: подписывание артефактов и проверка подписи при развёртывании, доверенные реестры образов, защита конвейера сборки. Скомпрометированный CI опаснее скомпрометированного сервера, потому что раздаёт вредоносный артефакт всем.
Что ещё спрашивают
Инъекции: единственная надёжная защита от SQL-инъекций — параметризованные запросы, где данные никогда не попадают в текст запроса. Экранирование вручную — ненадёжная замена. То же относится к динамическому JPQL и к конкатенации в нативных запросах.
Транспорт: TLS обязателен снаружи; внутри периметра между сервисами всё чаще применяют взаимную аутентификацию mTLS, потому что модель «внутри сети всё свои» не выдерживает современных требований — это и есть идея zero trust.
Лимиты как средство защиты: ограничение частоты запросов на аутентификацию мешает перебору паролей, ограничение размера тела запроса и глубины вложенности защищает от исчерпания ресурсов, а таймауты — от медленных клиентов.
Ошибки и утечки информации: наружу отдают код ошибки и correlation id, но не стектрейс, не текст SQL и не внутренние адреса. И симметрично — сообщение при неудачном входе не должно различать «нет такого пользователя» и «неверный пароль», иначе оно превращается в инструмент перечисления учётных записей.
Как отвечать на собеседовании
Назовите актуальную редакцию OWASP Top 10 и хотя бы отметьте, что действующая версия — 2025 года, а не 2021. Перечислять все десять пунктов наизусть не требуется; ценнее объяснить два-три класса риска на живых примерах.
На вопрос про контроль доступа приводите пример с перебором идентификаторов в GET /orders/{id} и формулируйте правило запрета по умолчанию. Это конкретнее любых общих слов о безопасности.
Про JWT отвечайте через компромисс: самодостаточность даёт масштабируемость и отнимает возможность отзыва; лечится коротким сроком жизни и refresh-токеном. Добавьте технические ловушки — фиксация алгоритма, отсутствие шифрования полезной нагрузки, XSS против CSRF при выборе места хранения.
И покажите, что видите картину шире кода: моделирование угроз на этапе дизайна, логирование и алерты на аномалии аутентификации, ротация секретов и контроль зависимостей. Именно это отличает ответ уровня lead от перечисления уязвимостей.