flawopen.com/Incidents/microsoft-autogen-studio-autojack-agent-rce-june-2026
AutoJack: исследовательская цепочка RCE в AutoGen Studio
Microsoft обнаружила локальную цепочку RCE через MCP в dev-сборке AutoGen Studio. Её исправили до релиза; в PyPI она не выходила.[1], [2]
Представьте исследовательскую лабораторию, где помощник читает записки посетителей. Его пускают в диспетчерскую, потому что он работает в том же здании. На входе для этой комнаты пропускают обычную проверку личности, а записка посетителя может выбрать запускаемый инструмент. AutoJack объединил эти упрощения: браузерный агент показал недоверенное содержимое, оно достигло локальной плоскости управления MCP в AutoGen Studio, а переданные вызывающей стороной настройки могли привести к запуску дочернего процесса. Нужно аутентифицировать плоскость управления, убрать параметры запуска из WebSocket URL и изолировать помощника от рабочей станции разработчика. Microsoft сообщает, что исправление появилось в ветке upstream до публикации PyPI. Исследование касается кода до выпуска, а не затронутой версии для клиентов.[1]
Ключевые понятия и термины
AutoJack- Название Microsoft для продемонстрированной цепочки в разрабатываемой версии AutoGen Studio. В отчёте сказано, что маршрут MCP исправили до включения в опубликованный пакет PyPI.[1], [2]
Loopback / localhost- Сетевой интерфейс для доступа к службам на том же хосте. Он ограничивает доступ извне, но не изолирует локальные процессы, например браузер агента, от других служб хоста.[1]
Проверка Origin для WebSocket- Серверная проверка заголовка Origin при WebSocket handshake. Microsoft установила, что в проверенном сценарии агента такая проверка сама по себе не отделяла отображённую страницу от локальной службы MCP.[1], [3]
StdioServerParams- Конфигурация MCP stdio в AutoGen: программа и аргументы для запуска процесса сервера. Описанный маршрут декодировал эти настройки из параметра URL WebSocket.[1], [2], [5]
Confused deputy- Привилегированный компонент побуждают использовать собственные полномочия в интересах недоверенной стороны. Здесь браузерный агент и локальная служба Studio связали содержимое страницы с запуском процесса на хосте.[1]
Связи со стандартами
- Ссылка CWE для слабого места, описанного в этом руководстве: CWE-78 CWE-306 CWE-1385
- OWASP GenAI 2025 — LLM06:2025 Чрезмерные полномочия агента
Хронология инцидента
Microsoft опубликовала исследование AutoJack и меры защиты. В нём описана контролируемая локальная демонстрация, а не подтверждённая атака на клиентов.[1]
Пошаговый сценарий атаки
Агенту поручают просмотреть недоверенное содержимое
Запрос, полученная страница или другой недоверенный ввод заставляет браузерный агент AutoGen отобразить страницу злоумышленника на той же машине, где работает AutoGen Studio.[1]
Исходный код: Уязвимый vs Защищённый вариант
Уязвимый пример разбирает параметры запуска, контролируемые вызывающей стороной, но намеренно не запускает процесс. Исправление upstream убрало настройки из запроса WebSocket, перенесло их в одноразовое серверное состояние сессии и восстановило аутентификацию маршрутов MCP. Этот защитный шаблон добавляет срок действия, ограничение размера, блокировку для параллельного доступа и список разрешённых исполняемых файлов; замените примерное имя точными разрешёнными бинарными файлами MCP. Он не заменяет проверку Origin и изоляцию ОС.[1], [2]
import base64
import json
from dataclasses import dataclass
@dataclass(frozen=True)
class StdioServerParams:
command: str
args: tuple[str, ...]
def params_from_websocket_query(query: dict[str, str]) -> StdioServerParams:
# Маршрут разработки доверял конфигурации, переданной в URL.
encoded = query["server_params"]
decoded = base64.b64decode(encoded)
return StdioServerParams(**json.loads(decoded))from dataclasses import dataclass
from threading import Lock
from time import monotonic
from uuid import uuid4
@dataclass(frozen=True)
class StdioServerParams:
command: str
args: tuple[str, ...]
SESSION_TTL = 30.0
MAX_PENDING = 256
ALLOWED_COMMANDS = {"approved-mcp-server"}
pending: dict[str, tuple[float, StdioServerParams]] = {}
pending_lock = Lock()
def register_params(params: StdioServerParams, authenticated: bool) -> str:
# authenticated должен поступать из проверенного middleware, а не из данных запроса.
if not authenticated:
raise PermissionError("MCP control-plane authentication required")
if params.command not in ALLOWED_COMMANDS:
raise ValueError("unapproved MCP server executable")
now = monotonic()
with pending_lock:
for key, (expires, _) in list(pending.items()):
if expires <= now:
pending.pop(key, None)
if len(pending) >= MAX_PENDING:
raise RuntimeError("pending MCP session limit reached")
session_id = str(uuid4())
pending[session_id] = (now + SESSION_TTL, params)
return session_id
def consume_params(session_id: str, authenticated: bool) -> StdioServerParams:
if not authenticated:
raise PermissionError("MCP control-plane authentication required")
with pending_lock:
entry = pending.pop(session_id, None)
if entry is None or entry[0] <= monotonic():
raise ValueError("unknown or expired MCP session")
return entry[1]Чек-лист по защите системы для инженеров
- ✓Требуйте аутентификацию и авторизацию на каждом маршруте плоскости управления MCP, включая WebSocket handshake; проверьте для этих маршрутов все включённые режимы аутентификации.[1], [2], [4]
- ✓Не принимайте настройки запуска процессов в URL WebSocket или другом вводе под контролем браузера. Регистрируйте их через аутентифицированный запрос и связывайте с короткоживущей одноразовой серверной сессией.[2]
- ✓Удаляйте просроченные ожидающие сессии, ограничьте их число, потребляйте каждую атомарно и отклоняйте неизвестные, просроченные или повторно использованные идентификаторы.[2]
- ✓Разрешайте только утверждённые исполняемые файлы MCP-серверов и фиксированные схемы аргументов; вывод модели и содержимое страниц не должны выбирать произвольные программы.[1], [5]
- ✓Изолируйте браузерных агентов, отображающих недоверенные страницы, от привилегированных локальных плоскостей управления; по возможности блокируйте доступ к loopback из песочницы браузера.[1], [3]
- ✓Запускайте агента и Studio с минимальными правами или во временной VM/контейнере; создайте оповещение о неожиданных дочерних процессах от сред выполнения агента.[1]
- ✓Для сборок AutoGen Studio из исходников используйте ревизию b047730 или новее. Microsoft указывает, что затронутого маршрута не было в актуальном тогда пакете PyPI; проверяйте конкретный артефакт развёртывания.[1], [2]
Источники
- Microsoft Security Blog — AutoJack: как одна страница может запустить код на хосте ИИ-агента
- Коммит Microsoft AutoGen b047730 — защита конечной точки MCP WebSocket
- CWE-1385: отсутствует проверка Origin в WebSocket
- CWE-306: отсутствует аутентификация критически важной функции
- CWE-78: некорректная нейтрализация специальных символов в команде ОС