{ "index": 179, "slug": "editorial-2023-01-mechanism-threat-model", "title": "Модель угроз без догадок: связать актив, риск и проверяемый контроль", "excerpt": "Как превратить разговор о безопасности в проверяемую связь: назвать актив, границу и злоупотребление, выбрать контроль и заранее определить evidence для отрицательного пути.", "contentHtml": "
В ревью появляется знакомый симптом: в изменении уже назван контроль — подпись, шифрование, rate limit или дополнительная проверка, — но никто не может ответить, какой актив он защищает и какой вход должен быть отвергнут. Обсуждение быстро сводится к вкусу: один инженер предлагает JWT, другой — mTLS, третий — ещё один middleware. Цена ошибки — ложное закрытие риска. Команда может потратить время на защиту не той границы, а при откате не сможет объяснить, какую гарантию она снимает.
\nТезис статьи простой: модель угроз полезна только тогда, когда связывает четыре наблюдаемых вещи — актив, злоупотребление, контроль и evidence. Название технологии не заменяет эту связь. Сначала нужно зафиксировать, что важно сохранить, какое действие нарушает это свойство, где система принимает решение и чем команда увидит отказ. Такой минимальный контракт не доказывает безопасность продукта. Он делает решение проверяемым и показывает, чего ещё не хватает.
\nВозьмём учебный поток: browser-client отправляет change-request через границу public-api-to-handler, обработчик принимает или отклоняет запрос, затем записывает его в store. Актив — не «данные вообще», а конкретный change-request. Злоупотребление — отправить запрос без valid signature. Контроль — проверять подпись до записи. Evidence — наблюдаемый отказ на неподписанном входе.
\nУ каждого поля есть один вопрос. Asset отвечает: «что потеряет свойство при ошибке?». Abuse отвечает: «какое действие мы пытаемся остановить?». Boundary отвечает: «где вход перестаёт быть доверенным?». Control отвечает: «какое решение примет система?». Evidence отвечает: «что увидит проверяющий и по какому признаку скажет pass или fail?». Если поле заменяют словами «система», «безопасность» или «проверено», модель теряет смысл.
\n| Элемент | Учебное значение | Проверяемый вопрос | Что не следует из записи |
|---|---|---|---|
| Actor | browser-client | кто формирует вход? | личность пользователя и его права |
| Asset | change-request | что нужно сохранить? | классификация всех данных продукта |
| Boundary | public-api-to-handler | где меняется доверие к входу? | полная топология сети |
| Abuse | unsigned request | какое действие не должно пройти? | полный список атак |
| Control | signed-request | какое условие проверяет handler? | достаточность криптографии |
| Evidence | local rejection check | какой отказ можно наблюдать? | результат production-проверки или pentest |
Ниже — учебный JavaScript-пример. Он не создаёт ключи, не подписывает HTTP-запросы и не обращается к базе. Функция проверяет только полноту описания потока. Это полезно для иллюстрации механизма: пропущенный актив или неизвестный контроль не превращаются в молчаливую догадку.
\nfunction planThreatModel(input) {\n const required = ['actor', 'asset', 'boundary', 'abuse', 'control', 'evidence'];\n const missing = required.filter((key) => !input[key]);\n\n if (missing.length > 0) {\n return { status: 'reject', reason: `missing: ${missing.join(', ')}` };\n }\n\n const allowedControls = ['signed-request', 'explicit-authorization'];\n if (!allowedControls.includes(input.control)) {\n return { status: 'reject', reason: 'unknown-control' };\n }\n\n return {\n status: 'accept',\n contract: {\n asset: input.asset,\n abuse: input.abuse,\n control: input.control,\n evidence: input.evidence\n }\n };\n}\n\n// Учебный вызов: это не проверка реального endpoint.\nplanThreatModel({\n actor: 'browser-client',\n asset: 'change-request',\n boundary: 'public-api-to-handler',\n abuse: 'unsigned request',\n control: 'signed-request',\n evidence: 'local rejection check'\n});\nПоложительный результат здесь означает только то, что запись содержит нужные поля и знакомый контроль. Он не означает, что подпись реализована правильно, ключи защищены, права проверены или запрос нельзя подделать другим способом. Отрицательный путь важнее happy path: пустой asset, отсутствующая boundary и неизвестный control должны остановить описание. В рабочем коде такой контракт нужно дополнить тестом самого handler, а затем отдельно проверить интеграцию и эксплуатационные границы.
\n| Симптом | Причина | Проверка | Действие |
|---|---|---|---|
| Есть control, но нет asset | выбрали привычную технологию | какой объект теряет свойство? | назвать один asset до выбора механизма |
| Есть threat, но нет boundary | не указано место решения | где вход меняет статус доверия? | показать одну границу на потоке |
| Есть control, но нет evidence | не описан отрицательный путь | какой вход должен получить отказ? | добавить test, log или ручную проверку |
| В evidence написано «проверено» | не назван метод и результат | что именно увидит другой инженер? | указать вход, ожидаемый отказ и артефакт |
| Rollback означает «вернуть всё» | модель смешана с выпуском | какие поля и ресурсы реально меняются? | разделить snapshot договора и план отката |
Малая модель не ранжирует риск, не считает вероятность, не строит attack tree и не перечисляет все trust zones. Она не проверяет криптографический протокол, identity provider, права доступа, хранение секретов или журналирование. Если актив связан с персональными данными, платежами или критичной операцией, потребуется более подробная классификация, согласованный владелец риска и независимая проверка.
\nКонтроль может оказаться неверным даже при полной записи. Подпись не заменяет авторизацию. Шифрование канала не доказывает целостность бизнес-операции. Rate limit не решает проблему подмены личности. Нельзя переносить учебное signed-request на реальный API без проверки протокола, ключей, времени жизни, повторной отправки и обработки ошибок. Отрицательный результат модели — повод остановиться и уточнить решение, а не повод подобрать другое модное слово.
\nМодель готова к следующему этапу, если независимый инженер без устных пояснений может назвать asset, злоупотребление, boundary, контроль и evidence; воспроизвести отрицательную проверку; увидеть однозначный pass или fail; и понять, что именно откатывается. Это критерий полноты записи, а не сертификат безопасности. Для реализации нужен отдельный критерий: тест должен пройти на настоящем handler с разрешённым входом и явно заданным неподписанным входом, а результат должен принадлежать согласованному артефакту проверки.
\n