pimenov.ai

База знаний

MCP и безопасность — prompt injection, tool poisoning и как защититься

Как устроена безопасность MCP: реальные атаки (tool poisoning, prompt injection, rug pull, tool shadowing) и практические меры: OAuth-авторизация, изоляция, least privilege, сканирование, пиннинг версий, аудит tool calls.

Опубликовано Обновлено

MCP (Model Context Protocol) связывает ИИ-приложения с внешними инструментами и данными. Такое подключение расширяет поверхность атаки: локальный сервер может выполнять код с правами клиента, удалённый сервер получает выданные ему полномочия, а описания инструментов и возвращаемый контент способны влиять на поведение модели.

📌
Коротко: считайте MCP-сервер, его метаданные, описания инструментов и результаты вызовов отдельными недоверенными входами. Безопасная конфигурация сочетает минимальные полномочия, изоляцию, явное подтверждение рискованных действий, контроль сетевого доступа и аудит.

Содержание

  1. Целевая архитектура
  2. Чек-лист быстрой проверки
  3. Основные атаки
  4. Требования актуальной спецификации
  5. Практические меры для клиента и сервера
  6. Эталонный профиль подключения
  7. Действия при изменении инструмента
  8. Источники

Целевая архитектура

Безопасная схема строится вокруг хоста MCP, который сохраняет контроль над полномочиями и действиями агента:

flowchart LR
    U[Пользователь] --> H[Хост MCP]
    H --> P[Проверка политик и подтверждение]
    P --> S[Изолированный MCP-сервер]
    S --> E[Разрешённые внешние API]
    H --> L[Журнал вызовов]
    S --> L
    D[Недоверенные данные и описания] --> H

Хост показывает пользователю существенные параметры операции, проверяет полномочия и ограничивает доступ сервера к файлам и сети. Данные от инструментов остаются недоверенными до проверки. Токен, предназначенный одному MCP-серверу, нельзя передавать другому сервису или использовать как универсальный ключ.

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

Чек-лист быстрой проверки

Известны автор, владелец и источник релиза сервера.
Зафиксированы версия пакета и хеш описаний инструментов.
Команда запуска показана полностью и одобрена пользователем.
Сервер работает с минимальными правами процесса и файловой системы.
Исходящие соединения ограничены списком необходимых адресов.
Для HTTP используются отдельные короткоживущие токены с узкими областями доступа; для stdio OAuth-поток MCP не применяется, а учётные данные берутся из окружения.
Сервер проверяет назначение токена и не принимает токен, выпущенный для другого ресурса, и не пересылает клиентский токен дальше.
Читающие и изменяющие операции различимы в интерфейсе.
Перед удалением, отправкой, публикацией и переводом требуется отдельное подтверждение.
Пользователь видит полного получателя, назначение и существенные аргументы вызова.
Запросы sampling можно просмотреть, изменить или отклонить.
На вызовы, размер ответа и циклы инструментов установлены лимиты.
Все вызовы и повышения полномочий попадают в журнал аудита.
Есть процедура отключения сервера и отзыва его токенов.

Основные атаки

Инструкции в описании инструмента (tool poisoning)

При отравлении инструмента вредные инструкции помещают в его описание или в параметры, которые модель видит при формировании вызова. Модель видит эти данные при выборе инструмента, поэтому влияние возможно до его вызова. Исследование Invariant Labs от 1 апреля 2025 года показало, что скрытые аргументы могут использоваться для передачи конфиденциальных данных.

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

Косвенная промпт-инъекция в данных

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

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

Тихое изменение после подключения (rug pull)

Сервер может изменить описание уже одобренного инструмента, а обновление пакета — его поведение. Клиенту следует хранить версию и хеш метаданных, уведомлять об изменении и требовать повторного согласия перед использованием изменившегося инструмента.

Влияние описания одного сервера на соседний инструмент (tool shadowing)

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

Sampling: запрос генерации со стороны сервера

Sampling позволяет серверу запросить генерацию у модели через клиента. Спецификация не задаёт конкретную модель интерфейса, но для доверия и безопасности рекомендует оставлять человека в контуре: пользователь должен иметь возможность увидеть и изменить промпт, отклонить запрос и проверить ответ до его передачи серверу.

