АШШумилкин А. О.ОАиП · ПиТПМ
ПиТПМ · Лекция 11

Лекция №11. Безопасность модулей программного обеспечения. Анализ уязвимостей в зависимостях программного кода (SAST/DAST).

4 150 слов7 разделов4 иллюстраций
↓ Скачать Markdown

§11.1. Почему тестировщик должен думать о безопасности

За этот семестр мы научились тестировать многое:

ЛекцияЧто тестировали
Лекция 6Модули и интеграцию с БД
Лекция 7Интерфейсы и E2E-сценарии
Лекция 8Производительность и нагрузку
Лекция 9CI/CD и автоматизацию
Лекция 10Совместимость микросервисов

Осталось последнее: безопасность. Если система работает, но небезопасна — она не работает. Потому что:

  • Данные пользователей могут быть украдены.
  • Система может быть взломана.
  • Бизнес может потерять репутацию и деньги.

Многие думают, что безопасность — это задача разработчиков. Но это не так. Кто отвечает за безопасность в проекте:

КтоЧто делает
РазработчикПишет код и старается избегать уязвимостей
АрхитекторПроектирует систему с учетом безопасности
DevOpsНастраивает серверы и сеть
ТестировщикПроверяет, что система безопасна

Задача тестировщика

— убедиться, что уязвимости системы выявлены (а затем переданы разработчикам для исправления). Тестировщик анализирует систему с позиции внешнего наблюдателя, действуя подобно потенциальному злоумышленнику.

Тестировщик — последний рубеж перед продакшеном. Вот как выглядит путь кода от разработчика до пользователя:

wireframe

Разработчик пишет код → Code Review → CI/CD → Тестировщик → Продакшен

                                                  ↑

                                            ПОСЛЕДНИЙ РУБЕЖ!

Что это значит:

Если тестировщик нашел уязвимостьЕсли тестировщик пропустил уязвимость
Уязвимость исправлена до релизаУязвимость попадает в продакшен
Пользователи в безопасностиХакеры могут использовать уязвимость
Репутация компании сохраненаСкандалы, утечки данных, штрафы

OWASP (Open Web Application Security Project)

— это международная организация, которая занимается безопасностью веб-приложений. Каждые несколько лет они публикуют список Top 10 — 10 самых опасных уязвимостей.

Зачем это знать тестировщику? Чтобы знать, на что обращать внимание.

Краткий обзор OWASP Top 10 (упрощенно):

№УязвимостьЧто этоПример
1Инъекции (SQL, NoSQL, OS)Злоумышленник внедряет вредоносный код в запрос' OR '1'='1 в поле ввода — и он зашел без пароля
2Потеря аутентификацииПароли и токены украдены или слабыеПароль 123456 — легко взломать
3XSS (межсайтовый скриптинг)Злоумышленник внедряет JavaScript на страницуПользователь кликает на ссылку — его данные украдены
4Небезопасные зависимостиИспользуются устаревшие библиотеки с уязвимостямиLog4j, jQuery с известными CVE
5Неправильная настройка безопасностиСервер настроен небезопасноОткрытые порты, слабые пароли по умолчанию
6Уязвимости в APIAPI не проверяет права доступаМожно получить данные другого пользователя
7Недостаточное логированиеНет логов для расследования инцидентовНепонятно, кто и когда взломал систему

Запомните

Важно понимать, что не нужно запоминать все 10 уязвимостей. Мы не будем их все подробно разбирать в курсе. Достаточно понимать, что они существуют и что тестировщик должен знать о них хотя бы на базовом уровне.

Что нужно запомнить:

1. Опасность SQL-инъекций — злоумышленник может прочитать, изменить или удалить данные.

2. Опасность XSS — злоумышленник может украсть данные пользователей.

3. Опасность устаревших библиотек — в них уже известны уязвимости, и их легко использовать.

4. Опасность неправильных настроек — система может быть взломана из-за слабого пароля или открытого порта.

Существует два основных подхода к тестированию безопасности. Мы будем подробно разбирать их в следующих параграфах, но пока кратко:

ПодходЧто этоКогда проверяетЧто ищет
**Static (SAST) **Проверка кода без запускаНа этапе написания кодаSQL-инъекции, XSS, устаревшие библиотеки
Dynamic (DAST)Проверка работающего приложенияНа этапе тестирования (staging)Неправильную авторизацию, открытые порты, уязвимости API

