SAST, DAST, IAST в разработке

Разбираемся, на каком этапе и каким способом автоматические анализаторы ловят уязвимости, как встроить их в IDE и CI, как читать находки и не утонуть в ложных срабатываниях.

SAST, DAST, IAST — три способа автоматически искать уязвимости: статический анализ исходного кода, динамический анализ работающего приложения и интерактивный анализ изнутри запущенного приложения. Они смотрят на программу с разных сторон и ловят разные классы дефектов.

Безопасность невозможно проверить одним прогоном раз в год. Между релизами в код попадают сотни изменений, и любое может внести уязвимость. Поэтому защиту автоматизируют: машина проверяет каждый коммит так же, как уже проверяет тесты и линтер. Этот урок — карта трёх подходов к такому анализу: что каждый ловит, что пропускает и куда его ставить в процессе. Важно: запускать сканеры безопасности можно только против своего кода и своих стендов — сканирование чужого приложения без письменного разрешения владельца подпадает под статью 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): инструмент не знает контекста выполнения и иногда подсвечивает безопасный код. Примеры: 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

IAST — интерактивный анализ изнутри

IAST (Interactive Application Security Testing) — гибрид. В приложение встраивается агент (инструментация рантайма), который наблюдает за выполнением изнутри, пока приложение работает под нагрузкой автотестов или DAST-сканера. Агент видит и реальный поток данных в памяти, и строку кода, где недоверенный ввод дошёл до опасной операции. Поэтому IAST совмещает преимущества: точность до строки (как SAST) и подтверждение в рантайме (как DAST), что резко снижает ложные срабатывания.

Плата за это — приложение нужно запустить с агентом и иметь набор тестов, которые «прогонят» код: IAST видит только исполненные пути. Поэтому IAST обычно ставят в QA-окружение и связывают с уже существующими функциональными или DAST-тестами.

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

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

Куда ставить в IDE и CI

Каждый анализ эффективнее на своём этапе:

ПодходЧто анализируетГде в процессеЛожные срабатывания
SASTисходный код (white-box)IDE / pre-commit / pull requestмного
DASTработающее приложение (black-box)staging после деплоямало
IASTрантайм изнутри (grey-box)QA, вместе с автотестамиочень мало

В IDE подключают быстрый SAST-плагин, чтобы подсветка появлялась прямо при наборе. В CI первым шагом ставят SAST на изменённые файлы pull request, чтобы сборка падала на критичных находках; DAST и IAST включают позже, на развёрнутом стенде. Пример шага CI:

sast:
  stage: test
  script:
    - semgrep --config=auto --error ./src   # ненулевой код выхода = сборка падает

Разбор находок и ложные срабатывания

Находку нельзя слепо принимать или слепо игнорировать — её нужно триажить. Алгоритм разбора: понять класс уязвимости и где source/sink; проверить, достижим ли путь реально и нет ли уже санитизации; оценить влияние. Если уязвимость реальна — завести задачу и починить; если это ложное срабатывание — пометить исключение в конфиге инструмента с комментарием почему, а не глобально отключать правило.

Главный риск — «усталость от алертов»: когда отчёт состоит на 90% из шума, команда перестаёт его читать и пропускает настоящую дыру. Поэтому правила настраивают под проект, базовый уровень фиксируют, а в гейт сборки выносят только высокоуверенные критичные находки.

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

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

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

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

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

Итоги

  • SAST читает исходный код не запуская (white-box): рано и точно, но много ложных срабатываний.
  • DAST атакует работающее приложение снаружи (black-box): ловит рантайм и конфигурацию, но не указывает строку.
  • IAST наблюдает изнутри через агента (grey-box): точно до строки и почти без шума, но видит только исполненные тестами пути.
  • Каждый подход встраивается на своём этапе: SAST — в IDE/PR, DAST — на staging, IAST — в QA с автотестами.
  • Находки нужно триажить, гасить шум и помнить: «зелёный отчёт» не заменяет ревью и пентест.
Проверьте себя
1. Чем IAST отличается от SAST и DAST?
AIAST через агент наблюдает за реальным потоком данных изнутри работающего приложения, совмещая точность до строки (как SAST) и подтверждение в рантайме (как DAST)
BIAST анализирует только зависимости и их CVE
CIAST полностью заменяет необходимость в код-ревью и пентесте
DIAST работает без запуска приложения, как обычный линтер
2. Почему SAST обычно даёт больше ложных срабатываний, чем DAST?
ASAST анализирует код статически и не знает контекста выполнения, поэтому иногда подсвечивает фактически безопасные пути
BSAST вообще не способен находить реальные уязвимости
CDAST проверяет каждую строку кода и потому никогда не ошибается
DЛожные срабатывания зависят только от языка программирования