Перейти к содержимому

Модель угроз для интернет-магазина: собираем по STRIDE за один вечер

Модель угроз для интернет-магазина: собираем по STRIDE за один вечер
Время чтения: 11 мин.

В прошлом месяце я получил задание в рамках практической лабораторной работы по ИБ: взять тестовый интернет-магазин и собрать для него модель угроз по методологии STRIDE. На входе — ноль опыта в моделировании и стойкое ощущение, что это «документ на 40 страниц, который никто не читает». На выходе — готовая модель с 14 задокументированными угрозами, 5 из которых критичные, и конкретный план контрмер. Весь процесс занял один вечер — около четырёх с половиной часов. Ниже — пошаговый разбор, как повторить это с нуля.

Зачем интернет-магазину модель угроз

Модель угроз — структурированный документ, который отвечает на три вопроса: что в системе ценного (активы), кто и как может до этого добраться (векторы атак — пути, по которым злоумышленник дотягивается до системы) и что с этим делать (контрмеры). Если проще — список ответов на вопрос «что может пойти не так и насколько это больно».

Интернет-магазин обрабатывает персональные данные покупателей (ФИО, адреса, телефоны), платёжную информацию, хранит каталог товаров и историю заказов. По 152-ФЗ («О персональных данных») оператор, который обрабатывает ПДн (персональные данные), обязан оценивать угрозы их безопасности. Штрафы за утечку ПДн — до 15 млн ₽ за первичное нарушение и до 500 млн ₽ за повторные. Модель угроз здесь не академическая формальность, а рабочий инструмент.

Бизнес-логика атаки: зачем ломают магазины

Мотивация атакующего в e-commerce прямолинейная: платёжные данные продаются на теневых площадках, базы email+пароль идут на credential stuffing (подстановка украденных пар логин-пароль в другие сервисы), а доступ к админ-панели открывает подмену платёжных реквизитов для вывода денег. По данным IBM X-Force Threat Intelligence Index 2025, атаки с использованием действительных учётных данных выросли на 71% за год — e-commerce один из основных источников этих credentials. Это не абстрактная «киберопасность», а конкретная экономика: чем ценнее данные в системе, тем выше интерес к ней.

Как составить модель угроз: дорожная карта

Перед тем как погружаться в шаги — общий план. Построение модели угроз шаг за шагом выглядит так (структура основана на четырёх вопросах Адама Шостака, автора книги «Threat Modeling: Designing for Security»):

  1. Определить активы — что жалко потерять.
  2. Нарисовать DFD (Data Flow Diagram — диаграмму потоков данных) — как данные перемещаются по системе.
  3. Расставить границы доверия — где уровень «доверия» к данным меняется.
  4. Прогнать каждый элемент через STRIDE — шесть категорий угроз.
  5. Приоритизировать — что чинить первым.
  6. Описать контрмеры — конкретные действия с деталями для разработчика.

Что нужно для повторения: браузер (для draw.io или OWASP Threat Dragon), текстовый редактор и базовое понимание клиент-серверной архитектуры — что есть фронтенд, бэкенд и база данных.

Шаг 1 — определяем активы и рисуем DFD-диаграмму потоков данных

Активы тестового магазина

Актив — то, что жалко потерять. В терминологии NIST CSF v2.0 (Cybersecurity Framework — набор рекомендаций NIST по управлению кибербезопасностью) это функция ID.AM-01, Asset Management — инвентаризация того, чем управляет организация. В тестовом интернет-магазине я выделил четыре категории:

  • Данные покупателей — ФИО, email, телефон, адрес доставки. Это ПДн, подпадающие под 152-ФЗ.
  • Платёжные данные — номера карт, токены оплаты. Попадают под стандарт PCI DSS (набор требований к защите данных платёжных карт).
  • Учётные записи — логины и хеши паролей покупателей и администраторов.
  • Каталог и заказы — товарные позиции, цены, статусы заказов. Подмена цены — прямой финансовый ущерб.

DFD — карта движения данных

DFD показывает, как данные перемещаются между компонентами системы. Рисовать можно в draw.io (бесплатный браузерный редактор), OWASP Threat Dragon (бесплатный инструмент с встроенной поддержкой STRIDE) или на маркерной доске — серьёзно, маркер и доска работают не хуже. Для тестового магазина DFD уровня 1 выглядит так:

