SAST, DAST и SCA: автоматический поиск уязвимостей

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

SAST/DAST/SCA — три взаимодополняющих класса инструментов: статический анализ кода, динамический анализ работающего приложения и анализ состава зависимостей. Вместе они автоматизируют поиск уязвимостей в конвейере разработки.

Ручной аудит безопасности дорог и проводится редко. Между аудитами в код попадают сотни изменений, и каждое может внести уязвимость. Идея DevSecOps — заставить машину проверять безопасность на каждом коммите, как уже проверяются тесты и линтер. Этот урок — про три семейства таких сканеров, их сильные и слабые стороны. Запускать их можно только против своего кода и своих стендов: сканирование чужого приложения без разрешения владельца попадает под статью 272 УК РФ.

Зачем это знать разработчику

Стоимость исправления уязвимости растёт по мере её продвижения к продакшену. Баг, пойманный сканером на коммите, чинится за минуты; та же уязвимость, найденная в проде после инцидента, обходится в простой, расследование и репутационный ущерб. Понимая, что именно умеет каждый класс инструментов, разработчик не полагается вслепую на «зелёный отчёт» и сознательно закрывает слепые зоны. Это и есть mindset защитника: не один волшебный сканер, а продуманная комбинация.

SAST — статический анализ кода

SAST (Static Application Security Testing) читает исходный код или байт-код, не запуская его. Инструмент строит из программы граф потока данных и ищет шаблоны опасного кода: пользовательский ввод, который доходит до SQL-запроса без параметризации; конкатенация в команду оболочки; захардкоженный пароль; небезопасный криптоалгоритм. Концептуально SAST отслеживает путь от источника (source — недоверенный ввод) до стока (sink — опасная операция):

source (request.args) ──> обработка ──> sink (cursor.execute)
                  если по пути нет санитизации/параметризации —> находка SQLi

Сильная сторона SAST — он видит весь код, включая редкие ветки, и указывает точную строку. Запускается рано, прямо в IDE или на pull request. Слабая сторона — ложные срабатывания (false positives): инструмент не знает контекста выполнения и иногда подсвечивает безопасный код. Поэтому находки SAST нужно триажить — разбирать, реальна ли уязвимость. Примеры инструментов: Semgrep, Bandit (Python), CodeQL.

# SAST против своего репозитория: ищем антипаттерны в коде
semgrep --config=auto ./src
bandit -r ./src        # специализирован под Python

DAST — динамический анализ работающего приложения

DAST (Dynamic Application Security Testing) подходит с другой стороны: он не видит код, а взаимодействует с развёрнутым приложением снаружи, как пользователь или браузер. Сканер обходит страницы и эндпоинты, подставляет в параметры пробные значения и анализирует ответы: появилась ли SQL-ошибка, отразился ли ввод в HTML без экранирования, как ведёт себя аутентификация. По сути DAST автоматизирует часть проверок, которые делает пентестер.

Сильная сторона — DAST находит проблемы, видимые только в рантайме: ошибки конфигурации сервера, отсутствие security-заголовков, проблемы сессий — то, чего нет в исходниках. Он не зависит от языка. Слабая сторона — видит только то, до чего дотянулся: непокрытый эндпоинт остаётся непроверенным, и точную строку кода DAST не укажет. Запускают его на тестовом стенде (не на проде с живыми данными):

# DAST против СВОЕГО тестового стенда (например, локальный OWASP Juice Shop)
zap.sh -cmd -quickurl http://localhost:3000 -quickout report.html

OWASP ZAP — классический бесплатный DAST. Запускать его разрешено только против стендов, которыми вы владеете или на которые есть письменное согласие.

SAST и DAST дополняют друг друга

Их часто противопоставляют, но правильнее использовать оба. SAST — «белый ящик» (white-box): видит внутренности, ловит баг рано и точечно, но не знает рантайма. DAST — «чёрный ящик» (black-box): видит поведение, ловит конфигурацию и интеграции, но не указывает строку. Уязвимость, которую пропустит один, нередко поймает другой.

