Моделирование угроз веб-приложения проводят за пять шагов: нарисовать схему потоков данных с границами доверия, определить, что в системе ценно и кто может ей навредить, перебрать угрозы по каждому элементу схемы, принять по каждой решение и записать его как задачу или тест, затем назначить события, после которых модель пересматривается. Небольшому приложению хватает двух-трёх встреч по паре часов с участием разработчика, аналитика и владельца продукта.

Результат нужен не для отчёта, а для работы: каждая найденная угроза превращается в требование в трекере либо в тест. Если угрозы остались в презентации, моделирование не состоялось. Услуга по проведению такой работы описана на странице «Threat modeling для веб-приложений», здесь только порядок и таблицы, по которым команда справится сама.

Коротко. Пять шагов: схема, активы и нарушители, перебор угроз по элементам, решение по каждой, проверка и пересмотр. Схему рисуют те, кто знает систему на самом деле, а не по документации. Угроза без решения и владельца в реестре не считается найденной.

Что подготовить до первой встречи

Хорошая сессия начинается за несколько дней до неё. Нужны три вещи: люди, материалы и правила.

ЧтоСоставЗачем
УчастникиРазработчик или архитектор, аналитик, владелец продукта, тот, кто эксплуатирует систему; для приложения с платежами или персональными данными ещё ответственный за безопасностьКаждый видит свою часть: разработчик знает код, администратор знает, как всё развёрнуто на самом деле, владелец знает цену потери
МатериалыОписание ролей, список интеграций, схема развёртывания, перечень типов данныхНе дать встрече уйти в вопросы «а что вообще у нас есть»
ИнструментДоска или draw.io; схемы как текст (Mermaid, PlantUML), если хотите хранить их в репозиторииСхема должна быть редактируемой после встречи, а не фотографией доски
Роль ведущегоОдин человек задаёт вопросы и следит за порядком, другой записываетТот, кто пишет, не успевает думать, и наоборот

Правила сессии

  • Ищем угрозы, а не виноватых: «здесь можно подменить идентификатор» не означает претензию к автору кода.
  • Записываем всё, не споря о серьёзности на месте. Оценка идёт отдельным шагом.
  • Не решаем, как чинить. Решение принимается позже, иначе встреча превращается в проектирование.
  • Схема отвечает на вопрос «как есть», а не «как задумано». Расхождение само по себе находка.

Шаг 1. Схема потоков данных

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

ЭлементКак рисуемВопрос к немуПример в условном сервисе
Внешний участникПрямоугольник вне системыКто он и можем ли мы ему доверятьСотрудник партнёра, администратор, платёжный провайдер
ПроцессКруг или скруглённый блокКакую логику выполняет и от чьего имениПриложение, обработчик загрузки, задача обмена с учётом
ХранилищеДве параллельные линииЧто там лежит и кто имеет доступ в обход приложенияБаза, хранилище файлов, очередь
Поток данныхСтрелка с подписьюЧто передаётся и как защищено по путиЗагрузка файла, вызов API учётной системы, письмо
Граница доверияПунктирная линияЧто меняется при переходе: права, сеть, владелецИнтернет и сервер, сервер и база, наш контур и контур заказчика

Границы доверия — самое важное на схеме. Угрозы концентрируются там, где данные переходят от менее доверенного участника к более доверенному. Начинайте с общей схемы на одной странице, затем раскрывайте один-два самых рискованных процесса. Схема, на которой помещается только половина системы, лучше схемы, которую никто не читает.

Когда схема готова, разработчик проверяет её по коду и конфигурации, а администратор сверяет с реальным развёртыванием. Обычно после этого появляются пара забытых потоков: выгрузка для аналитики, служебный доступ подрядчика, резервная копия на отдельном сервере. Это первая польза от встречи.

Шаг 2. Активы и нарушители

Угроза имеет смысл только относительно того, что вы защищаете, и того, кто на это покушается. Сначала запишите активы: персональные данные клиентов, договорные цены, права подтверждать платежи, ключи доступа к другим системам, журнал действий. У каждого указывается владелец и последствия потери: разглашения, подмены, недоступности.

Затем нарушители. Не нужно придумывать сложные образы; достаточно пяти-шести типов с названным уровнем доступа:

КтоЧто у него естьЧего может добиватьсяЧто из этого следует
Аноним из интернетаТолько публичные адресаПодбор паролей, перегрузка, использование открытых функцийЗащита входа, ограничения частоты, отсутствие лишнего на публичных адресах
Зарегистрированный клиентСвоя учётная запись и свои данныеУвидеть чужое, подменить идентификатор, повысить себе праваПрава на каждый запрос и тесты изоляции клиентов
Недобросовестный сотрудник партнёраЛегитимный доступ к данным партнёраВыгрузить базу, отменить заказы, изменить реквизитыОтдельные права на опасные действия, журнал, подтверждения
Сотрудник поддержкиШирокий доступ для помощи клиентамПросматривать лишнее, входить от имени клиентаВход от имени клиента с записью, минимум прав
Подрядчик или администраторСлужебный доступ к серверам и базеЧитать данные в обход приложения, оставить закладкуРаздельные учётные записи, журнал администраторов, шифрование чувствительных полей
Скомпрометированная интеграцияКлюч доступа от учётной системы или почтового сервисаПодать поддельные данные или читать лишнееМинимальные права ключа, проверка входящих данных

