Files
progcode/editorial/agent-rewrites/179.json
T
huncode 2d914b543f
Build and deploy / deploy (push) Failing after 15s
Publish rewritten technical article archive
2026-08-02 22:19:34 +03:00

8 lines
15 KiB
JSON
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{
"index": 179,
"slug": "editorial-2023-01-mechanism-threat-model",
"title": "Модель угроз без догадок: связать актив, риск и проверяемый контроль",
"excerpt": "Как превратить разговор о безопасности в проверяемую связь: назвать актив, границу и злоупотребление, выбрать контроль и заранее определить evidence для отрицательного пути.",
"contentHtml": "<p>В ревью появляется знакомый симптом: в изменении уже назван контроль — подпись, шифрование, rate limit или дополнительная проверка, — но никто не может ответить, какой актив он защищает и какой вход должен быть отвергнут. Обсуждение быстро сводится к вкусу: один инженер предлагает JWT, другой — mTLS, третий — ещё один middleware. Цена ошибки — ложное закрытие риска. Команда может потратить время на защиту не той границы, а при откате не сможет объяснить, какую гарантию она снимает.</p>\n<p>Тезис статьи простой: модель угроз полезна только тогда, когда связывает четыре наблюдаемых вещи — актив, злоупотребление, контроль и evidence. Название технологии не заменяет эту связь. Сначала нужно зафиксировать, что важно сохранить, какое действие нарушает это свойство, где система принимает решение и чем команда увидит отказ. Такой минимальный контракт не доказывает безопасность продукта. Он делает решение проверяемым и показывает, чего ещё не хватает.</p>\n<h2>Механизм: от актива к доказательству</h2>\n<p>Возьмём учебный поток: browser-client отправляет change-request через границу public-api-to-handler, обработчик принимает или отклоняет запрос, затем записывает его в store. Актив — не «данные вообще», а конкретный change-request. Злоупотребление — отправить запрос без valid signature. Контроль — проверять подпись до записи. Evidence — наблюдаемый отказ на неподписанном входе.</p>\n<p>У каждого поля есть один вопрос. Asset отвечает: «что потеряет свойство при ошибке?». Abuse отвечает: «какое действие мы пытаемся остановить?». Boundary отвечает: «где вход перестаёт быть доверенным?». Control отвечает: «какое решение примет система?». Evidence отвечает: «что увидит проверяющий и по какому признаку скажет pass или fail?». Если поле заменяют словами «система», «безопасность» или «проверено», модель теряет смысл.</p>\n<table><caption>Минимальная связь в одном потоке</caption><thead><tr><th>Элемент</th><th>Учебное значение</th><th>Проверяемый вопрос</th><th>Что не следует из записи</th></tr></thead><tbody><tr><td>Actor</td><td>browser-client</td><td>кто формирует вход?</td><td>личность пользователя и его права</td></tr><tr><td>Asset</td><td>change-request</td><td>что нужно сохранить?</td><td>классификация всех данных продукта</td></tr><tr><td>Boundary</td><td>public-api-to-handler</td><td>где меняется доверие к входу?</td><td>полная топология сети</td></tr><tr><td>Abuse</td><td>unsigned request</td><td>какое действие не должно пройти?</td><td>полный список атак</td></tr><tr><td>Control</td><td>signed-request</td><td>какое условие проверяет handler?</td><td>достаточность криптографии</td></tr><tr><td>Evidence</td><td>local rejection check</td><td>какой отказ можно наблюдать?</td><td>результат production-проверки или pentest</td></tr></tbody></table>\n<h2>Конкретный пример: строгий контракт для отрицательного пути</h2>\n<p>Ниже — учебный JavaScript-пример. Он не создаёт ключи, не подписывает HTTP-запросы и не обращается к базе. Функция проверяет только полноту описания потока. Это полезно для иллюстрации механизма: пропущенный актив или неизвестный контроль не превращаются в молчаливую догадку.</p>\n<pre><code>function planThreatModel(input) {\n const required = ['actor', 'asset', 'boundary', 'abuse', 'control', 'evidence'];\n const missing = required.filter((key) =&gt; !input[key]);\n\n if (missing.length &gt; 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});</code></pre>\n<p>Положительный результат здесь означает только то, что запись содержит нужные поля и знакомый контроль. Он не означает, что подпись реализована правильно, ключи защищены, права проверены или запрос нельзя подделать другим способом. Отрицательный путь важнее happy path: пустой asset, отсутствующая boundary и неизвестный control должны остановить описание. В рабочем коде такой контракт нужно дополнить тестом самого handler, а затем отдельно проверить интеграцию и эксплуатационные границы.</p>\n<figure><img src=\"/assets/editorial/2023/threat-model-2023-contract.svg\" alt=\"Учебная схема связи актива, злоупотребления, контроля и evidence в модели угроз\"><figcaption>Учебная схема показывает связь change-request, unsigned request, signed-request и local rejection check. Она не описывает реальную сеть, ключи или результаты проверки.</figcaption></figure>\n<h2>Симптом → причина → проверка → действие</h2>\n<table><caption>Диагностика неполной модели</caption><thead><tr><th>Симптом</th><th>Причина</th><th>Проверка</th><th>Действие</th></tr></thead><tbody><tr><td>Есть control, но нет asset</td><td>выбрали привычную технологию</td><td>какой объект теряет свойство?</td><td>назвать один asset до выбора механизма</td></tr><tr><td>Есть threat, но нет boundary</td><td>не указано место решения</td><td>где вход меняет статус доверия?</td><td>показать одну границу на потоке</td></tr><tr><td>Есть control, но нет evidence</td><td>не описан отрицательный путь</td><td>какой вход должен получить отказ?</td><td>добавить test, log или ручную проверку</td></tr><tr><td>В evidence написано «проверено»</td><td>не назван метод и результат</td><td>что именно увидит другой инженер?</td><td>указать вход, ожидаемый отказ и артефакт</td></tr><tr><td>Rollback означает «вернуть всё»</td><td>модель смешана с выпуском</td><td>какие поля и ресурсы реально меняются?</td><td>разделить snapshot договора и план отката</td></tr></tbody></table>\n<h2>Порядок действий</h2>\n<ol><li><strong>Сузьте область.</strong> Возьмите один поток, один актив и одну границу. Не пытайтесь описать весь продукт одной диаграммой.</li><li><strong>Назовите злоупотребление глаголом.</strong> Формулировка «отправить запрос без действительной подписи» проверяемее, чем слово «подделка».</li><li><strong>Определите решение.</strong> Запишите, в какой точке handler должен принять или отклонить вход. Не выдавайте имя технологии за условие.</li><li><strong>Опишите evidence.</strong> Укажите конкретный вход, ожидаемый результат и артефакт: unit test, журнал решения или согласованную ручную проверку.</li><li><strong>Проверьте отрицательную ветку.</strong> Передайте пустой asset, неверный вход или неизвестный control. Система должна отказать явно, а не достроить контекст.</li><li><strong>Отделите модель от реализации.</strong> Сверьте контракт с реальным кодом, конфигурацией и владельцем ключей. Учебный пример не заменяет эти проверки.</li><li><strong>Запишите откат.</strong> Назовите, что возвращается при удалении контроля. Если меняются ключи, миграции, очереди или совместимость, нужен отдельный операционный план.</li></ol>\n<h2>Ограничения и отрицательный путь</h2>\n<p>Малая модель не ранжирует риск, не считает вероятность, не строит attack tree и не перечисляет все trust zones. Она не проверяет криптографический протокол, identity provider, права доступа, хранение секретов или журналирование. Если актив связан с персональными данными, платежами или критичной операцией, потребуется более подробная классификация, согласованный владелец риска и независимая проверка.</p>\n<p>Контроль может оказаться неверным даже при полной записи. Подпись не заменяет авторизацию. Шифрование канала не доказывает целостность бизнес-операции. Rate limit не решает проблему подмены личности. Нельзя переносить учебное signed-request на реальный API без проверки протокола, ключей, времени жизни, повторной отправки и обработки ошибок. Отрицательный результат модели — повод остановиться и уточнить решение, а не повод подобрать другое модное слово.</p>\n<h2>Проверяемый критерий готовности</h2>\n<p>Модель готова к следующему этапу, если независимый инженер без устных пояснений может назвать asset, злоупотребление, boundary, контроль и evidence; воспроизвести отрицательную проверку; увидеть однозначный pass или fail; и понять, что именно откатывается. Это критерий полноты записи, а не сертификат безопасности. Для реализации нужен отдельный критерий: тест должен пройти на настоящем handler с разрешённым входом и явно заданным неподписанным входом, а результат должен принадлежать согласованному артефакту проверки.</p>\n<h2>Проверяемые источники</h2>\n<ul><li><a href=\"https://cheatsheetseries.owasp.org/cheatsheets/Threat_Modeling_Cheat_Sheet.html\" target=\"_blank\" rel=\"noopener noreferrer\">OWASP Threat Modeling Cheat Sheet</a> — практическая рамка: модель системы, поиск угроз, меры и проверка.</li><li><a href=\"https://csrc.nist.gov/pubs/sp/800/154/ipd\" target=\"_blank\" rel=\"noopener noreferrer\">NIST SP 800-154, Guide to Data-Centric System Threat Modeling</a> — Initial Public Draft; NIST указывает, что документ планируют финализировать, поэтому его нельзя цитировать как завершённый стандарт.</li><li><a href=\"https://csrc.nist.gov/pubs/sp/800/218/final\" target=\"_blank\" rel=\"noopener noreferrer\">NIST SP 800-218, Secure Software Development Framework v1.1</a> — официальная рамка практик безопасной разработки, а не доказательство корректности конкретного контроля.</li></ul>"
}