[Покупатель] --HTTPS--> [Веб-сервер]
                              |
                         [API Backend]
                           /       \
                  [БД PostgreSQL]  [Платёжный шлюз]
                                        |
                                 [Банк-эквайер]

Четыре типа элементов на DFD:

  • Внешние сущности — покупатель (браузер), платёжный шлюз, банк. Находятся за пределами вашей системы.
  • Процессы — веб-сервер, API-бэкенд. Обрабатывают и трансформируют данные.
  • Хранилища — база данных PostgreSQL. Данные в покое.
  • Потоки данных — стрелки между элементами. По ним данные передаются.

На эту диаграмму у меня ушло 20 минут в draw.io. Не нужно рисовать каждый микросервис — достаточно ключевых компонентов, между которыми ходят чувствительные данные. Ожидаемый результат: схема из 5–7 блоков со стрелками, которая помещается на один экран.

Шаг 2 — расставляем границы доверия

Граница доверия (trust boundary) — линия, где уровень доверия к данным меняется. Поверхность атаки (attack surface — совокупность всех точек, через которые атакующий может воздействовать на систему) концентрируется именно здесь, потому что данные переходят из менее контролируемой среды в более контролируемую.

В нашем магазине четыре границы:

  1. Покупатель → Веб-сервер — интернет → DMZ (демилитаризованная зона — сегмент сети между внешним миром и внутренними серверами). Всё от браузера — недоверенный ввод. Без исключений.
  2. Веб-сервер → API Backend — DMZ → внутренняя сеть. Веб-сервер может быть скомпрометирован, поэтому бэкенд не должен доверять ему безоговорочно.
  3. API Backend → БД — приложение → хранилище. Backend имеет прямой доступ к ПДн.
  4. API Backend → Платёжный шлюз — внутренняя сеть → внешний сервис. Платёжные данные покидают периметр.

На DFD границы обозначаются пунктирной линией. В Threat Dragon они добавляются как отдельный элемент — перетаскиваете прямоугольник вокруг группы компонентов. На этот шаг ушло 10 минут.

Если времени мало — моделируйте только пересечения границ доверия. Как отмечает Пранав Хиварекар в разборе STRIDE-процесса, «большинство угроз кластеризуются прямо на границах доверия», и анализ только boundary-crossing покрывает основную массу рисков.

Шаг 3 — анализ угроз интернет-магазина через STRIDE методологию

STRIDE — методология категоризации угроз, разработанная в Microsoft. Каждая буква — категория угрозы, которая нарушает определённое свойство безопасности:

Буква Угроза Нарушаемое свойство
S — Spoofing Подмена идентичности Аутентификация
T — Tampering Модификация данных Целостность
R — Repudiation Отказ от авторства действий Неотказуемость
I — Information Disclosure Утечка информации Конфиденциальность
D — Denial of Service Отказ в обслуживании Доступность
E — Elevation of Privilege Повышение привилегий Авторизация

STRIDE не говорит, «как атаковать». Она даёт чек-лист категорий, которые нужно проверить для каждого элемента и потока данных в системе. Ценность — в полноте: трудно забыть целый класс угроз, когда идёшь по структурированному фреймворку.

Матрица STRIDE по типам элементов

Не все шесть категорий применимы к каждому типу элемента DFD. Это ловушка, в которую я попал: пытался «натянуть» Spoofing на поток данных и потратил 15 минут впустую. Матрица ниже экономит время (по материалам STRIDE-per-element из документации Microsoft):

Элемент DFD S T R I D E
Внешняя сущность (покупатель) Да Нет Да Нет Нет Нет
Процесс (API-бэкенд) Да Да Да Да Да Да
Хранилище (БД) Нет Да Нет Да Да Нет
Поток данных (HTTPS) Нет Да Нет Да Да Нет

Процессы уязвимы ко всем шести категориям — поэтому API-бэкенд обычно самый «горячий» компонент в модели.

Пример: прогоняем API-бэкенд магазина через STRIDE

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

