DarkRiDDeR12 мин

Полевой маршрут модели угроз: как не принять контроль без объекта защиты

БезопасностьПрактика

Изменение безопасности часто приходит как готовая фраза: «добавим подпись», «поставим ограничение» или «закроем endpoint». Проблема в том, что после первого вопроса ревью — какой актив и какой abuse — разговор останавливается. Цена — не только лишняя работа. Непроверяемый control может заблокировать полезный поток, а команда не сумеет объяснить, какие данные нужны для решения и что произойдёт при откате.

Ниже — маршрут для одного change, а не процедура оценки организации. Он берёт маленький учебный DFD: browser-client → public-api-to-handler → handler → change-request store. В нём одна граница, один asset и одно злоупотребление. Локальная функция помогает проверить полноту записи, но не общается с браузером, API, ключами или production. Поэтому она не выдаётся за pentest, compliance evidence или результат настоящей модели угроз.

Соберите симптом как наблюдаемый пробел

Начните не с названия технологии, а с пробела в решении. Например: handler сейчас получает request, но contract не говорит, по какому признаку он должен отвергнуть неподтверждённый вход. Это ещё не утверждение, что есть уязвимость. Чтобы сделать утверждение, понадобятся scope, конфигурация, реализация, данные о доступе и независимая проверка. На первом шаге достаточно честно назвать неизвестное: у решения нет связи между активом, злоупотреблением и evidence.

Затем сузьте поток. Browser-client — источник, change-request — asset, public-api-to-handler — boundary, unsigned request — abuse. У каждого слова есть функция в следующем вопросе. Asset отвечает «что важно». Boundary отвечает «где меняются предположения». Abuse отвечает «какое действие не должно пройти». Если одно слово заменить словом «система» или «безопасность», маршрут сразу теряет место для проверки.

Диагностика записи до реализации
Наблюдение в ревьюВероятная причинаПроверяемый вопросПервое действие
Есть control, нет assetвыбрали привычную мерукакой объект теряет свойство?назвать asset одной строкой
Есть threat, нет boundaryне указано место решениягде вход перестаёт быть доверенным?нарисовать одну стрелку DFD
Есть control, нет evidenceнет отрицательной веткикакой вход должен быть отвергнут?добавить локальную проверку договора
В evidence написано «проверено»не назван методчто именно увидит reviewer?указать test, log или ручной шаг
Rollback означает «вернуть всё»смешаны модель и выпусккакие артефакты меняются?разделить snapshot и deployment plan

Разложите один поток, не рисуя весь продукт

На схеме достаточно source, process и store. Стрелка request проходит boundary. Возле неё положите abuse; возле handler — control; рядом с control — evidence. Не добавляйте в рисунок несуществующие базы, firewall, SIEM или сотрудников для солидности. Каждый объект должен поддерживать вопрос, который вы зададите в ревью. Если рисуете ключ, должны быть готовы объяснить его жизненный цикл; если пока не готовы, ключ не нужен в малой модели.

Контроль signed-request выбран здесь как условный пример, не совет для любого API. Он не равен «шифровать трафик», «проверять пользователя» или «включить JWT». Его узкое обещание записано в модели: без проверяемой подписи handler не принимает request. В реальном решении это может быть не тот механизм, или обязательство может жить на другой границе. Правильность выбора определяет доменная и техническая проверка, которую статья не подменяет.

Маршрут диагностики учебной модели угроз: контроль без asset возвращает к названию объекта; threat без boundary — к DFD-стрелке; control без evidence — к отрицательной проверке; accepted plan сохраняет snapshot, rollback возвращает исходные поля.
Рисунок показывает порядок вопросов для ревью и границу rollback учебной записи. Он не является диаграммой инцидента, отчётом сканера или процедурой развёртывания.

Прогоните локальный fixture, затем отделите его от продукта