Простая аналогия:

  • SAST — это как проверка чертежа здания. Вы смотрите на план и ищете ошибки до того, как начали строить.
  • DAST — это как проверка уже построенного здания. Вы ходите по коридорам, проверяете замки, смотрите, не открыты ли окна.

§11.2. SAST: Static Application Security Testing

Давайте разберем что такое SAST. SAST расшифровывается как Static Application Security Testing.

SAST

— статическое тестирование безопасности приложений.

Важно знать

Это значит, что SAST проверяет код без его запуска. Он анализирует исходный код, ищет потенциальные уязвимости и сообщает о них разработчику.

Пример:

csharp

// Вот такой код может содержать уязвимость
public IActionResult GetUser(string userId)
{
    // SAST найдет проблему: SQL-инъекция!
    var query = $"SELECT * FROM Users WHERE Id = '{userId}'";
    //                                                ↑
    //                    userid приходит от пользователя
    //                    злоумышленник может передать: ' OR '1'='1
    var user = db.Execute(query);
    return Ok(user);
}

SAST ищет не все уязвимости, а только те, которые можно найти в коде. Вот основные категории:

Что ищет SASTПримерПочему это опасно
SQL-инъекции"SELECT * FROM Users WHERE Id = '" + userId + "'"Злоумышленник может украсть или удалить данные
XSS (межсайтовый скриптинг)Response.Write(userInput)Злоумышленник может внедрить JavaScript на страницу
Устаревшие библиотекиИспользование log4j старой версии с известной уязвимостьюЕсть известные CVE, которые легко использовать
Ошибки конфигурацииСтрока подключения с паролем в кодеПароль виден всем, у кого есть доступ к коду
Небезопасные методыИспользование MD5 для хеширования паролейMD5 можно взломать, нужно использовать bcrypt
Отсутствие валидацииНе проверяется ввод пользователяЗлоумышленник может отправить любые данные

SAST запускается на ранних этапах разработки, как можно раньше.

Где запускаетсяКогдаЗачем
В IDE (Visual Studio)Пока разработчик пишет кодМгновенная обратная связь
В CI/CDПри каждом git pushАвтоматическая проверка
В Code ReviewПеред вливанием в mainПроверка перед мержем

В IDE это выглядит следующим образом. Разработчик пишет код:

csharp

// Разработчик пишет такой код
string query = $"SELECT * FROM Users WHERE Id = '{userId}'";

SAST (в IDE) подсвечивает строку красным и пишет:

wireframe

⚠️ Уязвимость: Возможна SQL-инъекция. 

Используйте параметризованные запросы вместо конкатенации строк.

Разработчик исправляет:

csharp

// Исправленный код
var query = "SELECT * FROM Users WHERE Id = @UserId";
// Используем параметры, а не конкатенацию

В §9.7 лекции №9 мы говорили о линтерах (StyleCop, ESLint). На первый взгляд SAST и линтер делают похожее — проверяют код без запуска. Но разница есть.

ХарактеристикаЛинтерSAST
Что ищетСтиль и качество кода (отступы, названия)Уязвимости безопасности (SQL-инъекции, XSS)
Тип ошибокКосметические и стилистическиеКритические (могут привести к взлому)
ПоследствияКод некрасивый, но работаетКод может быть взломан
Когда использоватьВсегдаВсегда

Простая аналогия:

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

И то, и другое важно, но SAST важнее, потому что он находит реальные угрозы.

Для .NET-проектов есть несколько популярных инструментов SAST:

1. Security Code Scan

Это бесплатный анализатор для .NET. Он встроен в Visual Studio и проверяет код на уязвимости прямо во время написания.

bash

# Установка через NuGet
dotnet add package SecurityCodeScan

Что проверяет:

  • SQL-инъекции.
  • XSS-уязвимости.
  • Использование небезопасных методов.
  • Слабые алгоритмы хеширования.

2. SonarQube

SonarQube

— это мощная платформа для анализа кода. Она проверяет не только уязвимости, но и качество кода, покрытие тестами, дублирование.

yaml

# В CI/CD (GitHub Actions)
- name: Run SonarQube analysis
  run: |
    dotnet tool install --global dotnet-sonarscanner
    dotnet sonarscanner begin /k:"project-key" /d:sonar.host.url="http://sonarqube:9000"
    dotnet build
    dotnet sonarscanner end

Что проверяет:

  • Все, что проверяет Security Code Scan.
  • Плюс качество кода, сложность, тестовое покрытие.
  • Плюс интеграцию с CI/CD.

