FlawOpen

flawopen.com/Incidents/microsoft-autogen-studio-autojack-agent-rce-june-2026

● Microsoft AutoGen project · CWE-1385 / CWE-306 / CWE-78 · 2026-06-18 · Hoch
Sicherheitsforschung · FlawOpen

AutoJack: RCE-Forschungskette in AutoGen Studio

Microsoft fand eine lokale RCE-Kette via MCP im AutoGen-Studio-Entwicklungsbuild. Vor Release behoben, erschien sie nie auf PyPI.[1], [2]

💡 Einfache Erklärung (ELI5)

Stellen Sie sich ein Forschungslabor vor, in dem ein Assistent Besuchernotizen liest. Der Assistent darf in den Kontrollraum, weil er im selben Gebäude arbeitet. Am Empfang entfällt dort die normale Identitätsprüfung, und eine Besuchernotiz kann auswählen, welches Werkzeug gestartet wird. AutoJack verband diese Abkürzungen: Ein Browsing-Agent zeigte nicht vertrauenswürdige Inhalte an, diese erreichten die lokale MCP-Steuerung von AutoGen Studio, und vom Anfragenden gelieferte Einstellungen konnten einen Kindprozess starten lassen. Authentifizieren Sie den Kontrollraum, nehmen Sie Startparameter aus WebSocket-URLs heraus und isolieren Sie den Assistenten vom Entwicklerrechner. Microsoft zufolge wurde der Fehler vor einer PyPI-Veröffentlichung im Upstream-Branch behoben. Die Forschung betrifft Quellcode vor der Veröffentlichung, keine betroffene Kundenversion.[1]

Kernkonzepte & Begriffe

AutoJack
Microsofts Bezeichnung für eine demonstrierte Kette in einem AutoGen-Studio-Entwicklungsbuild. Laut Bericht wurde die betroffene MCP-Route behoben, bevor sie in einem veröffentlichten PyPI-Paket enthalten war.[1], [2]
Loopback / localhost
Eine Netzwerkschnittstelle, über die Dienste auf demselben Host erreichbar sind. Sie begrenzt Zugriffe aus externen Netzen, isoliert aber lokale Prozesse wie den Agentenbrowser nicht von anderen Hostdiensten.[1]
Origin-Prüfung bei WebSockets
Eine serverseitige Prüfung des Origin-Headers während des WebSocket-Handshakes. Microsoft stellte fest, dass diese Prüfung allein im getesteten Agentenablauf die dargestellte Seite nicht vom lokalen MCP-Dienst fernhielt.[1], [3]
StdioServerParams
AutoGens MCP-stdio-Konfiguration mit Programm und Argumenten zum Start eines Serverprozesses. Die beschriebene Route dekodierte diese Einstellungen aus einem WebSocket-URL-Parameter.[1], [2], [5]
Confused deputy
Eine privilegierte Komponente wird dazu gebracht, ihre eigenen Rechte für eine nicht vertrauenswürdige Partei einzusetzen. Hier bildeten Browsing-Agent und lokaler Studio-Dienst die Brücke von Seiteninhalten zum Prozessstart auf dem Host.[1]

Framework-Zuordnungen

Vorfall-Zeitstrahl

Vor dem 18.06.2026

Microsoft meldete das Verhalten an MSRC; die AutoGen-Maintainer härteten den Upstream-Branch mit Commit b047730. Laut Bericht war die betroffene MCP-WebSocket-Route noch nicht in einem PyPI-Paket veröffentlicht.[1], [2]

18.06.2026

Microsoft veröffentlichte die AutoJack-Forschung und Schutzmaßnahmen. Beschrieben wird eine kontrollierte lokale Demonstration, kein bestätigter Angriff auf Kunden.[1]

Schritt-für-Schritt Angriffsablauf

Schritt 1

Der Agent soll nicht vertrauenswürdige Inhalte durchsuchen

Ein Prompt, eine abgerufene Seite oder eine andere nicht vertrauenswürdige Eingabe veranlasst einen AutoGen-Browsing-Agenten, eine vom Angreifer kontrollierte Seite auf demselben Rechner wie AutoGen Studio darzustellen.[1]

Schritt 2

Die dargestellte Seite erreicht den lokalen MCP-WebSocket

Im von Microsoft getesteten Aufbau konnte Seitenskript den MCP-Endpunkt von Studio auf localhost erreichen. Die Origin-Liste isolierte die Steuerung nicht von Code, den der lokale Agentenbrowser darstellte.[1], [3]

Schritt 3

Die MCP-Route umgeht die normale Authentifizierungs-Middleware

Die betroffene Middleware übersprang /api/mcp-Pfade in der Annahme, der WebSocket-Handler würde sie selbst authentifizieren. Laut Microsoft fehlte diese Prüfung im Handler.[1], [4]

Schritt 4

Die WebSocket-Abfrage bestimmt Serverparameter

Die Entwicklungsroute dekodierte server_params aus der URL in StdioServerParams. Der MCP-stdio-Transport verwendete command und args anschließend zum Start eines Kindprozesses.[1], [2], [5]

Schritt 5

Die Kette erreicht das Hostkonto

Der lokale Studio-Prozess startet den konfigurierten Kindprozess mit seinen Betriebssystemrechten. Microsoft demonstrierte dies in einem kontrollierten lokalen Proof of Concept und sagt, dass die Route nicht in einem veröffentlichten PyPI-Paket enthalten war.[1], [2]

Quellcode: Verwundbar vs. Sicher

Das verwundbare Beispiel analysiert vom Aufrufer kontrollierte Startparameter, startet aber absichtlich keinen Prozess. Der Upstream-Fix entfernte sie aus der WebSocket-Abfrage, legte sie in einem einmal verwendbaren serverseitigen Sitzungszustand ab und aktivierte die Authentifizierung für MCP-Routen wieder. Dieses defensive Referenzmuster ergänzt Ablaufzeit, Größenlimit, Nebenläufigkeitssperre und eine Allowlist ausführbarer Programme; ersetzen Sie den Beispielnamen durch die genau freigegebenen MCP-Binärdateien. Es ersetzt weder Origin-Prüfung noch Betriebssystemisolation.[1], [2]

VERWUNDBARE IMPLEMENTIERUNG
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:
    # Die Entwicklungsroute vertraute der in der URL übermittelten Konfiguration.
    encoded = query["server_params"]
    decoded = base64.b64decode(encoded)
    return StdioServerParams(**json.loads(decoded))
GEHÄRTETER SICHERHEITS-PATCH
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 muss aus verifizierter Middleware stammen, niemals aus Anfragedaten.
    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]

Checkliste für Engineering & Systemsicherheit

Quellen