Команда может запустить fixture до ревью, чтобы исключить механические пропуски: пустой asset, отсутствующую boundary или неизвестный control. Пример не требует зависимостей и возвращает одинаковые objects. Но после PASS нужно сделать второй шаг: показать место в коде или документе, к которому относится выбранная запись. Без этого fixture проверяет только аккуратность учебной формы, а не поведение приложения.

node web/scripts/upgrade-2023-01.mjs --verify-fixture

# PASS означает: локальная модель приняла полный набор полей,
# связала signed-request с одним evidence и умеет вернуть snapshot.
# PASS не означает: endpoint проверен, подпись реализована или риск закрыт.

Полезно разнести evidence по уровням. Для модели — assertion функции. Для реализации — unit test обработчика или review конкретного guard. Для интеграции — согласованный test среды с явными входными данными. Для эксплуатации — отдельная процедура с владельцем и допустимыми логами. Нельзя складывать эти уровни в одну строку «проверено». Такой ярлык скрывает, что именно отсутствует, и затрудняет решение, можно ли выпускать change.

Маршрут: симптом → причина → проверка → действие

  1. Симптом. Выпишите control из текущего change и отметьте, какое поле из asset, boundary, abuse, evidence отсутствует.
  2. Причина. Найдите точку, где система должна принять защитное решение. Не называйте сетевую зону boundary, если не можете объяснить, какое предположение меняется.
  3. Проверка договора. Выполните fixture и прочитайте сами assertions. Они проверяют модель, не ваше приложение; это должно остаться в описании change.
  4. Действие. Добавьте один конкретный evidence для одной отрицательной ветки. Сформулируйте его так, чтобы другой человек мог сказать PASS или FAIL без догадки.
  5. Проверка реализации. Отдельно договоритесь об окружении, данных, владельце и артефакте реальной проверки. Если этого нет, пишите «не проверено», а не «защищено».
  6. Откат. Для модели восстановите исходную запись. Для production подготовьте отдельный план: совместимость, ключи, миграции и наблюдение не существуют внутри данного fixture.

Типичные неверные движения

Первое неверное движение — перечислить STRIDE или controls вместо конкретного злоупотребления. Так терминология прячет отсутствие условия. Второе — назвать модель угроз после одной схемы и посчитать задачу закрытой. NIST SP 800-154 сам называет threat modeling формой risk assessment; маленькая схема может быть входом в неё, но не заменой scope и оценки. Третье — считать reject в unit test доказательством сетевой защиты. У уровня проверки есть граница, и она должна быть написана рядом с результатом.

Четвёртое движение — вводить rollback после того, как change уже необратимо связан с другими компонентами. В учебной модели rollback безопасен потому, что это возврат четырёх строк из памяти. В настоящей доставке надо заранее понять, какие контракты, данные и права уже зависят от нового контроля. Если неизвестно, лучше остановить изменение, чем объявить «можно быстро выключить» без доказуемой процедуры.

Граница и следующий шаг

Данная партия не содержит реального DFD продукта, списка активов, оценок риска, scans, traces, уязвимостей, пользователей или результатов. Она не заявляет соответствие NIST, не выбирает криптографию и не гарантирует защиту от неподписанного входа. Источники нужны для проверки терминов и порядка работы, а не как заёмный авторитет для модели из нескольких строк.

Следующий шаг — на ближайшем security-sensitive change завести маленькую запись из таблицы, назначить владельца evidence и вынести операционный rollback в отдельный release plan. Если одна строка не заполняется, это полезный результат: change ещё недостаточно понятен для выбора контроля. Так автор развивает системную практику без притворства, что один пример заменяет зрелую программу безопасности.

Историческая граница января 2023

К январю 2023 были доступны NIST SP 800-154 IPD (14.03.2016), NIST SP 800-218 v1.1 Final (03.02.2022) и NIST SP 800-53 Rev. 5 (2020). Их статусы и даты указаны рядом со ссылками. Они не фиксируют состояние локальной платформы и не дают статье права заявлять проверенный security effect.

Проверяемые источники