Сервер может попросить модель использовать инструменты внутри sampling. Клиент обязан заранее объявить возможность sampling.tools, а сервер не должен отправлять запрос с инструментами клиенту, который эту возможность не объявил. Обеим сторонам следует ограничивать число итераций, частоту запросов и объём контекста.

Значения thisServer и allServers параметра includeContext помечены как soft-deprecated. По умолчанию этот параметр лучше не передавать: его значение none не включает контекст других серверов.

Ошибка доверенного посредника (confused deputy) и подмена назначения токена

В официальной документации confused deputy описан прежде всего для MCP-прокси, который обращается к стороннему API через общий OAuth-клиент. Если прокси не запрашивает согласие отдельно для каждого MCP-клиента, злоумышленник может попытаться получить код авторизации без корректного согласия пользователя.

Другой опасный антипаттерн — передача токена без проверки (token passthrough): сервер принимает токен клиента, не подтверждает, что он выпущен для самого сервера, и пересылает его дальше. MCP-сервер обязан проверять назначение токена и принимать только токены, выпущенные для его ресурса. Для обращения к стороннему API нужен отдельный токен этого API.

SSRF (Server-Side Request Forgery) при обнаружении OAuth-метаданных

SSRF, или подделка серверного запроса, возникает, когда клиент под влиянием внешних данных обращается к непредусмотренному адресу. При обнаружении OAuth-метаданных такими данными могут быть URL из заголовка WWW-Authenticate, документа защищённого ресурса и метаданных сервера авторизации.

Если клиент автоматически запрашивает эти адреса без проверки, вредный MCP-сервер может направить его к внутренним IP-адресам, облачным metadata endpoint, сервисам на localhost или к внутреннему адресу после перенаправления. Возможны утечка учётных данных, разведка сети и взаимодействие с внутренними сервисами.

В рабочей среде разрешайте HTTPS для OAuth-адресов. Исключение для HTTP оставляйте только для loopback-адресов при локальной разработке. Блокируйте приватные и зарезервированные диапазоны, включая 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 127.0.0.0/8, 169.254.0.0/16, fc00::/7 и fe80::/10. Проверяйте каждый переход перенаправления и используйте выходной egress-прокси с сетевыми политиками.

Проверку IP лучше выполнять проверенной библиотекой: самописные фильтры часто пропускают альтернативные формы адресов, IPv4-mapped IPv6 и DNS rebinding. Учитывайте также разрыв между проверкой DNS-ответа и фактическим запросом.

Компрометация локального сервера и цепочки поставки

Локальный MCP-сервер выполняется с правами процесса клиента. Вредная команда запуска или пакет могут получить доступ к файлам, переменным окружения и сети.

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

Локальный HTTP следует защищать авторизацией либо защищённым IPC, например Unix domain socket. Не разрешайте серверу доступ к личным файлам и сети шире необходимого.

Требования актуальной спецификации

По состоянию на версию MCP 2025-11-25 для HTTP-авторизации применяются следующие положения:

  • авторизация в MCP опциональна; если она поддерживается, HTTP-реализациям следует соответствовать этой спецификации, а реализациям на stdio следует получать учётные данные из окружения;
  • механизм авторизации MCP основан на OAuth 2.1 и связанных RFC; в тексте спецификации OAuth 2.1 указан как IETF draft;
  • клиент обязан применять PKCE (Proof Key for Code Exchange, защита кода авторизации от перехвата) и проверять поддержку PKCE; при технической возможности используется метод S256;
  • токен передаётся в заголовке Authorization: Bearer, а не в строке запроса;
  • клиент указывает целевой ресурс через параметр resource и включает его и в запрос авторизации, и в запрос токена; значение должно идентифицировать канонический URI MCP-сервера;
  • сервер проверяет, что токен выпущен именно для его ресурса, и не принимает и не пересылает токены с другим назначением;
  • начальные области доступа (scope) должны быть минимальными, а повышение полномочий выполняется по мере необходимости через точный challenge WWW-Authenticate;
  • MCP-сервер с авторизацией проверяет каждый входящий запрос и не использует идентификатор сессии как средство аутентификации;
  • OAuth-адреса проходят строгую проверку схемы и назначения, а открывать их через shell-команду запрещено.

