Skip to content
KitploitKITPLOIT
ToolsBlog
Log in
Einreichen
ToolsBlog
Einreichen

Hacking-, PenTest- und Cybersicherheits-Tools für Ihr Sicherheitsarsenal!

Kitploit ist ein Verzeichnis von Hacking-, Cybersicherheits- und Pentesting-Tools. Entdecken Sie die neuesten Projekt-Updates, um Schwachstellen zu finden, Systeme zu analysieren, Tests zu automatisieren und Ihre Sicherheit zu stärken.

FeedsKontaktDatenschutz© 2026 Kitploit

Tool-Verzeichnis

Kategorien

Alle Kategorien anzeigen
Loading categories
CVE-2026-33701-Unsafe-Deserialization-in-OpenTelemetry-Java-Agent-RMI-Instrumentation — Technische Analyse von CVE-2026-33701, einer unsicheren Deserialisierungs-Schwachstelle in der RMI-Instrumentierung des OpenTelemetry Java Agent, einschließlich Exploit-Bedingungen, Patch-Details und Minderungsstrategien. | Kitploit
Tools/GitHubGitHub/pl4tyz/cve-2026-33701-unsafe-deserialization-in-opentelemetry-java-agent-rmi-instrumentation
SchwachstellenanalyseExploitationWebsicherheitLernen & Bildung
GitHubpl4tyz/cve-2026-33701-unsafe-deserialization-in-opentelemetry-java-agent-rmi-instrumentation

CVE-2026-33701-Unsafe-Deserialization-in-OpenTelemetry-Java-Agent-RMI-Instrumentation

Technische Analyse von CVE-2026-33701, einer unsicheren Deserialisierungs-Schwachstelle in der RMI-Instrumentierung des OpenTelemetry Java Agent, einschließlich Exploit-Bedingungen, Patch-Details und Minderungsstrategien.

Repository anzeigen
11vor 6 MonatenNoch nicht geprüft

Beliebteste

Alle anzeigen →

Entdecken Sie die meistgenutzten Tools unserer Community.

Alle Tools erkunden

Durchsuchen Sie unsere Tool-Sammlung

Alle Tools anzeigen →
Teilen

CVE-2026-33701 — Unsichere Deserialisierung in der RMI-Instrumentierung des OpenTelemetry Java Agents

Schweregrad: Kritisch (CVSS v4.0: 9.3)
Betroffene Versionen: opentelemetry-javaagent < 2.26.1
Behoben in: 2.26.1 (veröffentlicht am 23. März 2026)


Überblick

OpenTelemetry ist derzeit wahrscheinlich das am weitesten verbreitete Observability-Framework im Java-Ökosystem. Insbesondere der Java-Agent wird von Tausenden von Produktionsdiensten verwendet, um Anwendungen automatisch für Tracing, Metriken und Logging zu instrumentieren, ohne dass der Entwickler Codeänderungen vornehmen muss. Man hängt ihn einfach als javaagent-Flag an und er erledigt alles im Hintergrund.

Was CVE-2026-33701 interessant macht, ist nicht nur die Schwachstelle selbst, sondern die Art und Weise, wie sie eingeführt wurde. Der Agent registriert stillschweigend einen benutzerdefinierten RMI-Endpunkt als Nebeneffekt seiner RMI-Instrumentierung. Entwickler wissen nicht, dass er da ist. Er steht in keinem Anwendungscode. Er wurde von niemandem konfiguriert. Der Agent hat ihn automatisch platziert, und in Versionen unter 2.26.1 deserialisierte dieser Endpunkt eingehende Daten ohne jegliche Filter.

Wenn die Anwendung bereits einen RMI- oder JMX-Port offen hatte, konnte ein Angreifer mit Netzwerkzugriff auf diesen Port ein manipuliertes serialisiertes Payload an den benutzerdefinierten Endpunkt des Agents senden und möglicherweise Remote-Code-Ausführung mit den Rechten des JVM-Prozesses erreichen. Der Haken ist, dass RCE eine kompatible Gadget-Chain auf dem Anwendungs-Classpath erfordert. Mehr dazu später.


Wie der Agent RMI instrumentiert

Wenn sich der OTel Java Agent an eine JVM anhängt, instrumentiert er RMI-Aufrufe für die Kontextweitergabe. Die Idee ist, dass der Agent beim Aufruf einer entfernten Methode durch einen RMI-Client den aktuellen Trace-Kontext an die Serverseite weitergeben muss, damit Spans korrekt über Dienstgrenzen hinweg verbunden werden.

Dazu registriert der Agent sein eigenes benutzerdefiniertes RMI-Objekt mit einer fest codierten ObjID. In ContextPropagator.java:

public static final ObjID CONTEXT_CALL_ID =
    new ObjID("io.opentelemetry.javaagent.context-call".hashCode());

Diese ObjID ist die Art und Weise, wie der Agent seinen eigenen Endpunkt innerhalb der RMI-Laufzeitumgebung identifiziert. Wenn ein instrumentierter RMI-Client eine Verbindung zu einem Server herstellt, prüft er zunächst, ob der Server diese ObjID registriert hat. Wenn ja, sendet er ein Kontextweitergabe-Payload an ihn. Wenn nicht, überspringt er die Kontextweitergabe und führt einfach den regulären Aufruf aus.

