Анализ6 мин чтения2026-03-06

DAST анализ кода: как найти уязвимости, которые статика не видит

На одном проекте мы полгода гоняли SAST в пайплайне. Зелёные галочки, чистый код, всё красиво. Потом пен-тестеры за час нашли SQL-инъекцию в API. Статический ан

На одном проекте мы полгода гоняли SAST в пайплайне. Зелёные галочки, чистый код, всё красиво. Потом пен-тестеры за час нашли SQL-инъекцию в API. Статический анализатор просто не знал, что этот эндпоинт принимает пользовательский ввод в неочевидном формате.

Вот так я понял: одного статического анализа мало. Нужен DAST.

SAST, DAST, SCA — собери коллекцию

Разберёмся в алфававите безопасности.

SAST (Static Application Security Testing) — статический анализ. Смотрит исходный код, не запуская его. Находит небезопасные функции, хардкод секретов, уязвимые зависимости. Работает быстро, но даёт много ложных срабатываний.

DAST (Dynamic Application Security Testing) — динамический анализ. Атакует работающее приложение извне. Эмулирует хакера: сканирует эндпоинты, пробует инъекции, ищет открытые директории. Не видит код, но находит реальные уязвимости в рантайме.

SCA (Software Composition Analysis) — анализ зависимостей. Проверяет библиотеки на известные CVE. Npm audit, safety, Dependabot — это всё SCA.

По-хорошему, нужно всё три. Они не дублируют, а дополняют друг друга. SAST найдёт eval() в коде, SCA скажет, что lodash 4.17.15 уязвим, а DAST обнаружит, что админка доступна без авторизации.

Почему SAST недостаточен

Статика крутая. Я сам использую её в каждом проекте. Но у неё есть фундаментальные ограничения.

SAST не понимает контекст. Он видит функцию getUser(id) и не знает, откуда приходит id — из доверенного конфига или из HTTP-параметра. Поэтому либо пропускает уязвимости, либо орет на каждый SELECT * FROM.

DAST работает с тем, что реально исполняется. Ему плевать на исходники. Он стучится в работающее приложение и смотрит: а что если в поле username отправить ' OR '1'='1? Если сервер ответил ошибкой или отдал все записи — уязвимость реальна.

Есть ещё одна проблема. Сборка. В проде работает не тот код, что в репозитории. Есть Docker-слои, переменные окружения, конфиги nginx. SAST этого не видит. DAST — видит, потому что атакует именно то, что развёрнуто.

Но и DAST не панацея. Он не найдёт хардкоженный API-ключ в коде. Не скажет, что ты используем устаревшую версию React. И стоит дорого по времени — полноценное сканирование может идти часами.

DAST в деталях: как это работает

DAST-сканер — это робот-пентестер. Он работает по такому алгоритму:

Сначала краулер обходит приложение. Находит все страницы, формы, API-эндпоинты. Потом фаззер отправляет вредоносные payloads в каждое поле. SQL-инъекции, XSS, path traversal, command injection — сотни вариантов.

Анализатор смотрит на ответы. Ошибки базы данных? Аномальное время ответа? Редирект на сторонний ресурс? Это признаки уязвимости.

# Пример простого DAST-запроса
curl -X POST "https://api.example.com/users" \
  -H "Content-Type: application/json" \
  -d '{"email": "test@example.com; DROP TABLE users;--"}'

Хороший DAST умеет аутентифицироваться. Залогинился, получил сессию, пошёл сканировать защищённые области. Без этого проверяется только публичная часть — половина атаковой поверхности остаётся за бортом.

Инструменты: что выбрать

OWASP ZAP — классика. Open source, бесплатный, интегрируется во всё. UI убогий, но для CI/CD норм. Есть Docker-образ, API, куча плагинов.

Burp Suite Professional — индустриальный стандарт. Стоит денег, но пен-тестеры его обожают. Автоматическое сканирование крутое, ручной тестинг — ещё лучше.

Nucleus, Invicti, Acunetix — коммерческие решения. Дороже, но с красивыми отчётами для менеджмента и меньше ложных срабатываний.

GitLab DAST — встроен в GitLab CI. Если вы на GitLab, это самый простой путь. Конфигурируется одной строкой.

# .gitlab-ci.yml
stages:
  - test

dast:
  stage: test
  image: registry.gitlab.com/gitlab-org/security-products/dast:latest
  variables:
    DAST_WEBSITE: https://staging.example.com
    DAST_AUTH_URL: https://staging.example.com/login
    DAST_USERNAME: "testuser"
    DAST_PASSWORD: "testpass"
  script:
    - /analyze
  artifacts:
    reports:
      dast: gl-dast-report.json

Честно? Для начала хватит OWASP ZAP. Бесплатно, функционал достаточный. Когда упрётесь в ограничения — думайте о платных решениях.

Внедрение в CI/CD