В приведённых требованиях MCP нет универсального правила, обязывающего подтверждать каждый обычный вызов инструмента. Интерфейс подтверждения выбирает приложение. Для sampling рекомендуется human-in-the-loop, а для локальной установки и чувствительных операций явное согласие остаётся важным защитным рубежом.

Практические меры для клиента и сервера

Если вы подключаете MCP-сервер

  1. Проверьте владельца, историю релизов и способ доставки.
  2. Зафиксируйте точную версию; отключите неконтролируемое автообновление.
  3. Сохраните хеш списка инструментов, их описаний и схем аргументов.
  4. Запустите локальный сервер в контейнере или системной песочнице.
  5. Разрешите только необходимые каталоги и сетевые адреса.
  6. Создайте отдельное OAuth-приложение и выдайте минимальные области доступа.
  7. Проверьте интерфейс подтверждения: он должен показывать действие, получателя и аргументы без скрытых полей.
  8. Настройте журналирование и быстрый отзыв токена.

Если вы разрабатываете MCP-сервер

  • Делайте инструменты узкими по назначению и проверяйте авторизацию на стороне сервера.
  • Не помещайте в description инструкции, которые требуют скрывать действия или менять поведение других инструментов.
  • Не принимайте токен только на основании наличия области доступа: проверяйте подпись, срок действия, издателя, назначение и права на конкретный объект.
  • Для стороннего API получайте отдельный токен; передача клиентского токена дальше запрещена.
  • Валидируйте входные данные, результаты инструментов и сообщения sampling.
  • Ограничивайте частоту запросов, размер ответа и число итераций цикла инструментов.
  • Версионируйте изменения описаний и публикуйте проверяемые артефакты релиза.

Эталонный профиль подключения

Используйте этот шаблон как минимальную карточку допуска сервера:

server:
  owner: 'team-or-vendor' # Владелец или ответственный поставщик.
  source: 'verified-release-url' # Проверенный источник релиза.
  version: 'pinned-version' # Зафиксированная версия.
  tool_metadata_hash: 'sha256:expected-hash' # Хеш описаний и схем инструментов.

runtime:
  transport: 'stdio-or-http' # Для HTTP-транспорта используйте HTTPS.
  sandbox: true # Запуск с ограниченными правами.
  filesystem_allowlist:
    - '/workspace/approved-directory' # Разрешённый каталог.
  network_allowlist:
    - 'api.example.com:443' # Разрешённое исходящее соединение.

authorization: # Для HTTP; при stdio этот OAuth-раздел не применяется.
  token_audience: 'https://mcp.example.com' # Ресурс, для которого выпущен токен.
  initial_scopes:
    - 'files:read' # Минимальная область доступа для начала работы.
  token_passthrough: false # Клиентский токен не передаётся стороннему API.

controls:
  confirm_mutations: true # Подтверждать операции с внешним эффектом.
  show_full_arguments: true # Показывать пользователю все существенные аргументы.
  sampling_review: true # Оставлять sampling на проверку пользователя.
  max_tool_loop_iterations: 5 # Пример лимита; настройте по модели угроз.
  audit_log: true # Записывать вызовы и изменения полномочий.

Значения здесь служат безопасными заполнителями. Реальные адреса, области доступа и лимиты определяются моделью угроз конкретного сервера.

Действия при изменении инструмента

  1. Заблокируйте изменившийся инструмент до проверки.
  2. Сравните новую версию, описание, схему аргументов и сетевые назначения с зафиксированными значениями.
  3. Проверьте, не появились ли скрытые поля, межсерверные инструкции или новые права.
  4. Повторно запустите сервер в изолированной среде с тестовыми данными.
  5. Получите новое согласие для дополнительных полномочий или рискованных действий.
  6. После допуска обновите хеш и запись аудита.

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

Источники

Следующий шаг

Для отдельного разбора атак на данные и поведение агента можно перейти к материалу «Промпт-инъекции: что это, чем опасны и как защитить агентов».

Связанные материалы

Если вы внедряете несколько MCP-серверов или отвечаете за их допуск, полезно отдельно разобрать границы между недоверенным контентом и инструкциями агента.

Если захотите обсудить, как это применить у себя или в команде — пишите в Telegram @pimenov