Uma vulnerabilidade nota 10 atingiu React e Next.js (CVE-2025-55182 e CVE-2025-66478)
O React se tornou a base do desenvolvimento web moderno, uma ferramenta confiável usada por cerca de 40% de todos os desenvolvedores [1]. Frameworks como o Next.js se baseiam nessa confiança, impulsionando inúmeras aplicações em todo o mundo.
No dia 3 de dezembro de 2025, essa base das aplicações web foi abalada com a divulgação das CVE-2025-55182, uma vulnerabilidade crítica apelidada de React2Shell, e a CVE-2025-66478, uma vulnerabilidade de mesma gravidade no Next.js.
Com uma pontuação máxima de 10,0 no Sistema Comum de Pontuação de Vulnerabilidades (CVSS), elas representam ameaças graves e facilmente exploráveis.
Entendendo a vulnerabilidade
Em arquiteturas que utilizam React Server Components (como o Next.js com App Router), o servidor renderiza componentes e os envia para o navegador. Para realizar essa comunicação, estruturas de dados complexas (objetos) precisam ser convertidas em um fluxo de texto via HTTP (serialização) e reconstruídas quando o servidor recebe uma requisição ou resposta (desserialização) [2].
A vulnerabilidade reside no pacotereact-server e na forma como ele processa referências de objetos durante a desserialização. O mecanismo específico de exploração envolve o Event Loop do JavaScript e o tratamento de operações assíncronas. Quando o servidor utiliza o comando await para gerenciar tarefas em segundo plano, o Event Loop verifica se o objeto em questão possui uma função chamada .then().
Se possuir, o sistema assume que o objeto é uma "Promise" (promessa) e executa essa função .then() automaticamente para registrar o resultado da tarefa.
O React Flight permite que o servidor envie dados para o cliente (ou vice-versa) de forma fragmentada. Em vez de enviar um JSON gigante de uma vez, React e Next CVE 1 ele envia "Chunks" indexados por IDs. Esses chunks podem referenciar uns aos outros para reconstruir a árvore de dados final [4].
Cenário Legítimo (Exemplo de "Frutas" - adaptado do GitHub do msanft):
Imagine que o servidor quer enviar um objeto:
{ object: 'fruit', name: 'cherry' }No protocolo Flight, isso pode ser quebrado em várias partes interdependentes:
// Representação simplificada do envio de dados (Chunks)
files = {
"0": (None, '["$1"]'), // Chunk 0: É uma lista que conté
m o Chunk 1
"1": (None, '{"object":"fruit","name":"$2:fruitName"}'),
"2": (None, '{"fruitName":"cherry"}'), // Chunk 2: Dados brutos
}Ao processar isso, o React resolve as referências ( $1 , $2 ) e monta o objeto
final corretamente.
2. A Falha: Referências Inseguras (Prototype Pollution)
A vulnerabilidade (CVE-2025-55182) surge porque o mecanismo que resolve
essas referências (ex: buscar fruitName dentro do Chunk 2) não verificava se a
chave acessada era segura. Isso permitia acessar o protótipo do objeto
JavaScript.
O Código do Ataque (Acesso ao Construtor): Um atacante pode enviar um chunk que pede para o React buscar a propriedade constructor em vez de um dado legítimo.
files = {
"0": (None, '["$1:__proto__:constructor:constructor"]'), // Acessa o Constr
utor de Funções
"1": (None, '{"x":1}'),
}Ao desserializar isso, o resultado final não é um dado, mas sim o Construtor de Função (Function Constructor) do JavaScript. Ter acesso a esse construtor é o primeiro passo para executar qualquer código arbitrário.
O Ataque
Um atacante pode enviar uma payload HTTP especialmente criada onde ele força a propriedade .then de um objeto a ser uma ferramenta de sistema perigosa ou um construtor de funções (como o Function Constructor do JavaScript). Devido à desserialização insegura, o servidor não valida corretamente a estrutura desses dados. Ao encontrar a propriedade .then maliciosa, o Event Loop é enganado e executa o código do atacante no exato momento em que tenta registrar a tarefa, acreditando estar apenas resolvendo uma promessa legítima.
A CVE-2025-55182 refere-se à vulnerabilidade na biblioteca react-server , enquanto a CVE-2025-66478 foi atribuída ao Next.js por empacotar essa biblioteca vulnerável. Portanto, ao atacar um servidor Next.js, o atacante está explorando a falha de desserialização do React.
Apenas ter o Function Constructor não basta, pois o servidor executa o objeto resultante com await . O await passa funções ( resolve , reject ) para o objeto, mas o Function Constructor espera uma string de código para compilar. Se o await chamar o construtor diretamente, ocorre um erro de sintaxe.
Para contornar isso, o exploit utiliza uma técnica brilhante de manipulação de chunks para forçar o servidor a processar o payload duas vezes, permitindo alinhar os argumentos corretamente. O pesquisador msanft criou uma prova de conceito (PoC) para exploração da CVE-2025-55182 [4].
Passo A: Usar $@ para pegar o "Chunk Bruto"
O protocolo permite usar $@ para referenciar o objeto do chunk "cru" antes de ser resolvido. O atacante usa isso para sobrescrever o método .then do próprio chunk com o método nativo Chunk.prototype.then.
Passo B: O Gadget $B (Blobs)
Ao forçar o uso do Chunk.prototype.then , o atacante obriga o React a executar a função initializeModelChunk . Dentro dessa função, existe uma lógica para processar dados binários (Blobs), identificada pelo prefixo $B . O código vulnerável do React para processar $B faz algo assim:
// Lógica interna do React (simplificada)
response._formData.get(response._prefix + id)O atacante controla tanto _formData quanto _prefix através de um chunk malicioso.
Passo C: O Payload Final (RCE)
O atacante monta um chunk onde:
1. _formData.get é substituído pelo Function Constructor (obtido via prototype pollution).
2. _prefix contém o código malicioso (ex: process.mainModule... ).
O resultado é que o React executa involuntariamente:
Function("código malicioso" + id) .
Trecho do Payload de Exploração
crafted_chunk = {
// 1. Sobrescreve o .then para forçar o reprocessamento via initializeMod
elChunk
"then": "$1:__proto__:then",
"status": "resolved_model",
"reason": -1,
// 2. Define o valor a ser reprocessado usando o gadget de Blob ($B)
"value": '{"then": "$B0"}',
"_response": {
// 3. O código malicioso (Note o comentário // para anular o sufixo nu
mérico)
"_prefix": "process.mainModule.require('child_process').execSync('cal
c'); // ",
"_formData": {
// 4. Aponta o método 'get' para o Construtor de Função
"get": "$1:constructor:constructor",
},
},
}Ao enviar esse chunk, o servidor o desserializa, o await dispara a cadeia de eventos manipulada, e o código é executado antes mesmo de qualquer validação de rota da aplicação. Mais detalhes e um script com a PoC completa você pode ver no GitHub do msanft.
Correção aplicada
Código Vulnerável (antes do patch):
// O servidor recebia metadados e acessava a propriedade diretamente
return moduleExports[metadata[NAME]];Isso permitia que um atacante enviasse uma referência como $1:__proto__:constructor:constructor para obter acesso direto ao construtor Function do JavaScript, que permite criar e executar código dinamicamente.
O Patch (Correção):
// Agora verifica se a propriedade existe legitimamente no objeto
if (hasOwnProperty.call(moduleExports, metadata[NAME])) {
return moduleExports[metadata[NAME]];
}Dimensão do problema
A dimensão do problema é imensa. Dados da Wiz Research [2] indicam que 39% de todos os ambientes em nuvem contêm instâncias vulneráveis de React ou Next.js. A falha em si é uma vulnerabilidade de execução remota de código (RCE) não autenticada, e testes realizados por diversas empresas de segurança mostraram que a exploração tem "confiabilidade próxima a 100%". Trata-se de uma falha lógica determinística no protocolo "Flight" usado pelos componentes do servidor React.
Essas vulnerabilidades não são resultados de configuração incorreta ou de um caso extremo obscuro. Um aplicativo Next.js padrão criado com create-nextapp é explorável por padrão, sem necessidade de alterações de código por parte do desenvolvedor. Essas CVEs revelam um problema mais profundo e sistêmico sobre as concessões que fazemos na arquitetura de software moderna. Como observaram os pesquisadores da Unit 42: Em última análise, esse incidente ressalta o atrito inerente entre desempenho e segurança na arquitetura moderna [3]. Embora os componentes de servidor React otimizem a busca de dados e a otimização para mecanismos de busca (SEO) ao aproximar a lógica da fonte, eles simultaneamente aproximam a superfície de ataque dos dados mais sensíveis e valiosos das organizações. Em outras palavras, o próprio recurso projetado para tornar os aplicativos mais rápidos e eficientes — os componentes de servidor React — também criou um caminho direto e não autenticado para um invasor executar código no servido.
Onde estudar mais essa vulnerabilidade?
O Hacking Club prontamente disponibilizou um laboratório vulnerável para você treinar.
Acesse https://app.hackingclub.com/training/challenges/103 e venha explorar na prática o Rect2Shell!
Fontes [1] https://www.statista.com/statistics/1124699/worldwide-developer-surveymost-used-frameworks-web/
[2] https://www.wiz.io/blog/critical-vulnerability-in-react-cve-2025-55182
[3] https://unit42.paloaltonetworks.com/cve-2025-55182-react-and-cve-202566478-next/
[4] https://github.com/msanft/CVE-2025-55182