SCA — анализ зависимостей

SCA (Software Composition Analysis) проверяет не ваш код, а чужой — сторонние библиотеки, которые вы подключили. Современное приложение на 80–90% состоит из зависимостей, и уязвимость в любой из них становится вашей уязвимостью. SCA сверяет список пакетов (и их версии) с базами известных уязвимостей (CVE) и сообщает: «в этой версии библиотеки есть известная дыра, обновитесь до такой-то».

# SCA: проверка зависимостей на известные CVE
npm audit                 # для Node.js
pip-audit                 # для Python
# в CI часто используют отдельные сканеры (Trivy, OWASP Dependency-Check, Snyk)

SCA критичен, потому что эта категория (уязвимые и устаревшие компоненты) — отдельный пункт в OWASP Top 10. Подробно безопасность зависимостей разбирается в следующем уроке; здесь важно запомнить место SCA в общей картине: он закрывает тот пласт риска, который SAST и DAST не видят, ведь код библиотеки вы не пишете и не сканируете построчно.

Как это работает под капотом

Все три класса сводятся к сопоставлению с шаблоном, но на разных представлениях программы. SAST матчит шаблоны на синтаксическом дереве и графе потока данных исходника. DAST матчит отклики работающего приложения на заранее заготовленные пробы. SCA матчит имена и версии пакетов против базы CVE. Отсюда и их ограничения: SAST не знает рантайм-окружения, DAST не знает код, SCA не оценивает, используется ли уязвимый участок библиотеки на самом деле. Ни один не даёт стопроцентной гарантии — поэтому защита строится слоями.

Где их место в пайплайне

Каждый инструмент включается там, где он эффективнее всего:

ИнструментЧто анализируетКогда в пайплайне
SASTисходный код (white-box)IDE / pre-commit / на pull request
SCAзависимости (CVE)на каждый build, при изменении lock-файла
DASTработающее приложение (black-box)на staging-стенде после деплоя

SAST и SCA — быстрые и «сдвинуты влево» (shift-left), ближе к моменту написания кода. DAST требует развёрнутого приложения, поэтому идёт позже, на тестовом окружении. Как превратить эти проверки в обязательный гейт сборки — тема последнего урока раздела.

Как защититься

1. Используйте все три класса, а не один. Они закрывают разные слепые зоны: код, рантайм, зависимости.

2. Сдвигайте проверки влево. Чем раньше (IDE, pre-commit, PR) — тем дешевле починка.

3. Триажьте находки. Особенно у SAST много ложных срабатываний; настраивайте правила под проект и помечайте проверенные исключения, чтобы команда не привыкла игнорировать отчёты.

4. Не считайте «зелёный отчёт» доказательством безопасности. Сканеры находят известные шаблоны; логические уязвимости и бизнес-логику по-прежнему проверяет человек (код-ревью, пентест).

Итоги

  • SAST читает исходный код не запуская его (white-box): ловит баг рано и точечно, но даёт ложные срабатывания.
  • DAST атакует работающее приложение снаружи (black-box): ловит рантайм и конфигурацию, но не указывает строку.
  • SCA сверяет зависимости с базами CVE: закрывает риск чужого кода, который вы не пишете.
  • Инструменты дополняют друг друга и встраиваются в пайплайн по принципу shift-left (раньше — дешевле).
  • Запускать сканеры можно только против своего кода/стендов; «зелёный отчёт» не заменяет ревью и пентест.
Проверьте себя
1. Чем принципиально различаются SAST и DAST?
ASAST анализирует исходный код, не запуская приложение (white-box); DAST взаимодействует с уже работающим приложением снаружи (black-box)
BSAST ищет уязвимости в зависимостях, а DAST — в исходном коде
CSAST работает только для Python, а DAST — только для JavaScript
DЭто два названия одного и того же инструмента
2. Какой класс инструментов отвечает за поиск известных уязвимостей (CVE) в сторонних библиотеках?
ASCA (Software Composition Analysis)
BSAST
CDAST
DЛинтер стиля кода