NextJS
Reading time: 24 minutes
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)
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 standardmĂ€Ăiges 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
Kernverzeichnisse und Dateien
- public/: Beherbergt statische Assets wie Bilder, Schriftarten und andere Dateien. Dateien hier sind am Stammverzeichnis (
/
) zugĂ€nglich. - app/: Zentrales Verzeichnis fĂŒr die Seiten, Layouts, Komponenten und API-Routen Ihrer Anwendung. Umfasst das App Router-Paradigma, das erweiterte Routing-Funktionen und die Trennung von Server- und Client-Komponenten ermöglicht.
- app/layout.tsx: Definiert das Hauptlayout fĂŒr Ihre Anwendung, das alle Seiten umschlieĂt und konsistente UI-Elemente wie Kopfzeilen, FuĂzeilen und Navigationsleisten bereitstellt.
- app/page.tsx: Dient als Einstiegspunkt fĂŒr die Stammroute
/
, die die Startseite rendert. - app/[route]/page.tsx: Behandelt statische und dynamische Routen. Jedes Verzeichnis innerhalb von
app/
stellt ein Routen-Segment dar, undpage.tsx
innerhalb dieser Verzeichnisse entspricht der Komponente der Route. - app/api/: EnthÀlt API-Routen, die es Ihnen ermöglichen, serverlose Funktionen zu erstellen, die HTTP-Anfragen verarbeiten. Diese Routen ersetzen das traditionelle Verzeichnis
pages/api
. - app/components/: Beherbergt wiederverwendbare React-Komponenten, die in verschiedenen Seiten und Layouts verwendet werden können.
- app/styles/: EnthĂ€lt globale CSS-Dateien und CSS-Module fĂŒr komponentenspezifisches Styling.
- app/utils/: Beinhaltet Hilfsfunktionen, Hilfsmodule und andere nicht-UI-Logik, die in der gesamten 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 die TypeScript-Einstellungen fĂŒr das Projekt und ermöglicht TypĂŒberprĂŒfungen und andere TypeScript-Funktionen.
- package.json: Verwaltet die AbhÀngigkeiten, Skripte und Metadaten des Projekts.
- README.md: Bietet Dokumentation und Informationen ĂŒber das Projekt, einschlieĂlich Einrichtungsanleitungen, Nutzungshinweisen und anderen relevanten Details.
- yarn.lock / package-lock.json: Sperrt die AbhÀngigkeiten des Projekts auf bestimmte Versionen, um konsistente Installationen in verschiedenen Umgebungen sicherzustellen.
Client-Seite in Next.js
Dateibasiertes Routing im app
-Verzeichnis
Das app
-Verzeichnis ist das Fundament des Routings in den neuesten Next.js-Versionen. Es nutzt das Dateisystem, um Routen zu definieren, was das Routing-Management intuitiv und skalierbar macht.
Behandlung des Stammverzeichnisses /
Dateistruktur:
my-nextjs-app/
âââ app/
â âââ layout.tsx
â âââ page.tsx
âââ public/
âââ next.config.js
âââ ...
Wichtige Dateien:
app/page.tsx
: Behandelt Anfragen an den Stamm-Pfad/
.app/layout.tsx
: Definiert das Layout fĂŒr die Anwendung, das alle Seiten umschlieĂt.
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>
);
}
ErklÀrung:
- Routen-Definition: Die
page.tsx
-Datei direkt imapp
-Verzeichnis entspricht der/
-Route. - Rendering: Diese Komponente rendert den Inhalt fĂŒr die Startseite.
- Layout-Integration: Die
HomePage
-Komponente wird von derlayout.tsx
umschlossen, die Header, Footer und andere gemeinsame Elemente enthalten kann.
Verarbeitung anderer statischer Pfade
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
page.tsx
-Datei imabout
-Ordner entspricht der/about
-Route. - Rendering: Diese Komponente rendert den Inhalt fĂŒr die Ăber-Seite.
Dynamische Routen
Dynamische Routen ermöglichen die Handhabung von Pfaden mit variablen Segmenten, wodurch Anwendungen Inhalte basierend auf Parametern wie IDs, Slugs usw. anzeigen können.
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, das denid
-Parameter aus der URL erfasst. - Zugriff auf Parameter: Das
params
-Objekt enthÀlt die dynamischen Parameter, die innerhalb der Komponente zugÀnglich sind. - Routenabgleich: Jeder Pfad, der mit
/posts/*
ĂŒbereinstimmt, wie z.B./posts/1
,/posts/abc
usw., wird von dieser Komponente verarbeitet.
Verschachtelte Routen
Next.js unterstĂŒtzt verschachtelte Routen, die hierarchische Routenstrukturen ermöglichen, die der Verzeichnisstruktur entsprechen.
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
page.tsx
-Datei im Verzeichnisdashboard/settings/profile/
entspricht dem/dashboard/settings/profile
-Pfad. - Hierarchie-Reflexion: Die Verzeichnisstruktur spiegelt den URL-Pfad wider, was die Wartbarkeit und Klarheit verbessert.
Catch-All-Routen
Catch-All-Routen behandeln mehrere verschachtelte Segmente oder unbekannte Pfade und bieten FlexibilitÀt bei der Routenbearbeitung.
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. - Verwendung: NĂŒtzlich fĂŒr die Handhabung dynamischer Routing-Szenarien wie benutzergenerierte Pfade, verschachtelte Kategorien usw.
- Routenabgleich: Pfade wie
/anything/here
,/foo/bar/baz
usw. werden von dieser Komponente verarbeitet.
Potenzielle Client-Seitige Schwachstellen
WĂ€hrend Next.js eine sichere Grundlage bietet, können unsachgemĂ€Ăe Programmierpraktiken Schwachstellen einfĂŒhren. Wichtige client-seitige Schwachstellen sind:
Cross-Site Scripting (XSS)
XSS-Angriffe treten auf, wenn bösartige Skripte in vertrauenswĂŒrdige Websites injiziert werden. Angreifer können Skripte in den Browsern der Benutzer ausfĂŒhren, Daten stehlen oder Aktionen im Namen des Benutzers durchfĂŒhren.
Beispiel fĂŒr anfĂ€lligen Code:
// Dangerous: Injecting user input directly into HTML
function Comment({ userInput }) {
return <div dangerouslySetInnerHTML={{ __html: userInput }} />
}
Warum es anfÀllig ist: Die Verwendung von dangerouslySetInnerHTML
mit nicht vertrauenswĂŒrdigen Eingaben ermöglicht es Angreifern, bösartige Skripte einzuschleusen.
Client-Seitige Template-Injektion
Tritt auf, wenn Benutzereingaben in Templates unsachgemÀà behandelt werden, was Angreifern ermöglicht, Templates oder AusdrĂŒcke einzuschleusen und auszufĂŒhren.
Beispiel fĂŒr anfĂ€lligen 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 anfÀllig ist: Wenn template
oder data
schĂ€dliche Inhalte enthalten, kann dies zur AusfĂŒhrung unbeabsichtigten Codes fĂŒhren.
Client Path Traversal
Es handelt sich um eine Schwachstelle, die Angreifern ermöglicht, clientseitige Pfade zu manipulieren, um unbeabsichtigte Aktionen durchzufĂŒhren, wie z.B. Cross-Site Request Forgery (CSRF). Im Gegensatz zur serverseitigen Pfadtraversierung, die das Dateisystem des Servers angreift, konzentriert sich CSPT darauf, clientseitige Mechanismen auszunutzen, um legitime API-Anfragen an bösartige Endpunkte umzuleiten.
Beispiel fĂŒr anfĂ€lligen Code:
Eine Next.js-Anwendung ermöglicht es Benutzern, Dateien hochzuladen und herunterzuladen. Die Download-Funktion wird auf der Client-Seite implementiert, wo Benutzer den Dateipfad angeben können, um herunterzuladen.
// 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
- Ziel des Angreifers: DurchfĂŒhrung eines CSRF-Angriffs, um eine kritische Datei (z.B.
admin/config.json
) zu löschen, indem derfilePath
manipuliert wird. - Ausnutzung von CSPT:
- Bösartige Eingabe: Der Angreifer erstellt eine URL mit einem manipulierten
filePath
, wie z.B.../deleteFile/config.json
. - Resultierender API-Aufruf: Der clientseitige Code sendet eine Anfrage an
/api/files/../deleteFile/config.json
. - Verarbeitung durch den Server: Wenn der Server den
filePath
nicht validiert, verarbeitet er die Anfrage und könnte potenziell sensible Dateien löschen oder offenlegen.
- AusfĂŒhrung von CSRF:
- Erstellter Link: Der Angreifer sendet dem Opfer einen Link oder bettet ein bösartiges Skript ein, das die Download-Anfrage mit dem manipulierten
filePath
auslöst. - Ergebnis: Das Opfer fĂŒhrt unwissentlich die Aktion aus, was zu unbefugtem Datei-Zugriff oder -Löschung fĂŒhrt.
Warum es anfÀllig ist
- Mangelnde Eingabevalidierung: Der clientseitige Code erlaubt beliebige
filePath
-Eingaben, was Pfadtraversal ermöglicht. - Vertrauen auf Client-Eingaben: Die serverseitige API vertraut und verarbeitet den
filePath
ohne SanitĂ€rung. - Potenzielle API-Aktionen: Wenn der API-Endpunkt zustandsverĂ€ndernde Aktionen durchfĂŒhrt (z.B. löschen, Dateien Ă€ndern), kann er ĂŒber CSPT ausgenutzt werden.
Server-Seite in Next.js
Server-Seitiges 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 Ihren eigenen benutzerdefinierten Server erstellen, um die Anfragen zu verarbeiten.
AnwendungsfÀlle:
- Dynamische Inhalte, die hÀufig wechseln.
- 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 einer reduzierten 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 Functions (API-Routen)
Next.js ermöglicht die Erstellung von API-Endpunkten als serverlose Funktionen. Diese Funktionen werden nach Bedarf ausgefĂŒhrt, 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-Verarbeitung flexibler und leistungsfĂ€higer geworden. Dieser moderne Ansatz steht in engem Zusammenhang mit dem dateibasierten Routing-System, bietet jedoch erweiterte Funktionen, einschlieĂlich UnterstĂŒtzung fĂŒr Server- und Client-Komponenten.
Grundlegender Routen-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:
- Standort: API-Routen befinden sich im Verzeichnis
app/api/
. - Dateibenennung: Jeder API-Endpunkt befindet sich in seinem eigenen Ordner, der eine
route.js
oderroute.ts
Datei enthÀlt. - Exportierte Funktionen: Anstelle eines einzelnen Standardexports werden spezifische HTTP-Methodenfunktionen (z.B.
GET
,POST
) exportiert. - Antwortverarbeitung: Verwenden Sie den
Response
-Konstruktor, um Antworten zurĂŒckzugeben, was mehr Kontrolle ĂŒber Header und Statuscodes ermöglicht.
So gehen Sie mit anderen Pfaden und Methoden um:
Verarbeitung spezifischer HTTP-Methoden
Next.js 13+ ermöglicht es Ihnen, Handler fĂŒr spezifische HTTP-Methoden innerhalb derselben route.js
oder route.ts
Datei zu definieren, was klareren und besser organisierten Code fördert.
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" },
})
}
ErklÀrung:
- Mehrere Exporte: Jede HTTP-Methode (
GET
,PUT
,DELETE
) hat ihre eigene exportierte Funktion. - Parameter: Das zweite Argument ermöglicht den Zugriff auf Routenparameter ĂŒber
params
. - Erweiterte Antworten: GröĂere Kontrolle ĂŒber Antwortobjekte, die eine prĂ€zise Verwaltung von Headern und Statuscodes ermöglicht.
Catch-All und Verschachtelte Routen
Next.js 13+ unterstĂŒtzt erweiterte Routing-Funktionen wie Catch-All-Routen und verschachtelte API-Routen, die dynamischere und skalierbarere API-Strukturen ermöglichen.
Catch-All-Routenbeispiel:
// 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:
[...]
bezeichnet ein Catch-All-Segment, das alle verschachtelten Pfade erfasst. - Verwendung: NĂŒtzlich fĂŒr APIs, die unterschiedliche Routen-Tiefen 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.
- Parameterzugriff: Einfacher Zugriff auf mehrere Routenparameter ĂŒber das
params
-Objekt.
Verarbeitung von 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 verbesserte Routing-Funktionen einfĂŒhrte, wurden API-Routen hauptsĂ€chlich im pages
-Verzeichnis definiert. Dieser Ansatz wird immer noch hĂ€ufig verwendet und in Next.js 12 und frĂŒheren Versionen unterstĂŒtzt.
Grundlegende 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:
- Standort: API-Routen befinden sich im Verzeichnis
pages/api/
. - Export: Verwenden Sie
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 Endpunkt/api/hello
.
Dynamische API-Routen
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: Verwenden Sie
req.query.id
, um auf den dynamischen Parameter zuzugreifen. - Verarbeitung von Methoden: Nutzen Sie bedingte Logik, um verschiedene HTTP-Methoden (
GET
,PUT
,DELETE
usw.) zu verarbeiten.
Verarbeitung verschiedener HTTP-Methoden
WĂ€hrend das grundlegende API-Routenbeispiel alle HTTP-Methoden innerhalb einer einzigen Funktion behandelt, können Sie Ihren Code so strukturieren, dass jede Methode explizit fĂŒr bessere Klarheit und Wartbarkeit behandelt wird.
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`);
}
}
Best Practices:
- Trennung der Anliegen: Logik fĂŒr verschiedene HTTP-Methoden klar trennen.
- Antwortkonsistenz: Konsistente Antwortstrukturen sicherstellen, um die Handhabung auf der Client-Seite zu erleichtern.
- Fehlerbehandlung: Nicht unterstĂŒtzte Methoden und unerwartete Fehler elegant behandeln.
CORS-Konfiguration
Steuern Sie, welche UrsprĂŒnge auf Ihre API-Routen zugreifen können, 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",
},
})
}
Beachten Sie, dass CORS auch in allen API-Routen innerhalb der middleware.ts
-Datei konfiguriert werden kann:
// 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, was potenziell bösartigen Seiten ermöglicht, ohne EinschrĂ€nkungen mit Ihrer API zu interagieren.- Breite Methoden-Erlaubnis: Das Zulassen aller Methoden kann Angreifern ermöglichen, unerwĂŒnschte Aktionen durchzufĂŒhren.
Wie Angreifer es ausnutzen:
Angreifer können bösartige Websites erstellen, die Anfragen an Ihre API senden, und dabei Funktionen wie Datenabruf, Datenmanipulation oder das Auslösen unerwĂŒnschter Aktionen im Namen authentifizierter Benutzer missbrauchen.
CORS - Misconfigurations & Bypass
Servercode-Exposition auf der Client-Seite
Es kann einfach sein, Code, der vom Server verwendet wird, auch im Code zu verwenden, der auf der Client-Seite exponiert und verwendet wird. Der beste Weg, um sicherzustellen, dass eine Datei mit Code niemals auf der Client-Seite exponiert wird, besteht darin, diesen Import zu Beginn der Datei zu verwenden:
import "server-only"
SchlĂŒsseldateien und ihre Rollen
middleware.ts
/ middleware.js
Standort: Wurzel des Projekts oder innerhalb von src/
.
Zweck: FĂŒhrt Code in der serverseitigen serverlosen Funktion aus, bevor eine Anfrage verarbeitet wird, was Aufgaben wie Authentifizierung, Weiterleitungen oder das Modifizieren von Antworten ermöglicht.
AusfĂŒhrungsfluss:
- Eingehende Anfrage: Die Middleware fÀngt die Anfrage ab.
- Verarbeitung: FĂŒhrt Operationen basierend auf der Anfrage durch (z. B. ĂberprĂŒfung der Authentifizierung).
- Antwortmodifikation: Kann die Antwort Ă€ndern oder die Kontrolle an den nĂ€chsten Handler ĂŒbergeben.
BeispielanwendungsfÀlle:
- Umleitung nicht authentifizierter Benutzer.
- HinzufĂŒgen benutzerdefinierter Header.
- Protokollierung von Anfragen.
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
Standort: Wurzel des Projekts.
Zweck: Konfiguriert das Verhalten von Next.js, aktiviert oder deaktiviert Funktionen, passt Webpack-Konfigurationen an, setzt Umgebungsvariablen und konfiguriert mehrere Sicherheitsfunktionen.
Wichtige Sicherheitskonfigurationen:
Sicherheitsheader
Sicherheitsheader verbessern 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-Typ-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...
],
},
]
},
}
Bildoptimierungseinstellungen
Next.js optimiert Bilder fĂŒr die Leistung, aber Fehlkonfigurationen können zu SicherheitsanfĂ€lligkeiten fĂŒhren, wie z.B. das Zulassen von nicht vertrauenswĂŒrdigen Quellen, die bösartigen Inhalt injizieren.
Schlechtes Konfigurationsbeispiel:
// next.config.js
module.exports = {
images: {
domains: ["*"], // Allows images from any domain
},
}
Problem:
'*'
: Erlaubt das Laden von Bildern aus jeder externen Quelle, einschlieĂlich untrusted oder bösartiger Domains. Angreifer können Bilder hosten, die bösartige Payloads oder Inhalte enthalten, die Benutzer irrefĂŒhren.- Ein weiteres Problem könnte sein, eine Domain zuzulassen wo jeder ein Bild hochladen kann (wie
raw.githubusercontent.com
)
Wie Angreifer dies ausnutzen:
Durch das Injizieren von Bildern aus bösartigen Quellen können Angreifer Phishing-Angriffe durchfĂŒhren, irrefĂŒhrende Informationen anzeigen oder Schwachstellen in Bildrendering-Bibliotheken ausnutzen.
Umgebungsvariablen-Exposition
Verwalten Sie sensible Informationen wie API-SchlĂŒssel und Datenbankanmeldeinformationen sicher, ohne sie dem Client auszusetzen.
a. Exponieren 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 dasNEXT_PUBLIC_
PrÀfix gibt Next.js keine Variablen an den Client weiter. Wenn es jedoch fÀlschlicherweise mit dem PrÀfix versehen wird (z. B.NEXT_PUBLIC_SECRET_API_KEY
), wird es auf der Client-Seite zugÀnglich.
Wie Angreifer es ausnutzen:
Wenn sensible Variablen dem Client ausgesetzt sind, können Angreifer sie abrufen, indem sie den Client-seitigen Code oder Netzwerk-Anfragen inspizieren, und unbefugten Zugriff auf APIs, Datenbanken oder andere Dienste erlangen.
Redirects
Verwalten Sie URL-Weiterleitungen und -Umleitungen innerhalb Ihrer Anwendung, um sicherzustellen, dass Benutzer angemessen geleitet werden, ohne offene Redirect-Schwachstellen einzufĂŒhren.
a. Open Redirect Vulnerability
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, jede URL anzugeben, was offene Umleitungsangriffe ermöglicht.
- Vertrauen auf Benutzereingaben: Umleitungen zu von Benutzern bereitgestellten URLs ohne Validierung können zu Phishing, Malware-Verbreitung oder Diebstahl von Anmeldeinformationen fĂŒhren.
Wie Angreifer es ausnutzen:
Angreifer können URLs erstellen, die scheinbar von Ihrer Domain stammen, aber Benutzer 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 zu schĂ€dlichen Websites navigieren.
Webpack-Konfiguration
Passen Sie die Webpack-Konfigurationen fĂŒr Ihre Next.js-Anwendung an, die unbeabsichtigt SicherheitsanfĂ€lligkeiten einfĂŒhren kann, wenn sie nicht vorsichtig behandelt wird.
a. Sensible Module offenlegen
Schlechtes Konfigurationsbeispiel:
// next.config.js
module.exports = {
webpack: (config, { isServer }) => {
if (!isServer) {
config.resolve.alias["@sensitive"] = path.join(__dirname, "secret-folder")
}
return config
},
}
Problem:
- Exponieren sensibler Pfade: Das Aliasing sensibler Verzeichnisse und das Zulassen des Zugriffs von der Client-Seite können vertrauliche Informationen leaken.
- BĂŒndeln von Geheimnissen: Wenn sensible Dateien fĂŒr den Client gebĂŒndelt werden, werden deren Inhalte ĂŒber Quellkarten oder durch Inspektion des Client-Seiten-Codes zugĂ€nglich.
Wie Angreifer es ausnutzen:
Angreifer können auf die Verzeichnisstruktur der Anwendung zugreifen oder diese rekonstruieren, wodurch sie potenziell sensible Dateien oder Daten finden und ausnutzen können.
pages/_app.js
und pages/_document.js
pages/_app.js
Zweck: Ăberschreibt die Standard-App-Komponente und ermöglicht globale ZustĂ€nde, Stile und Layout-Komponenten.
AnwendungsfÀlle:
- Injizieren von globalem CSS.
- HinzufĂŒgen von Layout-Wrappern.
- Integrieren von Zustandsverwaltungsbibliotheken.
Beispiel:
// pages/_app.js
import "../styles/globals.css"
function MyApp({ Component, pageProps }) {
return <Component {...pageProps} />
}
export default MyApp
pages/_document.js
Zweck: Ăberschreibt das Standarddokument und ermöglicht die Anpassung der HTML- und Body-Tags.
AnwendungsfÀlle:
- Ăndern der
<html>
- oder<body>
-Tags. - HinzufĂŒgen von Meta-Tags oder benutzerdefinierten Skripten.
- Integration von Schriftarten von Drittanbietern.
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: WĂ€hrend Next.js mit einem integrierten Server geliefert wird, können Sie einen benutzerdefinierten Server fĂŒr erweiterte AnwendungsfĂ€lle wie benutzerdefinierte Routen oder die Integration mit bestehenden Backend-Diensten erstellen.
Hinweis: Die Verwendung eines benutzerdefinierten Servers kann die Bereitstellungsoptionen einschrĂ€nken, insbesondere auf Plattformen wie Vercel, die fĂŒr den integrierten Server von Next.js optimieren.
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 architektonische und sicherheitstechnische Ăberlegungen
Umgebungsvariablen und Konfiguration
Zweck: Sensible Informationen und Konfigurationseinstellungen auĂerhalb des Codes verwalten.
Best Practices:
- Verwenden Sie
.env
-Dateien: Speichern Sie Variablen wie API-SchlĂŒssel in.env.local
(von der Versionskontrolle ausgeschlossen). - Greifen Sie sicher auf Variablen zu: Verwenden Sie
process.env.VARIABLE_NAME
, um auf Umgebungsvariablen zuzugreifen. - Geheimnisse niemals auf dem Client offenlegen: Stellen Sie 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 einzuschrÀnken, lassen Sie sie aus dem env
-Objekt weg oder prefixen Sie sie mit NEXT_PUBLIC_
fĂŒr die Client-Exposition.
Authentifizierung und Autorisierung
Ansatz:
- Sitzungsbasierte Authentifizierung: Verwenden Sie Cookies zur Verwaltung von Benutzersitzungen.
- Token-basierte Authentifizierung: Implementieren Sie JWTs fĂŒr zustandslose Authentifizierung.
- Drittanbieter: Integrieren Sie sich mit OAuth-Anbietern (z. B. Google, GitHub) unter Verwendung von Bibliotheken wie
next-auth
.
Sicherheitspraktiken:
- Sichere Cookies: Setzen Sie die Attribute
HttpOnly
,Secure
undSameSite
. - Passwort-Hashing: Hashen Sie Passwörter immer, bevor Sie sie speichern.
- Eingabevalidierung: Verhindern Sie Injektionsangriffe, indem Sie Eingaben validieren und bereinigen.
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 Importe, um Code zu splitten und die anfĂ€nglichen 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>,
})
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)
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.