Spoofing. Злоумышленник подбирает или ворует учётные данные администратора через credential stuffing и получает доступ к панели управления заказами, потому что нет многофакторной аутентификации (MFA — дополнительный фактор подтверждения личности помимо пароля: SMS-код, TOTP-приложение, аппаратный ключ). Связь с NIST CSF: PR.AA-01 (управление идентификацией и аутентификацией).

Tampering. Покупатель модифицирует параметр price в запросе POST /api/cart/checkout, снижая стоимость заказа с 15 000 ₽ до 1 ₽, потому что бэкенд доверяет цене от клиента вместо того чтобы брать её из каталога на серверной стороне. Это пример из OWASP Top 10 A04:2021 — Insecure Design (ошибки проектирования — отсутствие контроля на уровне архитектуры, а не баг в коде).

Repudiation. Администратор меняет статус заказа на «возвращён», оформляет возврат средств на подконтрольный счёт и отрицает действие. Работает, потому что система не ведёт журнал аудита с привязкой к учётной записи и IP-адресу.

Information Disclosure. API-эндпоинт /api/users/{id}/profile возвращает в ответе хеш пароля и секрет MFA наряду с публичными полями профиля, потому что сериализатор отдаёт все поля объекта без фильтрации. Прямое попадание в OWASP Top 10 A01:2021 — Broken Access Control (нарушение контроля доступа). По статистике OWASP, 94% приложений содержат ту или иную форму этой проблемы.

Denial of Service. Злоумышленник отправляет тысячи запросов к эндпоинту /api/search?q=... с тяжёлыми regex-паттернами (это называется ReDoS — Regular Expression Denial of Service), вызывая исчерпание CPU на бэкенде, потому что нет rate limiting (ограничения количества запросов в единицу времени). Попадает в OWASP API Security API4:2023 — Unrestricted Resource Consumption.

Elevation of Privilege. Обычный покупатель подставляет ID чужого заказа в запрос GET /api/orders/{id} и получает данные чужого заказа (адрес доставки, телефон), потому что бэкенд проверяет аутентификацию, но не проверяет, принадлежит ли заказ текущему пользователю. Это IDOR (Insecure Direct Object Reference — небезопасная прямая ссылка на объект). По данным safeguard.sh, это самая частая и разрушительная уязвимость API: она обходит аутентификацию целиком, потому что вызывающий уже легитимно авторизован — просто запрашивает не своё.

Таким же способом я прошёл остальные компоненты: веб-сервер, БД, каждый поток данных — но только по применимым категориям из матрицы выше. Итог: 14 задокументированных угроз для всей модели угроз интернет-магазина.

Оценка рисков информационной безопасности: приоритизация угроз

14 угроз — хорошо, но чинить все одновременно невозможно. Для приоритизации рисков я использовал упрощённую шкалу DREAD-lite (облегчённая версия методики Microsoft DREAD). Каждой угрозе выставляются три оценки по шкале 1–3:

  • Impact — насколько больно: 1 = незначительно, 3 = утечка данных или финансовый ущерб.
  • Likelihood — насколько вероятно: 1 = нужен инсайдерский доступ, 3 = эксплуатируется удалённо без аутентификации.
  • Fix effort — сложность исправления: 1 = крупный рефакторинг, 3 = исправление в одну строку.

Пример приоритизации для пяти угроз из нашей модели:

Угроза Impact Likelihood Fix Итого Приоритет
Подмена цены в корзине (Tampering) 3 3 3 9 Критичный
IDOR в заказах (EoP) 3 3 2 8 Критичный
Утечка полей профиля (Info Disclosure) 3 2 3 8 Критичный
DoS через поиск (Denial of Service) 2 3 2 7 Высокий
Нет аудит-лога (Repudiation) 2 2 2 6 Средний

Угрозы с итогом 7+ идут в текущий спринт как P0-задачи. Остальные — в бэклог безопасности. В моём случае 5 из 14 угроз попали в критичную и высокую категорию — все сосредоточены на границах «Покупатель → Веб-сервер» и «API → БД». Не случайно: именно там данные переходят между зонами доверия.

Контрмеры: конкретика вместо «используйте шифрование»

Расплывчатые контрмеры хуже их отсутствия — они создают ложное ощущение, что проблема решена. Фраза «добавьте rate limiting» ничего не значит без порогов, окна и поведения при превышении. Вот примеры контрмер из моей модели — сформулированные так, чтобы разработчик мог реализовать их без дополнительных вопросов:

Подмена цены (Tampering). Цену товара при оформлении заказа берём из таблицы products на стороне сервера по product_id. Значение price из запроса клиента игнорируется. Валидация — серверная, на уровне бэкенда. Как понять, что работает: перехватываете запрос через Burp Suite, меняете поле price — итоговая сумма заказа в БД остаётся прежней.

IDOR в заказах (EoP). На каждый запрос GET /api/orders/{id} добавляется проверка WHERE order.user_id = current_user.id на уровне ORM (Object-Relational Mapping — слой, через который приложение работает с БД). Не полагаемся на то, что клиент запросит только «свои» ID. Проверка: запрос с валидным токеном пользователя A к заказу пользователя B возвращает 403 Forbidden.

DoS через поиск. Rate limiting — 60 запросов в минуту на аутентифицированного пользователя, скользящее окно, на уровне API-шлюза. Для неаутентифицированных — 20 запросов/минуту по IP. При превышении — ответ 429 Too Many Requests.

Утечка полей профиля (Info Disclosure). Сериализатор API явно перечисляет возвращаемые поля (whitelist-подход): name, email, avatar_url. Поля password_hash и mfa_secret исключены из всех ответов. Проверка: в ответе API на запрос профиля отсутствуют чувствительные поля — проверяем через curl или Postman.

Инструменты для threat modeling и затраты времени

За вечер я попробовал два инструмента для построения модели угроз:

draw.io (diagrams.net) — бесплатный, работает в браузере. DFD рисуется за 15–20 минут. Минус: нет встроенной STRIDE-логики, угрозы документируются отдельно в Markdown-файле или таблице. Для первого раза — более чем достаточно.

OWASP Threat Dragon — тоже бесплатный, тоже браузерный. Позволяет рисовать DFD и прикреплять угрозы прямо к элементам диаграммы. Удобен, когда модель нужно показывать команде.

Есть ещё Microsoft Threat Modeling Tool — десктопное решение, которое генерирует угрозы автоматически по шаблонам. Для учебного упражнения избыточно, но в enterprise-среде экономит время на больших системах.

Инструмент вторичен. Модель угроз, нарисованная маркером на доске и сфотографированная, ценнее красивого PDF, который никто не обновляет.

Мой расклад по времени:

Этап Время
Определение активов 15 мин
DFD + границы доверия 30 мин
STRIDE-анализ всех элементов 2 часа
Приоритизация DREAD-lite 30 мин
Описание контрмер 1 час
Итого ~4.5 часа

Для простого CRUD-приложения (создание, чтение, обновление, удаление записей) без сложной мультитенантности — 2 часа реалистичный срок.

Когда я закончил модель, первое ощущение — «почему казалось, что это сложно?» STRIDE не требует сертификации, специализированного ПО или многолетнего опыта в пентесте. Нужны draw.io, понимание того, как данные ходят по системе, и 4–5 часов сосредоточенной работы.

Но есть вещь, о которой мало говорят. Модель угроз — одноразовое упражнение ровно до первого изменения архитектуры. Добавили эндпоинт для мобильного приложения — модель устарела. Подключили CDN — новая граница доверия. Перевели платёжный шлюз — новый поток данных. На практике 90% моделей угроз превращаются в артефакт, который сделали ради галочки и забыли. А потом удивляются, что IDOR вылез в продакшене через полгода, когда джуниор добавил «быстрый эндпоинт» мимо middleware авторизации.

Модель работает, только если она живая: обновляется при каждом изменении дизайна, хранится рядом с кодом (а не в Confluence, куда никто не ходит) и каждая угроза — это тикет в бэклоге с владельцем. Без этого — 40 страниц макулатуры.

Я убеждён, что первую модель угроз нужно делать руками, без автоматизации. Автоматические генераторы выдают красивые отчёты, но не учат думать о системе как атакующий. А это и есть навык, который остаётся. Если хочется наработать его системно, а не по разрозненным статьям — на IB Basics эту логику разбирают от «как думать», а не «запомните терминологию».

Эту тему и смежные навыки разбирают на практике в курсе «Специалист по тестированию на проникновение» Codeby Academy.