Вот тут начинаются сложности. DAST требует работающего приложения. Статику можно гнать на коммите. DAST нужно развёрнутое окружение.

Обычно сканируют staging или review-окружения. Подняли ветку в изолированном контейнере — прогнали DAST — отдали отчёт.

# Пример для GitHub Actions с OWASP ZAP
name: DAST Scan

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  dast:
    runs-on: ubuntu-latest
    steps:
      - name: Deploy to staging
        run: |
          docker-compose -f docker-compose.staging.yml up -d
          sleep 30  # Ждём поднятия сервиса
      
      - name: ZAP Scan
        uses: zaproxy/action-full-scan@v0.7.0
        with:
          target: 'http://localhost:8080'
          cmd_options: '-a'
      
      - name: Tear down staging
        if: always()
        run: docker-compose -f docker-compose.staging.yml down

Важно не блокировать деплой на каждый finding. DAST даёт ложные срабатывания. На одном проекте мы сначала падали на любой alert, потом устали разруливать false positives, и сделали так: критические уязвимости блокируют, остальные просто логируются в MR.

# Скрипт для парсинга отчёта ZAP
import json

def parse_zap_report(report_path):
    with open(report_path) as f:
        report = json.load(f)
    
    critical = []
    for site in report.get('site', []):
        for alert in site.get('alerts', []):
            if alert['riskcode'] == '3':  # High risk
                critical.append({
                    'name': alert['name'],
                    'url': alert['instances'][0]['uri'],
                    'solution': alert['solution']
                })
    
    return critical

# Блокируем пайплайн только при критических уязвимостях
critical_vulns = parse_zap_report('zap-report.json')
if critical_vulns:
    print(f"Found {len(critical_vulns)} critical vulnerabilities!")
    exit(1)

Как мы это делали в стартапе

Небольшая история. Финтех-стартап, микросервисы на Python, деплой в Kubernetes. Внедряли безопасность поэтапно.

Первым делом добавили SCA. pip-audit для Python, npm audit для фронтенда. Это дало низко висящие плоды — нашли 23 уязвимости в зависимостях, за час закрыли критические.

Потом SAST. Semgrep — лёгкий, быстрый, понятные правила. Настроили за вечер. Первые две недели разбирали ложные срабатывания, потом привыкли.

DAST стал третьим этапом. OWASP ZAP в GitLab CI, сканирование staging перед каждым релизом. Нашёл открытый actuator-эндпоинт в Spring Boot и утечку метаданных в API. Исправили.

Полный цикл: коммит → SAST + SCA → билд → деплой на staging → DAST → прод. Да, дольше. Да, иногда бесит. Но спать спокойнее.

Сравнение подходов: табличка

Если коротко:

Подход Что находит Скорость False positives Требует запуска
SAST Уязвимости в коде Минуты Много Нет
SCA CVE в зависимостях Секунды Мало Нет
DAST Уязвимости в рантайме Часы Средне Да

Идеальная комбинация: SCA на каждый коммит, SAST на MR, DAST на релиз-кандидат. Так вы ловите проблемы максимально рано, но не тормозите разработку.

Что по автоматизации

Ручной запуск DAST — это костыль. Забудете. Нужно в CI/CD.

Но есть нюанс. Полное сканирование идёт 2-4 часа. На каждый MR — непозволительная роскошь. Решение: инкрементальное сканирование или baseline-подход.

При baseline вы впервые сканируете приложение полностью, сохраняете результаты. Потом при каждом запуске сравниваете: появились ли новые уязвимости? Если нет — зелёный свет. Если да — разбираться.

# ZAP baseline scan — быстро, но поверхностно
docker run -t owasp/zap2docker-stable zap-baseline.py \
  -t https://staging.example.com \
  -c baseline.conf \
  -r baseline-report.html

# Full scan — долго, но глубоко
docker run -t owasp/zap2docker-stable zap-full-scan.py \
  -t https://staging.example.com \
  -c full-scan.conf \
  -r full-report.html

Ещё вариант — анализ кода max, когда вы комбинируете все три подхода в едином пайплайне. Перебор? Возможно. Но для fintech, medtech и других регулируемых областей — необходимость.


DAST — не замена статическому анализу, а дополнение. Если вы сейчас используете только SAST — это уже хорошо. Но если обрабатываете персональные данные или деньги, добавьте DAST. Хотя бы на staging.

Кстати, если нет времени настраивать зоопарк сканеров, посмотрите на Distiq. Это AI-бот для code review, который находит уязвимости, баги и проблемы производительности прямо в MR. Интегрируется за пару минут, поддерживает основные языки. Не заменяет DAST, но закрывает большую часть вопросов по качеству кода до того, как он попадёт в рантайм.

Попробуйте Distiq для автоматического code review

AI-бот анализирует каждый MR/PR и оставляет комментарии с замечаниями. Интеграция за 2 минуты.

Попробовать бесплатно

Похожие статьи