Не включайте в модель всё подряд. Если для вашего сервиса государственный уровень противника не оправдан, так и запишите: «не рассматриваем», с причиной. Это тоже решение, и его потом можно пересмотреть.

Шаг 3. Перебор угроз по элементам схемы

Перебирать угрозы можно по методу STRIDE: шесть категорий (подмена, изменение данных, отказ от действия, раскрытие информации, отказ в обслуживании, повышение привилегий). Чтобы не гонять все шесть по каждому элементу, используют правило «STRIDE по элементам»: у разных типов элементов уместны разные категории.

Тип элементаПодменаИзменение данныхОтказ от действияРаскрытиеОтказ в обслуживанииПовышение прав
Внешний участникданетданетнетнет
Процессдададададада
Хранилищенетдадля журналовдаданет
Поток данныхнетданетдаданет

Для каждой пары «элемент — категория» задайте один вопрос и запишите ответы, даже если ответ «нет угрозы». Вот вопросы, которые работают в большинстве веб-приложений:

  • Подмена. Как система убеждается, что это тот, за кого себя выдаёт? Что будет, если украсть токен или подделать вызов?
  • Изменение. Что нельзя менять пользователю, но можно, если подставить своё значение в запрос?
  • Отказ от действия. Если этот человек скажет «я этого не делал», что в журнале докажет обратное?
  • Раскрытие. Что попадёт в ответ, в ошибку, в журнал и в резервную копию, чего там быть не должно?
  • Отказ в обслуживании. Какой запрос самый тяжёлый и можно ли отправлять его бесконечно?
  • Повышение прав. Что делает администратор и есть ли хоть один путь вызвать это обычному пользователю?

Дополнение: злоупотребление функцией

STRIDE хорошо ловит технические угрозы и хуже бизнес-логику. Поэтому после перебора добавьте второй проход: возьмите каждую функцию и спросите, как её использовал бы недобросовестный пользователь. Промокод применяется дважды, отмена оплаченного заказа возвращает деньги без проверки, приглашение в организацию уходит на чужую почту. Такие сценарии и становятся основой для тестов.

Шаг 4. Решение по каждой угрозе и запись

На этом шаге собранный список превращается в работу. По каждой угрозе выбирается одно из четырёх решений: снизить (добавить меру), передать (переложить на провайдера или страховку), принять (оставить осознанно) или избежать (убрать функцию). Серьёзность оцениваем качественно: кто может это сделать, что получит, насколько трудно. Придуманные баллы создают видимость точности, которой у проектных угроз нет.

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

Плохая записьХорошая записьПочему она лучше
Обеспечить безопасность загрузки файловПринимаются только перечисленные типы и ограниченный размер; файл хранится вне каталога сайта, имя заменяется идентификатором; отдача по ссылке с проверкой правПроверяется тестом: загружаем запрещённый тип, смотрим результат
Защитить вход от подбораПосле серии неудачных попыток вход замедляется по учётной записи и по адресу; пользователю приходит уведомлениеПонятно, что сделать и как проверить
Не раскрывать лишнее в ошибкахПользователю возвращается сообщение с идентификатором ошибки, подробности пишутся только в журналМожно сравнить ответ системы с записью
Учесть риск подмены вебхукаВходящие вызовы платёжного провайдера принимаются только с проверкой подписи; без неё возвращается отказТест подаёт вызов без подписи и ждёт отказ

В реестр на каждую угрозу попадают: описание, категория, затронутый актив, серьёзность, решение, владелец, срок и ссылка на задачу. Угроза без владельца и решения считается найденной только наполовину.

Шаг 5. Проверка и пересмотр

Модель, которую не проверяли, остаётся предположением. Проверка складывается из трёх действий:

  • Требования в приёмку. Сформулированные меры попадают в критерии приёмки задач, а не лежат отдельным документом.
  • Сценарии в тесты. Каждый сценарий злоупотребления превращается в автоматический тест или пункт проверки перед выпуском. Проверка прав, например, прогоняется из-под каждой роли.
  • Проверка кода. Самые серьёзные меры проверяет человек на ревью. Страница про ревью кода на безопасность описывает, как мы это делаем.

Пересмотр привязывается к событиям, а не к календарю. Хорошие поводы: новая интеграция, новая роль, новый тип данных, выход наружу, смена способа входа, приём платежей. Запишите этот список в самом документе. Тогда пересмотр становится пунктом в процессе изменений: аналитик видит, что задача подходит под один из признаков, и добавляет в неё обновление модели.

Частые ошибки

