Внешний пентест микросервисной платформы может закончиться чистым отчётом — и при этом почти ничего не сказать о том, где на самом деле живут риски. Причина не в качестве тестировщиков, а в устройстве системы: в микросервисах решения о доступе принимаются не на одной границе, а в десятках мест, многие из которых снаружи не видны.
Начнём с условного примера. Он придуман для иллюстрации, не описывает реального клиента или инцидента, и все совпадения случайны.
Условная платформа, которая прошла внешний тест
Представим B2B-сервис учёта заказов. Снаружи — API-шлюз: он проверяет токен пользователя, роль и отсекает лишнее. За шлюзом работают сервис заказов, сервис платежей, обработчик уведомлений и фоновый обработчик возвратов, который читает события из очереди. Между сервисами включён mTLS, внутренние адреса не опубликованы.
Внешний пентест проверил публичные эндпоинты и не нашёл ничего серьёзного. Затем команда согласовала второй этап: проверку внутренних путей из тестового окружения, с выделенной сервисной учётной записью и двумя тестовыми арендаторами. Картина изменилась.
Сервис заказов отвечал на прямой вызов в обход шлюза и брал идентификатор арендатора из заголовка, который обычно проставлял шлюз. Обработчик возвратов принимал событие «возврат одобрен» от любого сервиса, имевшего доступ к топику, и не сверял, к какому арендатору относится заказ. А при повторной доставке того же события возврат создавался дважды.
Ни одна из этих проблем не видна с периметра. И ни одну не предотвратил mTLS: он честно подтверждал, что вызов пришёл от сервиса внутри сети, но не отвечал на вопрос, имеет ли этот сервис право на эту операцию с этим объектом. Об этом разрыве — между «кто звонит» и «что ему можно» — и пойдёт речь.
Почему периметр перестал совпадать с приложением
В монолите вопрос «что входит в пентест» обычно сводится к одному приложению и его входам. Микросервисная архитектура заменяет одну границу множеством маленьких. Каждый сервис публикует интерфейс, чаще всего по HTTP или gRPC, и зависит от шлюзов, сервиса идентификации и соседей.
HTTP создавался для браузеров и серверов, но сегодня тот же протокол переносит и межмашинные вызовы, и программный доступ к API. В этом корень проблемы: пользовательский запрос и внутренний вызов выглядят на проводе почти одинаково, хотя допущения о доверии к ним принципиально разные. Пользователю никто не верит на слово. Соседнему сервису часто верят полностью.
Отсюда практический вывод. Тест, который касается только публичной точки входа, проверяет одну из многих границ — обычно самую защищённую. Остальные остаются за кадром.
Две идентичности в каждом вызове
Почти каждый внутренний запрос несёт два ответа на вопрос «кто это». Первый — идентичность сервиса: какой компонент сделал вызов. Второй — идентичность пользователя или арендатора, от чьего имени этот вызов совершается. Путаница между ними — один из самых частых источников слабостей.
mTLS отвечает на вопрос «кто звонит», а не «можно ли»
Взаимный TLS даёт сервисам возможность установить, с кем они разговаривают, и защищает передаваемые данные от чтения и подмены. Это полезный и часто необходимый слой. Но он работает на уровне транспорта. Сертификат подтверждает, что звонит сервис заказов, — и ничего не говорит о том, вправе ли этот вызов читать счёт конкретного клиента.
У mTLS есть и собственные операционные вопросы, которые стоит включить в проверку: как выпускаются и доставляются ключи, как отзываются скомпрометированные сертификаты, как часто и насколько безболезненно идёт ротация. Ответы на них — часть картины доверия, а не формальность.
Если межсервисная аутентификация построена на токенах, появляется похожий компромисс. Проверка токена через центральный сервис позволяет замечать отозванные токены, но добавляет задержку. Локальная проверка по открытому ключу быстрее, но отозванный токен может некоторое время продолжать работать. Профильный материал OWASP по безопасности микросервисов предлагает выбирать режим по критичности запроса. Для пентестера это повод проверить, какой режим выбран для действительно чувствительных операций.
Как контекст пользователя попадает внутрь
Есть миф, что раз HTTP «не хранит состояние», то и серверных сессий быть не должно. Это неточно. Протокол не связывает два запроса между собой, но приложение вправе хранить сессию на сервере и связывать запросы через cookie или токен. В микросервисах важен не выбор между сессиями и токенами, а то, как контекст пользователя переезжает от периметра внутрь.
Встречаются три подхода. Шлюз пересылает внешний токен как есть. Шлюз обменивает его на внутренний токен с более узкими правами. Или доверенный компонент на периметре выпускает собственное подписанное утверждение о пользователе. У каждого варианта свои слабые места, и проверять нужно не только наличие подписи.
Подпись защищает целостность утверждения: никто не изменил его по дороге. Но она не даёт доступ к ресурсу. Сервис, получивший корректно подписанное «это пользователь из арендатора А», всё ещё должен сам решить, можно ли этому пользователю то, о чём он просит. Отдельно стоит проверить, может ли вызывающий сервис подставить контекст другого пользователя, — как в нашем условном примере с заголовком арендатора.
Авторизация объекта и арендатора на каждом шаге
Шлюз хорошо умеет грубые проверки: есть ли у запроса действующий токен, есть ли у пользователя нужная роль, разрешён ли этот маршрут. Но он почти никогда не знает, кому принадлежит заказ номер такой-то и в каком состоянии он находится. Эти знания живут в сервисе, который владеет данными.
Поэтому позиция OWASP сформулирована недвусмысленно: каждый сервис должен сам контролировать доступ к своим защищённым операциям, включая внутренние вызовы, а проверки на шлюзе лишь дополняют этот контроль. Правила уровня объекта, арендатора и бизнес-логики исполняются там, где есть контекст.
Для проверки это означает простой, но трудоёмкий вопрос к каждому чувствительному действию. Откуда сервис берёт идентификатор арендатора — из проверенного контекста или из тела запроса? Сверяет ли он, что объект принадлежит этому арендатору? Повторяет ли проверку, когда тот же объект запрашивает другой внутренний сервис? В многоарендных продуктах ответы на эти вопросы определяют, насколько надёжна изоляция клиентов, — подробнее об этом в материале о пентесте для SaaS-компаний.
Обход шлюза: когда внутренний адрес оказывается доступен
Самая неприятная комбинация выглядит так: вся авторизация сосредоточена на шлюзе, а сервис за ним доступен напрямую. Достаточно одного неверно настроенного правила сети, отладочного порта или забытого балансировщика, и все проверки периметра перестают иметь значение.
Рекомендация OWASP здесь двойная: шлюз должен отсекать неавторизованные входящие запросы, а архитектура — не допускать прямого доступа в обход этих проверок. Пентест должен проверить обе половины. Принимает ли сервис запросы без шлюза? Доверяет ли он заголовкам, которые должен ставить только шлюз? Что произойдёт, если такой заголовок придёт снаружи?
Есть и тонкий вариант той же проблемы. Шлюзы, прокси, переходы между HTTP/1.1, HTTP/2 и WebSocket — это места, где разные компоненты могут по-разному разбирать один и тот же запрос. Если шлюз видит одно, а сервис за ним — другое, политика применяется не к тому запросу, который реально исполнился. Проверять такие расхождения стоит аккуратно, в согласованном окне и без влияния на продуктив.
Сетевая доступность при этом никогда не означает разрешения. Даже если тестировщик видит внутренний адрес, обращаться к нему можно только в рамках письменно согласованного контура. Если часть доверия обеспечивается платформой оркестрации, полезно связать проверку приложений с аудитом безопасности Kubernetes: сетевые политики и сервисные учётные записи там напрямую влияют на то, кто кого может вызвать.
Очереди, события и повторы: асинхронная половина системы
Многие команды тщательно защищают синхронные API и почти не думают о фоновой части. Между тем в типичной платформе значительная доля бизнес-операций завершается не в ответ на HTTP-запрос, а в обработчике, который прочитал сообщение из очереди.
У фонового обработчика нет пользователя перед глазами. Он видит сообщение и должен решить, верить ли ему. Ключевые вопросы те же, что и для синхронных вызовов, но ответы на них часто забыты. Кто вправе публиковать в этот топик? Несёт ли событие контекст арендатора, и проверяет ли обработчик, что объект действительно принадлежит этому арендатору? Можно ли опубликовать событие, которое приведёт к операции, недоступной тому же сервису через API?
Повторные запросы и идемпотентность
Многие брокеры сообщений и шаблоны интеграции гарантируют доставку «как минимум один раз». Это нормально и даже желательно для надёжности. Но тогда каждая операция, которая может прийти повторно, должна быть идемпотентной: второй экземпляр события «возврат одобрен» не должен порождать второй возврат.
То же касается синхронных повторов. Клиент или шлюз может повторить запрос по таймауту, пользователь — нажать кнопку дважды. Проверка должна показать, что сервис распознаёт повтор по ключу идемпотентности или по состоянию объекта и не выполняет денежную или необратимую операцию второй раз. Делать это стоит на тестовых данных и с заранее согласованным объёмом.
Согласованность бизнес-операции между сервисами
Операция «оформить заказ» в микросервисах часто растянута на несколько шагов: резерв товара, списание, подтверждение, уведомление. Если один шаг упал, система откатывает предыдущие компенсирующими действиями. Именно на стыках таких шагов появляются состояния, которых бизнес не планировал: заказ подтверждён, а оплата не прошла; возврат проведён, а заказ остался активным.
Это уже территория логических уязвимостей. Автоматический сканер вряд ли их найдёт, потому что каждый отдельный запрос выглядит легитимно. Как строить такую проверку и что требовать от подрядчика, мы разбирали в статье о тестировании бизнес-логики.
Карта доверия: что проверять и какие доказательства просить
Сведём всё сказанное в одну таблицу. Она пригодится и при планировании работ, и при чтении отчёта.
Листайте таблицу по горизонтали
| Зона доверия | Типичное допущение | Что проверить | Какое доказательство запросить |
|---|---|---|---|
| Шлюз и периметр | Всё опасное отсекается на входе | Принимают ли сервисы запросы в обход шлюза и доверяют ли его заголовкам | Запросы напрямую к сервису и ответ с тем же решением, что через шлюз, или с отказом |
| Межсервисный вызов | Раз есть mTLS, вызов легитимен | Отличает ли сервис вызывающих и ограничивает ли операции по их роли | Матрица «какой сервис что может вызвать» и пример отказа для неразрешённого вызывающего |
| Контекст пользователя | Внутренний заголовок или токен нельзя подменить | Может ли вызывающий сервис подставить чужого пользователя или арендатора | Попытка подмены контекста в тестовом окружении и зафиксированный отказ |
| Объект и арендатор | Шлюз уже проверил права | Сверяет ли сервис владельца объекта при каждом доступе, включая внутренний | Пары запросов от двух тестовых арендаторов к одному объекту с разными результатами |
| Очереди и события | Сообщения публикуют только «свои» | Кто может публиковать, проверяет ли обработчик арендатора и состояние объекта | Права на топики и пример отклонённого события с чужим объектом |
| Повторы и согласованность | Повтор безвреден, сбои редки | Идемпотентность чувствительных операций и состояния после частичного сбоя | Повторная доставка на тестовых данных и итоговое состояние объектов |
Главное в правой колонке: доказательство — это воспроизводимое наблюдение, а не утверждение «проверено». Ответ «уязвимостей не выявлено» без описания, какие пути и с какими учётными записями проверялись, мало что говорит о системе.
Ниже — та же логика в виде схемы прохождения запроса.
- Вход через периметрШлюз аутентифицирует пользователя и отсекает явно неразрешённые запросы, но не знает, кому принадлежат объекты.
- Передача контекстаСервис получает подтверждение, кто его вызвал, и проверяемый контекст пользователя и арендатора, который нельзя подменить по дороге.
- Решение в сервисеВладелец данных сам проверяет право на конкретный объект и операцию, даже если вызов пришёл от доверенного соседа.
- Асинхронное продолжениеОбработчик события заново сверяет издателя, арендатора и состояние объекта и безопасно переносит повторную доставку.
- След и корреляцияКаждый шаг пишет журнал с общим идентификатором цепочки, чтобы решение о доступе можно было восстановить и проверить.
Как спланировать проверку и не утонуть в сервисах
NIST SP 800-115 выделяет планирование, выполнение и действия после выполнения оценки. Для микросервисного проекта это можно развернуть в практическую последовательность: согласовать проверку, провести тесты, проанализировать находки, организовать устранение и ретест. Документу много лет, поэтому разумно брать из него дисциплину процесса, а не архитектурные рецепты.
Планирование начинается с реестра. Нужен список сервисов, их владельцев, интерфейсов и чувствительности данных, разделённый на периметральные и внутренние пути. Отдельно — карта асинхронных каналов: какие топики и очереди есть, кто в них пишет и кто читает. Без этого любой объём работ будет случайным.
Затем — письменное разрешение. В нём перечислены сервисы, среды, учётные записи и временные окна, согласованы условия остановки и контакт для эскалации, если что-то пойдёт не так. Для проверки авторизации понадобятся как минимум две тестовые учётные записи в разных арендаторах и, если это предусмотрено правилами, сервисная учётная запись внутри тестового контура.
Глубоко проверить каждый сервис удаётся редко, а один периметр упускает внутренние сбои доверия. Разумный компромисс — тщательно проверить периметр и слой идентификации, а внутренние сервисы выбирать прицельно. Выборку стоит взвешивать по двум признакам: насколько чувствительные данные обрабатывает сервис и сколько соседей ему доверяет. Сервис, которому верят все, — самый ценный кандидат.
Анализ при этом важнее, чем кажется. Незначительная слабость в одном сервисе может стать серьёзной только в сочетании с доверием, которое ему оказывает другой. Отчёт должен показывать такие цепочки, а не только список отдельных дефектов.
Если вы готовите такую проверку, контур удобнее обсуждать не перечнем адресов, а картой доверия: какие пути идут через шлюз и какие в обход него, какие очереди, какие арендаторы и учётные записи. С такой картой можно прийти к команде Pentest.red и вместе подготовить контур пентеста, чтобы до начала работ договориться, какие пути проверяются и в каком виде вы получите доказательства.
Что ещё проверить внутри каждого сервиса
Доверие и авторизация — центр темы, но не вся она. Сервисы, которые формируют команды, запросы к базе или обращения к другим сервисам из входных данных, нуждаются в проверке на внедрение. Важно, что это касается и данных, пришедших от внутренних соседей: «внутреннее» не значит «очищенное».
Для расстановки приоритетов полезны открытые каталоги. Список CWE Top 25 от MITRE помогает связывать находки с первопричинами, а OWASP Top 10 2025 удобен, чтобы объяснять категории риска руководству. Они не заменяют анализ конкретной архитектуры, но делают отчёт сопоставимым во времени.
Ответы сервисов — тоже материал для анализа. Разнобой в кодах состояния и телах ошибок между сервисами может раскрывать внутреннюю топологию. Квалифицировать это как утечку стоит только тогда, когда ответы действительно выдают чувствительные сведения, иначе отчёт засоряется шумом.
Наконец, журналирование. Если сервисы не передают по цепочке общий идентификатор вызова, восстановить, кто и почему получил доступ к объекту, почти невозможно. Многие внутренние API устроены как обычные REST-интерфейсы, и для них подходит методика из нашей статьи об оценке безопасности REST API.
Какие доказательства требовать в отчёте
Хороший отчёт о пентесте микросервисов отвечает на два вопроса: что именно было проверено и что будет считаться исправлением. Вторая таблица помогает отличить сильное доказательство от слабого.
Листайте таблицу по горизонтали
| Утверждение в отчёте | Сильное доказательство | Чего недостаточно | Как понять, что исправлено |
|---|---|---|---|
| Сервис недоступен в обход шлюза | Зафиксированные попытки прямого обращения из разрешённых точек сети и их результат | Схема сети без проверки на практике | Повтор тех же попыток после изменения даёт отказ |
| Межсервисная аутентификация работает | Отказ при вызове от неразрешённого сервиса или без учётных данных | Факт включения mTLS в конфигурации | Неразрешённый вызывающий получает отказ на уровне операции |
| Арендаторы изолированы | Пары запросов от разных тестовых арендаторов к одним и тем же объектам | Проверка от одной учётной записи | Чужой объект недоступен по всем проверенным путям, включая внутренние |
| Повторы безопасны | Повторная доставка тестового события и итоговое состояние данных | Ссылка на наличие очереди с подтверждениями | Повтор не меняет итог операции |
| События авторизованы | Права на публикацию и пример отклонённого события | Описание того, как «должно работать» | Событие с чужим объектом отклоняется и попадает в журнал |
От находки к проверяемому требованию
Многие отчёты описывают найденное, но не определяют, что значит «исправлено». Здесь помогает OWASP ASVS: стандарт задаёт требования к верификации безопасности приложений и рекомендует ссылаться на них с указанием версии, например v5.0.0-1.2.5, потому что нумерация между версиями может меняться. Списки требований публикуются в машиночитаемых форматах, так что их легко завести в трекер.
Практичный подход — назначить целевой уровень ASVS каждому сервису с учётом чувствительности данных и открытости, а пентест использовать как выборочную проверку того, выполняются ли требования на деле. После исправлений проверка повторяется по тому же требованию. Как организовать такой повтор и что считать закрытием, подробно описано в материале о проверке устранения уязвимостей.
Что меняется в процессах, а не только в коде
Результаты проверки должны влиять не только на очередь исправлений, но и на проектные решения. Инициатива CISA Secure by Design настаивает, что безопасность — бизнес-требование, а не дополнительная опция. Для микросервисов это переводится в конкретные решения по умолчанию: аутентификация между сервисами включена всегда, авторизация на уровне объекта вынесена в общую проверенную библиотеку или политику, журналы ведутся единообразно и с идентификатором цепочки.
Рамка NIST Cybersecurity Framework 2.0 помогает объяснить руководству объём, периодичность и стоимость таких изменений на привычном языке управления рисками. А для сервисов, которые выпускаются часто, разумно сочетать периодические ручные проверки с автоматическими тестами авторизации в конвейере: регрессия «сервис снова доверяет заголовку» должна ловиться до релиза. Правильный баланс зависит от частоты выпусков и готовности бизнеса к риску.
Чего пентест микросервисов не докажет
Важно честно понимать пределы метода. Пентест — это выборка. Он показывает, как система вела себя на проверенных путях, с проверенными учётными записями и в проверенной версии. Он не доказывает отсутствие уязвимостей во всех сервисах и не заменяет моделирование угроз и ревью архитектуры.
Ни один из общих стандартов — WSTG, ASVS, NIST SP 800-115 — не написан специально под микросервисы. Профильные рекомендации OWASP по микросервисам полезны, но и они описывают паттерны, а не готовый тест-план. Остальное — профессиональное суждение, которое должно быть видно в отчёте: почему выбраны именно эти сервисы, какие пути не проверялись и почему.
Наконец, выводы устаревают вместе с архитектурой. Новый сервис, новый топик или изменение маршрутизации на шлюзе могут открыть путь, которого на момент проверки не было.
С чего начать
Если свести статью к одному правилу, оно будет таким: каждый сервис, который владеет данными или совершает значимое действие, должен сам решать, разрешена ли операция над конкретным объектом, — независимо от того, кто его вызвал и как этот вызов был защищён по дороге. mTLS, шлюз и подписанные токены нужны, но они отвечают на другие вопросы.
Практически начать стоит с карты: сервисы, их владельцы, синхронные и асинхронные пути, точки, где принимается решение о доступе. Затем выбрать самые доверенные и самые чувствительные узлы и проверить их вместе с периметром.
Если хотите обсудить такую проверку с Pentest.red, приходите с этой картой и с ожиданиями к результату: какие пути доверия должны быть проверены, какие доказательства вам нужны и как будет устроен повторный тест. Формат работ описан на странице услуги тестирования на проникновение.
PENTEST.RED
Обсудить объём и стоимость пентеста
Сначала согласуем системы, доступы, ограничения и ожидаемый результат.
Статья подготовлена на основе глубокого исследования и прошла редакционную переработку.