NextJS
Reading time: 23 minutes
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)
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 funkcije kao što su rutiranje, API krajnje tačke 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
Osnovne Direktorije i Fajlovi
- public/: Sadrži statičke resurse kao što su slike, fontovi i drugi fajlovi. Fajlovi ovde su dostupni na korenskom putu (
/
). - app/: Centralna direktorija za stranice, rasporede, komponente i API rute vaše aplikacije. Obuhvata App Router paradigmu, omogućavajući napredne funkcije rutiranja i razdvajanje server-klijent komponenti.
- app/layout.tsx: Definiše osnovni raspored za vašu aplikaciju, obavijajući sve stranice i pružajući dosledne 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čnim i dinamičnim rutama. Svaka fascikla unutar
app/
predstavlja segment rute, apage.tsx
unutar tih fascikli odgovara komponenti rute. - app/api/: Sadrži API rute, omogućavajući vam da kreirate serverless funkcije koje obrađuju HTTP zahteve. Ove rute zamenjuju tradicionalnu
pages/api
direktoriju. - app/components/: Sadrži ponovo upotrebljive React komponente koje se mogu koristiti na različitim stranicama i rasporedima.
- app/styles/: Sadrži globalne CSS fajlove i CSS Module za stilizovanje ograničeno na komponente.
- app/utils/: Uključuje pomoćne funkcije, module i drugu logiku koja nije vezana za UI, a koja se može deliti širom aplikacije.
- .env.local: Čuva promenljive okruženja specifične za lokalno razvojno okruženje. Ove promenljive nisu uključene u kontrolu verzija.
- next.config.js: Prilagođava ponašanje Next.js, uključujući webpack konfiguracije, promenljive okruženja i bezbednosne postavke.
- tsconfig.json: Konfiguriše TypeScript postavke za projekat, omogućavajući proveru tipova i druge TypeScript funkcije.
- package.json: Upravljanje zavisnostima projekta, skriptama i metapodacima.
- README.md: Pruža dokumentaciju i informacije o projektu, uključujući uputstva za postavljanje, smernice za korišćenje i druge relevantne detalje.
- yarn.lock / package-lock.json: Zaključava zavisnosti projekta na specifične verzije, osiguravajući dosledne instalacije širom različitih okruženja.
Klijentska Strana u Next.js
Rutiranje na Bazi Fajlova u app
Direktoriji
Direktorija app
je kamen temeljac rutiranja u najnovijim verzijama Next.js. Ona koristi fajl sistem za definisanje ruta, čineći upravljanje rutama intuitivnim i skalabilnim.
Rukovanje Korenskim Putem /
Struktura Fajlova:
my-nextjs-app/
├── app/
│ ├── layout.tsx
│ └── page.tsx
├── public/
├── next.config.js
└── ...
Ključne datoteke:
app/page.tsx
: Obradjuje zahteve za korenski put/
.app/layout.tsx
: Definiše raspored za aplikaciju, obavijajući 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: Datoteka
page.tsx
direktno ispodapp
direktorijuma odgovara/
ruti. - Renderovanje: Ova komponenta renderuje sadržaj za početnu stranu.
- Integracija Rasporeda:
HomePage
komponenta je obavijenalayout.tsx
, koja može uključivati zaglavlja, podnožja i druge zajedničke elemente.
Obrada Ostalih Statickih Putanja
Primer: /about
Ruta
Struktura Datoteka:
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: Datoteka
page.tsx
unutarabout
foldera odgovara ruti/about
. - Renderovanje: Ova komponenta renderuje sadržaj za stranicu o nama.
Dinamičke Rute
Dinamičke rute omogućavaju rukovanje putanjama sa promenljivim segmentima, omogućavajući aplikacijama da prikazuju sadržaj na osnovu parametara kao što su ID-ovi, slugovi, itd.
Primer: /posts/[id]
Ruta
Struktura Datoteka:
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ćiid
parametar iz URL-a. - Pristup Parametrima:
params
objekat sadrži dinamičke parametre, dostupne unutar komponente. - Usklađivanje Ruta: Svaka putanja koja odgovara
/posts/*
, kao što su/posts/1
,/posts/abc
, itd., biće obrađena od strane ove komponente.
Ugnježdene Rute
Next.js podržava ugnježdene rute, omogućavajući hijerarhijske strukture ruta koje odražavaju raspored direktorijuma.
Primer: /dashboard/settings/profile
Ruta
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ždenje: Datoteka
page.tsx
unutardashboard/settings/profile/
odgovara ruti/dashboard/settings/profile
. - Refleksija Hijerarhije: Struktura direktorijuma odražava URL putanju, poboljšavajući održivost i jasnoću.
Catch-All Rute
Catch-all rute obrađuju više ugnježdenih segmenata ili nepoznatih putanja, pružajući fleksibilnost u obradi ruta.
Primer: /*
Ruta
Struktura Datoteka:
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 delove putanje kao niz. - Upotreba: Korisno za rukovanje dinamičkim rutiranjem kao što su putanje koje generišu korisnici, ugnježdene kategorije, itd.
- Usklađivanje Ruta: Putanje kao što su
/anything/here
,/foo/bar/baz
, itd., se obrađuju ovim komponentom.
Potencijalne Ranljivosti na Klijentskoj Strani
Dok Next.js pruža sigurnu osnovu, nepravilne prakse kodiranja mogu uvesti ranjivosti. Ključne ranjivosti na klijentskoj strani uključuju:
Cross-Site Scripting (XSS)
XSS napadi se dešavaju kada se zlonamerni skripti ubacuju u pouzdane veb sajtove. Napadači mogu izvršavati skripte u pregledačima korisnika, kradući podatke ili obavljajuć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 ulazima omogućava napadačima da ubace zlonamerne skripte.
Injekcija Šablona na Klijentskoj Strani
Događa se kada se korisnički unosi nepravilno obrađuju u šablonima, omogućavajući 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 ranjiv: Ako template
ili data
sadrže zlonamerni sadržaj, to može dovesti do izvršenja nepredviđenog koda.
Klijent Path Traversal
To je ranjivost koja omogućava napadačima da manipulišu putanjama na klijentskoj strani kako bi izvršili nepredviđene radnje, kao što je Cross-Site Request Forgery (CSRF). Za razliku od server-side path traversal, koja cilja na datotečni sistem servera, CSPT se fokusira na iskorišćavanje mehanizama na klijentskoj strani kako bi preusmerio legitimne API zahteve na zlonamerne krajnje tačke.
Primer ranjivog koda:
Next.js aplikacija omogućava korisnicima da otpremaju i preuzimaju datoteke. Funkcija preuzimanja je implementirana na klijentskoj strani, gde korisnici mogu da navedu putanju datoteke 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>
)
}
Napadni Scenarijo
- Cilj Napadača: Izvršiti CSRF napad da obriše kritičnu datoteku (npr.,
admin/config.json
) manipulišućifilePath
. - Iskorišćavanje CSPT:
- Zlonamerni Unos: Napadač kreira URL sa manipulisanom
filePath
kao što je../deleteFile/config.json
. - Rezultantni API Poziv: Klijentski kod šalje zahtev na
/api/files/../deleteFile/config.json
. - Rukovanje Servera: Ako server ne validira
filePath
, obrađuje zahtev, potencijalno brišući ili izlažući osetljive datoteke.
- Izvršavanje CSRF:
- Kreirana Veza: Napadač šalje žrtvi vezu ili ugrađuje zlonamerni skript koji pokreće zahtev za preuzimanje sa manipulisanom
filePath
. - Ishod: Žrtva nesvesno izvršava akciju, što dovodi do neovlašćenog pristupa ili brisanja datoteka.
Zašto je Ranjiv
- Nedostatak Validacije Unosa: Klijentska strana dozvoljava proizvoljne
filePath
unose, omogućavajući prelazak putanje. - Verovanje Klijentskim Unosima: Server-side API veruje i obrađuje
filePath
bez sanitizacije. - Potencijalne API Akcije: Ako API krajnja tačka izvršava akcije koje menjaju stanje (npr., brisanje, modifikovanje datoteka), može se iskoristiti putem CSPT.
Server-Side u Next.js
Server-Side Rendering (SSR)
Stranice se renderuju na serveru pri svakom zahtevu, osiguravajući da korisnik dobije potpuno renderovani HTML. U ovom slučaju treba da kreirate svoj prilagođeni server za obradu zahteva.
Upotrebe:
- Dinamički sadržaj koji se često menja.
- SEO optimizacija, jer pretraživači mogu da indeksiraju 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
Static Site Generation (SSG)
Stranice se prethodno renderuju u vreme izgradnje, što rezultira bržim vremenima učitavanja i smanjenim opterećenjem servera.
Upotreba:
- 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 Functions (API Routes)
Next.js omogućava kreiranje API krajnjih tačaka kao serverless funkcije. Ove funkcije se izvršavaju na zahtev bez potrebe za posvećenim serverom.
Upotrebe:
- Obrada slanja obrazaca.
- Interakcija sa bazama podataka.
- Obrada podataka ili integracija sa API-jem trećih strana.
Implementacija:
Sa uvođenjem app
direktorijuma u Next.js 13, rutiranje i rukovanje API-jem su postali fleksibilniji i moćniji. Ovaj moderni pristup se blisko usklađuje sa sistemom rutiranja zasnovanim na datotekama, ali uvodi poboljšane mogućnosti, uključujući podršku za server i klijentske komponente.
Basic Route Handler
Struktura datoteka:
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 rute se nalaze u
app/api/
direktorijumu. - Naziv fajlova: Svaki API endpoint se nalazi u svojoj fascikli koja sadrži
route.js
iliroute.ts
fajl. - Izvezene funkcije: Umesto jednog podrazumevanog izvoza, specifične funkcije HTTP metoda (npr.,
GET
,POST
) se izvoze. - Obrada odgovora: Koristite
Response
konstruktor za vraćanje odgovora, omogućavajući veću kontrolu nad header-ima i status kodovima.
Kako obraditi druge putanje i metode:
Obrada specifičnih HTTP metoda
Next.js 13+ omogućava vam da definišete handler-e za specifične HTTP metode unutar istog route.js
ili route.ts
fajla, promovišući jasniji i organizovaniji kod.
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 Izvozi: Svaka HTTP metoda (
GET
,PUT
,DELETE
) ima svoju funkciju za izvoz. - Parametri: Drugi argument omogućava pristup parametrima rute putem
params
. - Poboljšani Odgovori: Veća kontrola nad objektima odgovora, omogućavajući precizno upravljanje zaglavljem i statusnim kodom.
Catch-All i Ugnježdene Rute
Next.js 13+ podržava napredne funkcije usmeravanja kao što su catch-all rute i ugnježdene API rute, omogućavajući 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 segment koji obuhvata sve, hvatajući sve ugnježdene putanje. - Upotreba: Korisno za API-je koji treba da obrade različite dubine ruta 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ždenje: Omogućava hijerarhijske API strukture, odražavajući odnose resursa.
- Pristup Parametrima: Lako pristupite više parametara rute putem
params
objekta.
Upravljanje API rutama u Next.js 12 i ranije
API Rute u pages
direktorijumu (Next.js 12 i ranije)
Pre nego što je Next.js 13 uveo app
direktorijum i poboljšane mogućnosti rutiranja, API rute su se prvenstveno definisale unutar pages
direktorijuma. Ovaj pristup se i dalje široko koristi i podržava 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 rute se nalaze u
pages/api/
direktorijumu. - Izvoz: Koristite
export default
da definišete funkciju handler. - Potpis funkcije: Handler prima
req
(HTTP zahtev) ires
(HTTP odgovor) objekte. - Ruting: Ime fajla (
hello.js
) se mapira na krajnju tačku/api/hello
.
Dinamičke API Rute
Struktura fajla:
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: Kvadratne zagrade (
[id].js
) označavaju dinamičke delove rute. - Pristup parametrima: Koristite
req.query.id
za pristup dinamičkom parametru. - Rukovanje metodama: Iskoristite uslovnu logiku za rukovanje različitim HTTP metodama (
GET
,PUT
,DELETE
, itd.).
Rukovanje različitim HTTP metodama
Dok osnovni primer API rute obrađuje sve HTTP metode unutar jedne funkcije, možete strukturirati svoj kod da obrađuje svaku metodu eksplicitno radi bolje jasnoće i održivosti.
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:
- Razdvajanje Odgovornosti: Jasno razdvojiti logiku za različite HTTP metode.
- Doslednost Odgovora: Osigurati dosledne strukture odgovora radi lakšeg rukovanja na klijentskoj strani.
- Rukovanje Greškama: Elegantno obraditi nepodržane metode i neočekivane greške.
CORS Konfiguracija
Kontrolisati koje izvore mogu pristupiti vašim API rutama, smanjujući ranjivosti vezane za deljenje resursa između različitih izvora (CORS).
Primer Loše 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",
},
})
}
Napomena da CORS može biti konfigurisano u svim API rutama unutar middleware.ts
fajla:
// 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 kojoj veb stranici 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 radnje.
Kako napadači to koriste:
Napadači mogu kreirati zlonamerne veb stranice koje šalju zahteve vašem API-ju, potencijalno zloupotrebljavajući funkcionalnosti kao što su preuzimanje podataka, manipulacija podacima ili pokretanje neželjenih radnji u ime autentifikovanih korisnika.
CORS - Misconfigurations & Bypass
Izloženost server koda na klijentskoj strani
Lako je koristiti kod koji koristi server takođe u kodu koji je izložen i koristi se na klijentskoj strani, najbolji način da se osigura da datoteka koda nikada nije izložena na klijentskoj strani je korišćenje ovog uvoza na početku datoteke:
import "server-only"
Ključne datoteke i njihove uloge
middleware.ts
/ middleware.js
Lokacija: Korenski deo projekta ili unutar src/
.
Svrha: Izvršava kod u serverless funkciji na serverskoj strani pre nego što se zahtev obradi, omogućavajući zadatke kao što su autentifikacija, preusmeravanja ili modifikovanje odgovora.
Tok izvršenja:
- Dolazni zahtev: Middleware presreće zahtev.
- Obrada: Izvršava operacije na osnovu zahteva (npr., provera autentifikacije).
- Modifikacija odgovora: Može izmeniti odgovor ili preneti kontrolu sledećem handleru.
Primeri korišćenja:
- Preusmeravanje neautentifikovanih korisnika.
- Dodavanje prilagođenih zaglavlja.
- Zapisivanje zahteva.
Primer konfiguracije:
// 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: Korenski direktorijum projekta.
Svrha: Konfiguriše ponašanje Next.js, omogućavajući ili onemogućavajući funkcije, prilagođavajući webpack konfiguracije, postavljajući promenljive okruženja i konfigurišući nekoliko bezbednosnih funkcija.
Ključne bezbednosne konfiguracije:
Bezbednosni zaglavlja
Bezbednosna zaglavlja poboljšavaju bezbednost vaše aplikacije tako što upućuju pretraživače kako da rukuju sadržajem. Pomažu u ublažavanju raznih 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 za performanse, ali pogrešna podešavanja mogu dovesti do sigurnosnih ranjivosti, kao što je omogućavanje nepouzdanih izvora da ubace zlonamerni sadržaj.
Primer lošeg podešavanja:
// next.config.js
module.exports = {
images: {
domains: ["*"], // Allows images from any domain
},
}
Problem:
'*'
: Dozvoljava učitavanje slika sa bilo kog spoljnog izvora, uključujući nepouzdane ili zlonamerne domene. Napadači mogu hostovati slike koje sadrže zlonamerne payload-e ili sadržaj koji obmanjuje korisnike.- Drugi problem može biti dozvoliti domenu gde bilo ko može da otpremi sliku (kao što je
raw.githubusercontent.com
)
Kako napadači to zloupotrebljavaju:
Ubacivanjem slika iz zlonamernih izvora, napadači mogu izvesti phishing napade, prikazati obmanjujuće informacije ili iskoristiti ranjivosti u bibliotekama za renderovanje slika.
Izloženost promenljivih okruženja
Upravljajte osetljivim informacijama kao što su API ključevi i kredencijali baze podataka na siguran način bez izlaganja klijentu.
a. Izlaganje osetljivih promenljivih
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
: BezNEXT_PUBLIC_
prefiksa, Next.js ne izlaže varijable klijentu. Međutim, ako se greškom doda prefiks (npr.,NEXT_PUBLIC_SECRET_API_KEY
), postaje dostupno na strani klijenta.
Kako napadači to zloupotrebljavaju:
Ako su osetljive varijable izložene klijentu, napadači ih mogu preuzeti inspekcijom koda na strani klijenta ili mrežnih zahteva, stičući neovlašćen pristup API-ima, bazama podataka ili drugim uslugama.
Redirects
Upravljajte URL preusmeravanjima i prepisivanjima unutar vaše aplikacije, osiguravajući da su korisnici pravilno usmereni bez uvođenja ranjivosti otvorenog preusmeravanja.
a. Open Redirect Vulnerability
Primer loše 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 koju URL adresu, što omogućava napade otvorenog preusmeravanja.
- Verovanje korisničkom unosu: Preusmeravanje na URL adrese koje su pružili korisnici bez validacije može dovesti do fišinga, distribucije malvera ili krađe akreditiva.
Kako napadači to zloupotrebljavaju:
Napadači mogu kreirati URL adrese koje izgledaju kao da potiču sa vaše domene, ali preusmeravaju korisnike na zlonamerne sajtove. Na primer:
https://yourdomain.com/redirect?url=https://malicious-site.com
Korisnici koji veruju originalnoj domeni mogu nesvesno navigirati do štetnih veb sajtova.
Webpack Konfiguracija
Prilagodite Webpack konfiguracije za vašu Next.js aplikaciju, koje mogu nenamerno uvesti sigurnosne ranjivosti ako se ne rukuje 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:
- Izlaganje osetljivih putanja: Aliasiranje osetljivih direktorijuma i omogućavanje pristupa sa klijentske strane može dovesti do curenja poverljivih informacija.
- Pakovanje tajni: Ako su osetljivi fajlovi pakovani za klijenta, njihovi sadržaji postaju dostupni putem izvornih mapa ili inspekcijom koda sa klijentske strane.
Kako napadači to zloupotrebljavaju:
Napadači mogu pristupiti ili rekonstruisati strukturu direktorijuma aplikacije, potencijalno pronalazeći i eksploatišući osetljive fajlove ili podatke.
pages/_app.js
i pages/_document.js
pages/_app.js
Svrha: Preuzima podrazumevanu App komponentu, omogućavajući globalno stanje, stilove i komponente rasporeda.
Upotrebe:
- Umetanje globalnog CSS-a.
- Dodavanje omotača rasporeda.
- 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 dokument, omogućavajući prilagođavanje HTML i Body tagova.
Primeri upotrebe:
- Modifikovanje
<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
Prilagođeni Server (Opcionalno)
Svrha: Dok Next.js dolazi sa ugrađenim serverom, možete kreirati prilagođeni server za napredne slučajeve korišćenja kao što su prilagođeno usmeravanje ili integracija sa postojećim backend uslugama.
Napomena: Korišćenje prilagođenog servera može ograničiti opcije implementacije, posebno na platformama kao što je Vercel koje optimizuju za ugrađeni server Next.js.
Primer:
// 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")
})
})
Dodatne Arhitektonske i Bezbednosne Razmatranja
Promenljive Okruženja i Konfiguracija
Svrha: Upravljanje osetljivim informacijama i podešavanjima konfiguracije van koda.
Najbolje Prakse:
- Koristite
.env
Fajlove: Čuvajte promenljive kao što su API ključevi u.env.local
(isključeno iz kontrole verzija). - Pristupite Promenljivim Sigurno: Koristite
process.env.VARIABLE_NAME
za pristup promenljivim okruženja. - Nikada ne Izlažite Tajne na Klijentu: Osigurajte da se osetljive promenljive 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 serversku stranu, izostavite ih iz env
objekta ili ih prefiksirajte sa NEXT_PUBLIC_
za izlaganje klijentu.
Autentifikacija i Autorizacija
Pristup:
- Autentifikacija zasnovana na sesiji: Koristite kolačiće za upravljanje korisničkim sesijama.
- Autentifikacija zasnovana na tokenima: Implementirajte JWT-ove za stateless autentifikaciju.
- Treće strane: Integracija sa OAuth provajderima (npr., Google, GitHub) koristeći biblioteke kao što je
next-auth
.
Prakse bezbednosti:
- Sigurni kolačići: Postavite atribute
HttpOnly
,Secure
iSameSite
. - Hashovanje lozinki: Uvek hashujte lozinke pre nego što ih sačuvate.
- Validacija unosa: Sprečite napade injekcijom validacijom i sanitizacijom unosa.
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/image
komponent za automatsku optimizaciju slika. - Deljenje Koda: Iskoristite dinamičke uvoze za deljenje koda i smanjenje vremena učitavanja.
- Keširanje: Implementirajte strategije keširanja za API odgovore i statičke resurse.
- Lenjo 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>,
})
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)
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.