Das Problem ist, dass dieser Endpunkt innerhalb der JVM-RMI-Laufzeitumgebung registriert ist, was bedeutet, dass er denselben Transport nutzt wie der RMI- oder JMX-Port, den die Anwendung offen hat. Wenn die Anwendung -Dcom.sun.management.jmxremote.port gesetzt hat oder eigene RMI-Dienste exportiert, ist der Endpunkt des Agents auf demselben Port für jeden erreichbar, der sich verbinden kann.


Der verwundbare Code

Die Deserialisierung findet in ContextPayload.java statt. In Versionen unter 2.26.1 sah die read()-Methode wie folgt aus:

@SuppressWarnings("BanSerializableRead") // fine
public static ContextPayload read(ObjectInput oi) throws IOException {
    try {
        Object object = oi.readObject();
        if (object instanceof Map) {
            @SuppressWarnings("unchecked")
            Map<String, String> map = (Map<String, String>) object;
            return new ContextPayload(map);
        }
    } catch (ClassCastException | ClassNotFoundException ex) {
        logger.log(FINE, "Error reading object", ex);
    }
    return null;
}

Die Annotation @SuppressWarnings("BanSerializableRead") mit dem Kommentar // fine ist tatsächlich ziemlich aufschlussreich. Jemand im Team hat dies irgendwann als Bedenken markiert, die Unterdrückung wurde hinzugefügt, und der Kommentar sollte dies rechtfertigen. Offensichtlich war es nicht in Ordnung.

oi.readObject() ohne Serialisierungsfilter ist das klassische Muster unsicherer Deserialisierung. Die Java-Serialisierung instanziiert während der Deserialisierung bereitwillig jede Klasse auf dem Classpath, und wenn der Angreifer den serialisierten Stream kontrollieren kann, kann er wählen, welche Klassen in welcher Reihenfolge instanziiert werden. Das ist die Grundlage von Gadget-Chain-Angriffen.

Der Code prüft nach der Deserialisierung zwar instanceof Map, aber zu diesem Zeitpunkt ist der Schaden bereits angerichtet. Die Gadget-Chain wird während des readObject()-Aufrufs selbst ausgeführt, bevor eine Typprüfung stattfindet. Die instanceof-Prüfung ist aus Sicherheitssicht völlig irrelevant.


Der Patch

Der Fix in 2.26.1 ersetzt den Deserialisierungsansatz vollständig. Anstatt ein Map-Objekt zu serialisieren und readObject() aufzurufen, liest die neue Implementierung die Kontexteinträge manuell als primitive Typen:

@Nullable
public static ContextPayload read(ObjectInput oi) throws IOException {
    int size = oi.readInt();
    if (size > MAX_CONTEXT_ENTRIES) {
        logger.log(
            FINE,
            "RMI context propagation payload size {0} exceeds maximum allowed of {1}, skipping context propagation.",
            new Object[] {size, MAX_CONTEXT_ENTRIES});
        return null;
    }
    Map<String, String> map = new HashMap<>();
    for (int i = 0; i < size; i++) {
        String key = oi.readUTF();
        String value = oi.readUTF();
        map.put(key, value);
    }
    return new ContextPayload(map);
}

Und die Schreibseite wurde entsprechend aktualisiert:

public void write(ObjectOutput out) throws IOException {
    int size = context.size();
    if (size > MAX_CONTEXT_ENTRIES) {
        out.writeInt(0);
        return;
    }
    out.writeInt(size);
    for (Map.Entry<String, String> entry : context.entrySet()) {
        out.writeUTF(entry.getKey());
        out.writeUTF(entry.getValue());
    }
}

Dieser Ansatz liest nur primitive Typen (Ints und UTF-Strings) aus dem Stream. Es findet keine Objektinstanziierung statt. Keine Gadget-Chain kann über readInt() oder readUTF() ausgeführt werden. Der Fix ist korrekt und vollständig.

Es gibt noch eine zweite Änderung, die erwähnenswert ist. Die ObjID, die zur Identifizierung des benutzerdefinierten Endpunkts des Agents verwendet wird, wurde versioniert:

// Vorher (2.26.0)
new ObjID("io.opentelemetry.javaagent.context-call".hashCode());

// Nachher (2.26.1)
new ObjID("io.opentelemetry.javaagent.context-call-v2".hashCode());

Das bedeutet, dass ein gepatchter Agent auf die alte ObjID überhaupt nicht mehr reagiert. Ein Angreifer, der den alten Endpunkt angreift, würde von einem gepatchten Server keine Antwort erhalten. Dies ist eine zusätzliche Härtungsmaßnahme zusätzlich zum Deserialisierungs-Fix – sie bricht effektiv jeden Exploit, der gegen den v1-Endpunkt gebaut wurde, selbst wenn die Deserialisierung irgendwie noch erreichbar wäre.


Exploit-Bedingungen

Alle drei der folgenden Bedingungen müssen gleichzeitig erfüllt sein, damit dies ausnutzbar ist:

1. OpenTelemetry Java Agent auf JDK 16 oder niedriger angehängt

Dies ist die wichtigste Einschränkung. JDK 17 führte erhebliche Änderungen an den RMI-Interna ein und erzwingt eine viel strengere Modul-Kapselung über das Java Platform Module System. Die meisten Gadget-Chains, die gegen Java-Deserialisierung funktionieren, verlassen sich auf Reflektion, um auf interne JDK-Klassen zuzugreifen oder Methoden aufzurufen, die normalerweise nicht zugänglich wären. JDK 17 bricht diese Reflektionspfade standardmäßig aufgrund der starken Kapselung, was bedeutet, dass die Mehrheit der bekannten Gadget-Chains auf JDK 17 und höher einfach nicht funktioniert.

Tool herunterladen