Деревья атак и поверхность атаки
Учимся раскладывать «как сюда вообще можно прорваться» на дерево конкретных путей — и сознательно убирать лишние двери, пока их не нашли за нас.
Дерево атаки (attack tree) — иерархическая модель, где корень это цель злоумышленника, а ветви — альтернативные и составные способы её достичь; листья отвечают конкретным уязвимостям и шагам.
STRIDE отвечает на вопрос «какие угрозы возможны», а дерево атак — на вопрос «какими путями цель реально достижима и какой из путей самый дешёвый для атакующего». Это инструмент мышления: вы ставите себя на место нарушителя, формулируете его цель и честно перечисляете способы её добиться. Рядом живёт второе ключевое понятие — поверхность атаки: совокупность всех точек, через которые в систему можно «постучаться». Чем она меньше, тем меньше у дерева атак листьев. Поэтому два навыка работают в паре: деревом атак мы видим пути, минимизацией поверхности — отрезаем их у основания.
Зачем это знать защитнику
Защитнику дерево атак показывает, где тратить усилия. Если к цели ведут пять путей, а вы укрепили один, злоумышленник пойдёт по оставшимся четырём — безопасность системы определяется самым слабым путём, а не самым сильным. Дерево заставляет смотреть на систему целиком и сравнивать пути по стоимости: какой требует меньше навыков, времени и доступа. А карта поверхности атаки превращается в практический чек-лист: каждый открытый порт, эндпоинт, форма загрузки файла, сторонняя интеграция — это вход, который нужно либо защитить, либо убрать. Рисовать деревья атак для своей системы законно и полезно; это проектная дисциплина, а не подготовка взлома.
Как устроено дерево атак
В корне — цель, например «получить доступ к данным пользователей». Ниже — узлы-способы, соединённые логикой ИЛИ (достаточно любого) или И (нужны все сразу). Листья — атомарные действия. Текстом дерево записывают отступами:
ЦЕЛЬ: получить доступ к данным пользователей
├── ИЛИ: украсть учётные данные
│ ├── фишинг сотрудника
│ └── подбор слабого пароля
├── ИЛИ: использовать уязвимость приложения
│ ├── инъекция в недоверенный ввод
│ └── обойти проверку доступа (broken access control)
└── И: получить доступ к бэкапу
├── найти открытое хранилище бэкапов
└── И бэкап не зашифрован
Ветка «бэкап» — пример узла И: данные утекут, только если хранилище доступно и бэкап не зашифрован. Это сразу подсказывает дешёвую защиту: достаточно закрыть любое из двух условий (зашифровать бэкап), и вся ветка обрывается. Узлы можно помечать оценками — стоимость для атакующего, нужные навыки, шанс обнаружения — и так находить самый вероятный путь, чтобы укреплять именно его.
Поверхность атаки и доверительные границы
Поверхность атаки — это все точки взаимодействия с внешним миром: сетевые порты и эндпоинты API, формы и параметры, загрузка файлов, переменные окружения, сторонние библиотеки и сервисы, интерфейсы администратора. Каждая такая точка — потенциальный лист дерева атак. Базовое правило: чем меньше поверхность, тем меньше путей внутрь. Отсюда — практики минимизации: отключать неиспользуемые эндпоинты и порты, не публиковать админку в открытый интернет, удалять мёртвый код и лишние зависимости, держать дефолтную конфигурацию закрытой.
Доверительные границы (trust boundaries) делят систему на зоны с разным уровнем доверия: интернет, DMZ, внутренняя сеть, БД. Данные, пересекающие границу в сторону большего доверия, обязаны проходить проверку — здесь происходит большинство атак. Хорошая архитектура делает границы явными и немногочисленными и валидирует всё, что их пересекает.
Как это работает под капотом
Минимизация поверхности — это во многом про конфигурацию по умолчанию. Сервис, который при старте открывает наружу отладочный или административный интерфейс, добавляет в дерево атак готовый лист. Сравните намерение:
# УЯЗВИМАЯ конфигурация: админ-панель и отладка открыты всему интернету.
# Это два «бесплатных» листа в дереве атак.
bind_address: 0.0.0.0 # слушаем на всех интерфейсах, включая внешний
admin_panel: enabled # доступна без ограничения по сети
debug_mode: true # отдаёт стек-трейсы и внутренние пути
# БЕЗОПАСНАЯ конфигурация: поверхность сведена к минимуму.
bind_address: 127.0.0.1 # доступ только из внутренней сети/через VPN
admin_panel: internal_only
debug_mode: false # наружу — нейтральные сообщения об ошибках
Каждая убранная точка входа — это ветка дерева атак, которой больше нет. Поэтому минимизацию поверхности удобно вести именно по дереву: построили дерево, нашли листья, спросили по каждому «можно ли вообще убрать эту дверь, а не только повесить замок».
Как защититься
Стройте дерево атак для ключевых целей и укрепляйте самые дешёвые для атакующего пути, а не только очевидные. Сводите поверхность атаки к минимуму: отключайте неиспользуемое, не выставляйте админ-интерфейсы наружу, убирайте лишние зависимости и дефолтные учётки. Делайте доверительные границы явными и валидируйте всё, что их пересекает. Используйте узлы И в свою пользу: если для успеха атаки нужны два условия, достаточно гарантированно убрать одно (например, всегда шифровать бэкапы) — и целая ветка становится недостижимой. Помните юридическую рамку: моделировать и тестировать так можно только свои системы или системы с письменного согласия владельца (ст. 272 УК РФ).
Итоги
- Дерево атак раскладывает цель злоумышленника на конкретные пути; узлы — ИЛИ (любой) и И (все сразу).
- Безопасность определяется самым слабым путём — укреплять надо все ведущие к цели ветки.
- Поверхность атаки — все точки входа; чем она меньше, тем меньше путей у атакующего.
- Минимизация поверхности: отключать неиспользуемое, прятать админку, убирать лишние зависимости и дефолтные настройки.
- Узел «И» — подарок защитнику: убрав одно из условий, обрываешь всю ветку (например, шифрование бэкапа).