Почти все неудачные попытки моделирования угроз повторяют одни и те же сценарии:

ОшибкаК чему приводитКак избежать
Сделали один раз и положили в папкуЧерез полгода модель описывает другую системуСписок событий для пересмотра и владелец документа
Слишком подробная схема на первой встречеПоловина времени ушла на рисование, до угроз не дошлиНачинать с одной страницы, раскрывать только рискованные процессы
Участвуют только разработчикиНе видны бизнес-последствия и злоупотребления функциямиПозвать аналитика и владельца продукта
Угрозы записаны без решенийРеестр превращается в список страховНе закрывать встречу, пока у каждой угрозы нет решения и владельца
Оценка баллами, которые никто не может объяснитьСпоры о цифрах вместо решенийКачественная оценка по трём вопросам
Модель путают с аудитомЖдут отчёта о найденных ошибках в кодеОбъяснить участникам, что это разбор замысла, а ошибки кода ищут другими способами

Автоматические проверки кода и зависимостей не заменяют модель и не заменяются ею. О том, как они дополняют друг друга, рассказывает статья «SAST, DAST, SCA: в чём разница».

Когда справитесь сами, а когда нужна помощь

Собственными силами модель проводят там, где есть человек, готовый вести встречу, и команда, которая может спокойно посмотреть на собственный замысел. Помощь снаружи полезна в трёх случаях:

  • Нет опыта. Первую модель удобнее провести вместе с тем, кто знает типовые угрозы и умеет задавать неудобные вопросы.
  • Нужен документ для клиента. Отчёт со стороны воспринимается серьёзнее, чем самооценка.
  • Система сложная. Много ролей, организации внутри организаций, несколько интеграций. Модель такой системы требует нескольких встреч и аккуратного реестра.

Помощь снаружи не заменяет участия вашей команды: никто лучше неё не знает, как система работает на самом деле. Если вы решите делать модель сами, в статье достаточно шагов и таблиц, чтобы начать.

Что делаем мы и с чего начать

Берём моделирование угроз одного приложения: 200 000 ₽ и 2–3 недели, если у приложения один-два основных процесса и одна-две связанные системы, 350 000 ₽ и 3–4 недели при нескольких интеграциях. На выходе схема потоков данных, реестр угроз с решениями и владельцами, требования для трекера и сценарии злоупотребления для тестов. Сумма вычитается из первого этапа, если продолжаете с нами, а документами можно пользоваться и без нас.

Дальше, если нужно, пилот за 150 000–400 000 ₽ и 2–8 недель: перенос требований в ваш трекер, тесты и проверка самых серьёзных мер в коде. Работаем по схеме и описанию, боевые системы не атакуем, аттестацию и модель по формам регулятора для государственных систем не проводим, лицензии ФСТЭК у нас нет. Цены и сроки собраны на странице «Тарифы», описание услуги — на странице «Threat modeling для веб-приложений».

Частые вопросы

Сколько времени занимает моделирование угроз?

Небольшому приложению хватает двух-трёх встреч по паре часов плюс работа между ними: подготовка материалов, оформление реестра, перенос требований в трекер. Для сложной системы с несколькими интеграциями это три-четыре недели с участием нескольких людей.

Кого позвать на встречу?

Разработчика или архитектора, аналитика, владельца продукта и того, кто эксплуатирует систему. Для приложений с платежами и персональными данными добавьте ответственного за безопасность. Все вместе нужны только на сессиях по угрозам, схему можно готовить вдвоём.

Что такое границы доверия?

Линии на схеме, где данные переходят от менее доверенного участника к более доверенному: из интернета на сервер, из приложения в базу, из вашего контура во внешнюю систему. Большая часть угроз находится на этих границах.

Чем STRIDE отличается от OWASP Top 10?

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

Нужны ли специальные инструменты?

Нет, хватит доски или draw.io и таблицы. Если хочется хранить модель рядом с кодом, подойдут схемы как текст (Mermaid, PlantUML) или инструменты вроде OWASP Threat Dragon. Инструмент вторичен, главное порядок и наличие решения по каждой угрозе.

Как оценивать серьёзность без баллов?

Тремя вопросами: кто может это сделать, что он получит, насколько это трудно. Если достаточно изменить число в адресе, а получит он чужие данные, угроза идёт первой. Для оценки веса потери решает владелец продукта, а не разработчик.

Нужно ли делать модель угроз, если есть сканер?

Да, если приложение хранит чужие данные или принимает платежи. Сканер проверяет реализацию, а отсутствующую защиту по замыслу он не увидит: бессрочную ссылку для сброса пароля или массовую отмену заказов сотрудником партнёра код выполняет правильно.

Сколько стоит, если заказать у вас?

Модель одного приложения — 200 000 ₽ за 2–3 недели, при нескольких интеграциях — 350 000 ₽ за 3–4 недели, сумма вычитается из первого этапа. Пилот с переносом требований в трекер и проверкой мер — 150 000–400 000 ₽ за 2–8 недель.