Моделирование угроз веб-приложения проводят за пять шагов: нарисовать схему потоков данных с границами доверия, определить, что в системе ценно и кто может ей навредить, перебрать угрозы по каждому элементу схемы, принять по каждой решение и записать его как задачу или тест, затем назначить события, после которых модель пересматривается. Небольшому приложению хватает двух-трёх встреч по паре часов с участием разработчика, аналитика и владельца продукта.
Результат нужен не для отчёта, а для работы: каждая найденная угроза превращается в требование в трекере либо в тест. Если угрозы остались в презентации, моделирование не состоялось. Услуга по проведению такой работы описана на странице «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 недель.