3. OWASP Dependency Check (мы рассмотрим в §11.5)

Этот инструмент проверяет сторонние библиотеки на наличие известных уязвимостей.

Когда SAST находит уязвимость, разработчик видит что-то подобное. Разберем то, что они видят в IDE (Visual Studio):

wireframe

⚠️ Security Code Scan: SCS0001

   SQL injection vulnerability detected.

   The query is constructed using string concatenation with user input.

   Recommendation: Use parameterized queries.

   Location: UserController.cs, line 42

В CI/CD (отчет):

wireframe

=================================================================

Security Code Scan Report

=================================================================

1 critical issues found:

[CRITICAL] SQL injection vulnerability

File: UserController.cs

Line: 42

Description: Query uses string concatenation with user input.

Recommendation: Use parameterized queries.

=================================================================

Что делает разработчик:

1. Читает сообщение.

2. Понимает, где проблема и почему она опасна.

3. Исправляет код (использует параметризованный запрос).

4. Отправляет исправление снова.

§11.3. DAST: Dynamic Application Security Testing

DAST расшифровывается как Dynamic Application Security Testing.

DAST

— динамическое тестирование безопасности приложений.

Это значит, что DAST проверяет работающее приложение через внешние запросы. Он не смотрит на код, он ведет себя как злоумышленник — отправляет запросы, анализирует ответы и ищет уязвимости.

Чем DAST отличается от SAST:

ХарактеристикаSASTDAST
Что проверяетКод (без запуска)Работающее приложение
КогдаНа этапе написания кодаНа этапе тестирования (staging)
Знает кодДа (анализирует исходники)Нет (как хакер)
Что находитSQL-инъекции в коде, XSS, устаревшие библиотекиОткрытые порты, ошибки авторизации, неправильные заголовки
Требует запущенное приложениеНетДа
СкоростьБыстро (секунды)Медленнее (минуты)

Простая аналогия:

  • SAST — это как проверка чертежа самолета. Вы смотрите, правильно ли спроектированы крылья.
  • DAST — это как испытательный полет. Вы запускаете самолет, проверяете, открывается ли шасси, работает ли автопилот.

И SAST, и DAST нужны. Они находят разные типы проблем.

Что же может найти DAST? DAST находит уязвимости, которые видны снаружи, без доступа к коду.

Что ищет DASTПримерПочему это опасно
Неправильная авторизацияМожно зайти в админку без логинаЛюбой может управлять системой
Открытые портыПорт 8080 открыт, на нем висит база данныхХакер может подключиться к БД
Слабые паролиПароль admin на тестовом сервереЛегко взломать
Неправильные заголовкиНет X-Frame-Options, Content-Security-PolicyУязвимость к XSS
Незащищенные эндпоинтыGET /api/users возвращает всех пользователейУтечка данных
ИнъекцииSQL-инъекции, XSS в работающем приложенииКража данных

DAST запускается на работающем приложении, когда оно уже развернуто в тестовой среде (staging).

Где запускаетсяКогдаЗачем
Staging-средаПеред релизом в продакшенПроверить, что приложение безопасно
ПродакшенРегулярно (еженедельно, ежемесячно)Проверить, не появились ли новые уязвимости
ПериодическиПо расписанию (ночью)Не влияет на разработчиков

Это примерно выглядит следующим образом:

wireframe

Разработка → Test → Staging → DAST → Результат → Продакшен

       ↑

DAST проверяет здесь

Для .NET-проектов (и не только) есть несколько популярных инструментов DAST. Самый известный и доступный — OWASP ZAP.

1. OWASP ZAP (Zed Attack Proxy)

Это бесплатный инструмент от OWASP для тестирования безопасности веб-приложений. Как работает:

1. Вы запускаете OWASP ZAP.

2. Указываете URL вашего приложения (например, https://staging.myapp.com).

3. ZAP начинает сканировать: отправляет запросы, анализирует ответы, ищет уязвимости.

4. Вы получаете отчет о найденных проблемах.

Что умеет ZAP:

ВозможностьЧто делает
Автоматическое сканированиеПроверяет все эндпоинты на уязвимости
SpiderИщет все страницы и эндпоинты приложения
Active ScanАктивно атакует приложение (SQL-инъекции, XSS)
Passive ScanАнализирует ответы без атак
ПроксиМожно подхватывать и изменять запросы вручную

Отчет в OWASP ZAP выглядит следующим образом:

2. Коммерческие решения (для больших проектов)

ИнструментЧто делаетКогда нужен
Burp SuiteПрофессиональный инструмент для тестирования безопасностиДля профессионального пентеста
QualysОблачное сканирование уязвимостейДля корпоративных проектов

Как выглядит работа с OWASP ZAP? Она выглядит в виде нескольких шагов.

Шаг №1. Запустить ZAP

bash

# Запуск ZAP (из командной строки)
./zap.sh -cmd -quickurl https://staging.myapp.com -quickout report.html

Шаг №2. ZAP сканирует приложение

ZAP отправляет множество запросов к вашему приложению:

wireframe

→ GET /api/users

← 200 OK

→ POST /api/login

← 200 OK

→ GET /api/admin

← 403 Forbidden (хорошо, авторизация работает)

→ POST /api/users?sql=...

← 500 Internal Server Error (возможна инъекция!)

Шаг №3. Получить отчет

wireframe

=================================================================

OWASP ZAP Security Report

=================================================================

High risk issues: 2

  1. SQL Injection vulnerability found in /api/users

  2. Cross-Site Scripting found in /api/search

Medium risk issues: 3

  1. Missing security headers (X-Frame-Options)

  2. Sensitive data in response body

  3. Insecure cookie settings

Low risk issues: 1

  1. Directory listing enabled

=================================================================

DAST можно (и нужно) встраивать в CI/CD-конвейер. Как это выглядит в GitHub Actions:

yaml

name: Security Scan

on:
  push:
    branches: [ main ]

jobs:
  dast-scan:
    runs-on: ubuntu-latest

    steps:
      - name: Deploy application to staging
        run: |
          # Развертываем приложение на тестовую среду
          
      - name: Run OWASP ZAP scan
        uses: zaproxy/action-baseline@v0.11.0
        with:
          target: 'https://staging.myapp.com'
          
      - name: Upload results
        uses: actions/upload-artifact@v4
        with:
          name: dast-report
          path: report.html

Что получает команда при интеграции DAST в CI / CD:

РезультатДействие
✅ 0 уязвимостейРелиз разрешен
⚠️ 1 – 2 низкорисковыеТребуется подтверждение
❌ ВысокорисковыеРелиз блокируется

§11.4. SAST vs DAST: что и когда использовать

Мы познакомились с двумя подходами к тестированию безопасности:

ПодходЧто проверяетКогда
SASTКод (без запуска)На этапе разработки
DASTРаботающее приложениеНа этапе тестирования

Важно понять, что это не конкуренты

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

Простая аналогия: вы покупаете дом.

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

И то, и другое важно. Если чертежи плохие — дом не будет стоять. Если чертежи хорошие, но строители сделали ошибки — дом тоже не будет стоять.

Давайте сравним эти два подхода в виде таблицы:

ХарактеристикаSASTDAST
Что проверяетКод (исходники)Работающее приложение
Нужен ли запущенный кодНетДа
Знает ли кодДа (анализирует исходники)Нет (как хакер)
Когда запускаетсяНа этапе разработки (IDE, CI/CD)На этапе тестирования (staging)
СкоростьБыстро (секунды)Медленнее (минуты)
Что находитSQL-инъекции в коде, XSS, устаревшие библиотекиОткрытые порты, ошибки авторизации, неправильные заголовки
Требует доступа к кодуДаНет
Может найтиПроблемы в кодеПроблемы в инфраструктуре
ИтогПроверяет, правильно ли написаноПроверяет, правильно ли работает

Теперь давайте определим, когда какой инструмент использовать. SAST используем:

КогдаПочему
На этапе написания кода (IDE)Мгновенная обратная связь
При каждом git push (CI/CD)Автоматическая проверка
Перед Code ReviewНайти проблемы до того, как код увидят другие
Для проверки зависимостейНайти устаревшие библиотеки

DAST используем:

КогдаПочему
После развертывания в stagingПроверить работающее приложение
Перед релизом в продакшенФинальная проверка
Регулярно в продакшенеПроверить, не появились ли новые уязвимости
При изменении инфраструктурыПроверить, не открылись ли новые порты

Использование комбинации SAST + DAST является полным покрытием безопасности. Использовать только SAST — небезопасно, так как:

wireframe

SAST нашел проблемы в коде → Разработчик исправил → Релиз

                                                      ↓

                                          ❌ DAST не запускали!

                                          ❌ Не проверены настройки,

                                          ❌ Не проверена авторизация,

                                          ❌ Не проверены заголовки

использовать только DAST — небезопасно:

wireframe

DAST нашел проблемы в работе → Администратор исправил → Релиз

                                                         ↓

                                           ❌ SAST не запускали!

                                           ❌ Не проверены библиотеки,

                                           ❌ Не проверены SQL-инъекции в коде

использовать SAST + DAST — безопасно:

Что дает комбинация:

SAST находитDAST находитВместе находят
SQL-инъекции в кодеSQL-инъекции в работеВсё
XSS в кодеXSS в работеВсё
Устаревшие библиотекиНеправильные заголовкиВсё
Ошибки конфигурации в кодеОткрытые портыВсё

Давайте разберем практический пример. Возьмем, например, сценарий, когда команда разрабатывает интернет – магазин. Без проверки безопасности:

wireframe

Разработка → Тесты → Продакшен

                      ↓

          ❌ Уязвимости найдены хакерами

          ❌ Данные пользователей украдены

          ❌ Репутация компании разрушена

С SAST (половина решения):

wireframe

Разработка → SAST → Тесты → Продакшен

                      ↓

          ✅ Уязвимости в коде найдены

          ❌ Но уязвимости в настройках остались

С SAST + DAST (полное решение):

wireframe

Разработка → SAST → Тесты → DAST (Staging) → Продакшен

                          ↓                      ↓

                  ✅ Уязвимости в      ✅ Релиз безопасен

                  коде и настройках

                  найдены и исправлены

Давайте приведем простую аналогию, например, проверка чертежа и проверка готового здания. Проверка чертежа (SAST). Вы — архитектор. Вы смотрите на чертеж дома. Вы проверяете:

  • Правильно ли расположены стены?
  • Правильно ли рассчитана нагрузка?
  • Есть ли запас прочности?

Проверка готового здания (DAST). Вы — инспектор по строительству. Вы ходите по построенному дому. Вы проверяете:

  • Стоят ли стены ровно?
  • Не протекает ли крыша?
  • Закрываются ли двери?
  • Есть ли запасной выход?

§11.5. Анализ уязвимостей в зависимостях (SCA)

SCA расшифровывается как Software Composition Analysis.

Software Composition Analysis

— анализ состава программного обеспечения.

Это значит, что SCA проверяет все сторонние библиотеки (NuGet-пакеты, npm-пакеты), которые использует ваш проект, и ищет среди них известные уязвимости.

Вот, например, вы покупаете готовый торт в магазине. Вы не знаете, из каких ингредиентов он сделан. SCA — это как проверка всех ингредиентов: «Этот шоколад просрочен? Эта мука безопасна?».

Современные проекты редко пишут всё с нуля. Мы используем готовые библиотеки. Обычно, 90% кода – чужие библиотеки.

Тип библиотекиПримерЗачем
ФреймворкиASP.NET Core, ReactОснова приложения
УтилитыNewtonsoft.Json, LodashСериализация, обработка данных
Работа с БДEntity Framework, SequelizeРабота с базой данных
ТестированиеxUnit, Jest, PlaywrightНаписание тестов

Сколько кода в проекте — ваш, а сколько — чужие библиотеки?

Это значит, что, если в одной из этих библиотек есть уязвимость — она есть во всем проекте. Вы можете написать идеальный код, но, если библиотека, которую вы используете, уязвима — ваша система тоже уязвима.

Например, вы строите дом. Вы сами построили стены и крышу (ваш код). Но вы купили готовые окна (библиотека). Если окна плохие — дом будет холодным, даже если стены идеальные.

Чем же опасны устаревшие библиотеки? CVE (Common Vulnerabilities and Exposures) — это база данных известных уязвимостей. Каждая уязвимость получает свой номер (например, CVE-2021-44228). Пример: уязвимость в Log4j (CVE-2021-44228).

В 2021 году в популярной Java-библиотеке Log4j нашли критическую уязвимость. Это позволило хакерам выполнять произвольный код на серверах, где использовалась эта библиотека.

Что произошлоПоследствия
Log4j использовали тысячи приложенийОгромное количество систем было уязвимо
Хакеры нашли уязвимостьНачались массовые атаки
Нужно было срочно обновлять библиотекуКоманды работали сутками, чтобы исправить

А чем же опасны устаревшие библиотеки:

ОпасностьЧто это значит
Известные уязвимостиЕсли CVE известно, хакеры могут использовать его
Легкая эксплуатацияЧасто есть готовые скрипты для атаки
Сложно обнаружитьУязвимость не в вашем коде, а в библиотеке
Быстрое распространениеОдна уязвимость может затронуть тысячи проектов

Для .NET-проектов есть несколько инструментов для анализа зависимостей.

1. dotnet list package --vulnerable (встроенный)

Это встроенная команда в .NET SDK, которая проверяет пакеты на известные уязвимости.

bash

# Проверить уязвимости в проекте
dotnet list package --vulnerable

# Вывод
The following packages were found with known vulnerabilities:
┌────────────────────────────────────────────────────────────┐
│ Package                   │ Severity  │ Advisory URL       │
├───────────────────────────┼───────────┼────────────────────┤
│ Newtonsoft.Json 12.0.1    │ High      │ https://...        │
│ Microsoft.Data.SqlClient  │ Moderate  │ https://...        │
└────────────────────────────────────────────────────────────┘

Она показывает название пакета, текущую версию, уровень серьезности и ссылку на описание уязвимости.

2. OWASP Dependency Check

Бесплатный инструмент от OWASP для проверки зависимостей.

bash

# Запуск проверки
dependency-check --scan ./src --format HTML --out ./reports

Она проверяет все зависимости (NuGet, npm, Maven) на наличие известных CVE.

3. Snyk

Популярный инструмент для проверки безопасности зависимостей.

bash

# Установка Snyk
npm install -g snyk

# Проверка .NET-проекта
snyk test --dotnet

Что дает Snyk:

  • Проверка на уязвимости.
  • Рекомендации по исправлению (какую версию установить).
  • Интеграция с CI/CD.

SCA нужно встраивать в CI/CD так же, как и другие проверки безопасности.

Как это выглядит в GitHub Actions:

yaml

name: SCA Scan
on:
  push:
    branches: [ main, develop ]
jobs:
  dependency-check:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4      
      - name: Setup .NET
        uses: actions/setup-dotnet@v4
        with:
          dotnet-version: '8.0'      
      - name: Run SCA scan (dotnet)
        run: |
          dotnet list package --vulnerable      
      - name: Upload results
        uses: actions/upload-artifact@v4
        with:
          name: sca-report
          path: sca-report.txt

Как это выглядит в GitLab CI:

yaml

dependency-scan:
  stage: test
  image: mcr.microsoft.com/dotnet/sdk:8.0
  script:
    - dotnet list package --vulnerable
  artifacts:
    paths:
      - sca-report.txt

Что делать, если найдена уязвимость? Следовать следующим шагам:

ШагЧто делатьПочему
1. Посмотреть CVEОткрыть ссылку с описанием уязвимостиПонять, насколько это опасно
2. Проверить версиюУзнать, какая версия библиотеки используетсяПонять, подвержена ли она
3. Обновить библиотекуПерейти на версию, в которой исправлена уязвимостьУстранить проблему
4. ПротестироватьЗапустить тесты, чтобы убедиться, что ничего не сломалосьУбедиться, что обновление безопасно
5. Отправить кодЗапушить изменения, CI/CD проверит сноваПолучить зеленый отчет

Если обновление невозможно:

ВариантЧто делать
Поискать альтернативуИспользовать другую библиотеку
Написать оберткуИзолировать использование библиотеки
Принять рискНо задокументировать его

§11.6. Интеграция безопасности в CI/CD (DevSecOps)

Мы уже изучили три инструмента безопасности. Теперь посмотрим, как они встраиваются в конвейер. Схема конвейера с безопасностью:

Этапы конвейера с проверкой безопасности проходят в несколько этапов.

Этап №1. SAST при каждом push (быстро)

Запускается сразу после того, как разработчик отправляет код.

yaml

# GitHub Actions (упрощенно)
- name: Run SAST scan
  run: dotnet run --project SecurityCodeScan

Он проверяет SQL-инъекции, XSS, устаревшие методы, ошибки конфигурации. Время выполнения примерно 10 – 30 секунд.

В случае возникновения ошибки, конвейер падает. Разработчик исправляет уязвимость в коде.

Этап №2. SCA при каждом push (быстро)

Запускается параллельно с SAST или сразу после него.

yaml

- name: Run SCA scan
  run: dotnet list package --vulnerable

Он проверяет устаревшие библиотеки с известными уязвимостями (CVE). Время выполнения примерно 10 – 30 секунд.

В случае возникновения ошибки, конвейер падает. Разработчик обновляет уязвимую библиотеку.

Этап №3. DAST на развернутом приложении (в staging)

Запускается только после того, как приложение развернуто в staging-среде.

yaml

- name: Run DAST scan
  run: |
    # Развернуть приложение в staging
    # Запустить OWASP ZAP против staging-приложения

Он проверяет открытые порты, ошибки авторизации, неправильные заголовки, инъекции в работающем приложении. Время выполнения примерно 2 – 5 минут (медленнее, чем SAST).

В случае возникновения ошибки, конвейер падает. Команда исправляет настройки или код.

Что делать, если уязвимость найдена: падать или только предупреждать? Это главный вопрос при настройке безопасности в CI/CD.

ПодходЧто происходитКогда применять
Конвейер падаетРелиз блокируетсяДля критических уязвимостей (SQL-инъекции, утечка данных)
Только предупреждениеРелиз продолжаетсяДля низкорисковых проблем (стиль, рекомендации)

В случае, если конвейер падает:

yaml

- name: Run SAST scan
  run: dotnet run --project SecurityCodeScan
  # Если SAST нашел критическую уязвимость — конвейер падает

Когда использовать:

  • SQL-инъекции.
  • XSS.
  • Критические CVE в библиотеках.
  • Открытые порты в staging.

Почему:

  • Эти уязвимости легко использовать для атаки.
  • Они могут привести к утечке данных.
  • Их нужно исправлять до релиза.

Только предупреждение:

yaml

- name: Run SAST scan
  run: dotnet run --project SecurityCodeScan
  continue-on-error: true
  # Даже если SAST нашел проблемы — конвейер продолжается

Когда использовать:

  • Низкорисковые уязвимости (некритические).
  • Рекомендации по улучшению (не ошибки).
  • Устаревшая, но безопасная библиотека.

Почему:

  • Проблема не критична для релиза.
  • Ее можно исправить в следующих версиях.

Это сложно понять на первый взгляд, но если знать правило «80 / 20», то все становится просто.

Рассмотрим это правило:

Уровень серьезностиДействиеПример
Критическая (Critical)Конвейер падает ❌SQL-инъекция, утечка паролей
Высокая (High)Конвейер падает ❌XSS, известная уязвимость в библиотеке
Средняя (Medium)Предупреждение ⚠️Рекомендация по улучшению
Низкая (Low)Предупреждение ⚠️Стилистическая проблема

Конвейер для разработчиков выглядит в виде нескольких сценариев.

Сценарий №1. Всё хорошо

wireframe

✅ SAST (10s)    → ✅ Все хорошо

✅ SCA (10s)     → ✅ Все хорошо

✅ Build (30s)   → ✅ Собрано

✅ Tests (60s)   → ✅ Все тесты прошли

✅ Deploy (60s)  → ✅ Развернуто

✅ DAST (120s)   → ✅ Все хорошо

✅ Конвейер зеленый → Релиз разрешен!

Сценарий №2. SAST нашел уязвимость

wireframe

❌ SAST (10s)    → ❌ Найдена SQL-инъекция!

   → Конвейер остановлен!

   → Разработчик: исправляю уязвимость.

   → Отправляю исправление.

   → Конвейер снова зеленый.

Сценарий №3. DAST нашел уязвимость

wireframe

✅ SAST (10s)    → ✅ Все хорошо

✅ SCA (10s)     → ✅ Все хорошо

✅ Build (30s)   → ✅ Собрано

✅ Tests (60s)   → ✅ Все тесты прошли

✅ Deploy (60s)  → ✅ Развернуто

❌ DAST (120s)   → ❌ Найдены открытые порты!

   → Конвейер остановлен!

   → DevOps: закрываю порты.

   → Отправляю исправление.

   → Конвейер снова зеленый.

§11.7. Антипаттерны в тестировании безопасности

В этой лекции мы изучили инструменты безопасности: SAST, DAST, SCA. Но инструменты — это только половина дела. Вторая половина — правильное использование.

Есть несколько типичных ошибок, которые сводят на нет все усилия по обеспечению безопасности. Они превращают безопасность из реальной защиты в иллюзию.

Главная мысль этого параграфа заключается в том, что безопасность —это постоянный процесс. И каждый член команды за него отвечает.

Антипаттерн №1. «Безопасность — это не моя работа»

Почему это опасно:

Кто так думаетК чему это приводит
РазработчикПишет код с уязвимостями (SQL-инъекции, XSS)
ТестировщикНе проверяет безопасность, пропускает уязвимости
DevOpsНастраивает сервер с открытыми портами
Все вместеСистема уязвима, данные пользователей под угрозой

Как должно быть правильно:

КтоЧто делает
РазработчикПишет безопасный код (использует параметризованные запросы, валидацию)
ТестировщикПроверяет, что код безопасен (запускает SAST, проверяет авторизацию)
DevOpsНастраивает сервер безопасно (закрытые порты, HTTPS)
Все вместеБезопасность — общая ответственность

Для примера давайте посмотрим на аналогию. Безопасность в офисе — это не задача только охраны. Это задача всех. Каждый сотрудник закрывает дверь, не оставляет документы на столе, не сообщает пароли посторонним. Если кто-то думает «это не моя работа» — офис становится уязвимым.

Антипаттерн №2. «Мы проверили SAST, DAST не нужен»

Почему это опасно? SAST проверяет код, но не проверяет:

Что проверяет SASTЧто НЕ проверяет SAST
SQL-инъекции в кодеSQL-инъекции в работающем приложении
XSS в кодеXSS в работающем приложении
Устаревшие библиотекиОткрытые порты
Ошибки конфигурации в кодеНеправильные заголовки в ответах

Пример:

wireframe

SAST: ✅ Все хорошо. Код безопасен.

DAST: ❌ Найдена проблема: порт 8080 открыт, база данных доступна извне.

      ❌ Найдена проблема: отсутствуют заголовки безопасности.

Код безопасен, но система уязвима. Без DAST вы этого не узнаете.

Вот, например, вы проверили двигатель машины (SAST). Он работает идеально. Но вы не проверили, открыты ли двери, работает ли сигнализация, есть ли запасное колесо (DAST). Машина поедет, но она небезопасна.

Антипаттерн №3. «Запустили один раз и забыли»

Почему это опасно:

Что происходит со временемПоследствия
Появляются новые CVE в библиотекахВы используете устаревшие, уязвимые версии
Изменяются стандарты безопасностиВы не соответствуете современным требованиям
Появляются новые типы атакВы не защищены от новых угроз
Разработчики меняют кодНовый код может содержать уязвимости

Пример:

wireframe

Месяц 1: Настроили SAST ✅

Месяц 3: Появилась уязвимость в Newtonsoft.Json (CVE)

         SAST не обновлен → уязвимость не найдена

Месяц 6: Хакеры используют эту уязвимость ❌

Как должно быть правильно:

Что делатьКак часто
Обновлять правила SASTЕжемесячно
Проверять новые CVEЕженедельно
Пересматривать настройки безопасностиПосле каждого релиза
Обновлять инструментыПри выходе новых версий

Антипаттерн №4. «Игнорируем предупреждения»

Почему это опасно:

Уровень предупрежденияЧто это значитЕсли игнорировать
Информация (Info)РекомендацияНет проблем
Низкая (Low)Потенциальная проблемаМожет стать уязвимостью
Средняя (Medium)Реальная проблемаМожет привести к атаке
Высокая (High)Критическая уязвимостьАтака почти гарантирована

Пример:

wireframe

SAST: ⚠️ Предупреждение: используется MD5 для хеширования паролей.

       Рекомендация: использовать bcrypt.

Разработчик: "Ну, работает же. Не буду трогать."

Через месяц:

Хакеры взламывают пароли (MD5 уязвим) ❌

Желтые предупреждения становятся красными уязвимостями.

Сравнительная таблица антипаттернов представлена ниже:

АнтипаттернСимптомПоследствияРешение
«Не моя работа»Никто не отвечает за безопасностьСистема уязвима, все ждут другогоБезопасность — задача всех
«SAST достаточно»Запускают только SASTDAST находит проблемы в работеИспользовать SAST + DAST
«Запустили и забыли»Инструменты не обновляютсяНовые уязвимости не находятсяОбновлять регулярно
«Игнорируем предупреждения»Желтые отчеты закрываютсяПредупреждения становятся уязвимостямиИсправлять все, даже низкорисковые

В заключение нужно разобрать что делать и как это делать правильно при работе с тестированием:

Что нужно делатьКак
Признать ответственностьБезопасность — задача каждого члена команды
Использовать все инструментыSAST + DAST + SCA — не один, а все
Обновлять регулярноИнструменты, правила, библиотеки
Не игнорировать предупрежденияИсправлять все проблемы, даже низкорисковые
Проверять сноваПосле исправления — перезапускать проверку