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

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:

lua
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, a page.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:

arduino
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:

tsx
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 ispod app direktorijuma odgovara / ruti.
  • Renderovanje: Ova komponenta renderuje sadržaj za početnu stranu.
  • Integracija Rasporeda: HomePage komponenta je obavijena layout.tsx, koja može uključivati zaglavlja, podnožja i druge zajedničke elemente.
Obrada Ostalih Statickih Putanja

Primer: /about Ruta

Struktura Datoteka:

arduino
arduinoCopy codemy-nextjs-app/
├── app/
│   ├── about/
│   │   └── page.tsx
│   ├── layout.tsx
│   └── page.tsx
├── public/
├── next.config.js
└── ...

Implementacija:

tsx
// 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 unutar about 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:

arduino
arduinoCopy codemy-nextjs-app/
├── app/
│   ├── posts/
│   │   └── [id]/
│   │       └── page.tsx
│   ├── layout.tsx
│   └── page.tsx
├── public/
├── next.config.js
└── ...

Implementacija:

tsx
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ći id 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:

arduino
arduinoCopy codemy-nextjs-app/
├── app/
│   ├── dashboard/
│   │   ├── settings/
│   │   │   └── profile/
│   │   │       └── page.tsx
│   │   └── page.tsx
│   ├── layout.tsx
│   └── page.tsx
├── public/
├── next.config.js
└── ...

Implementacija:

tsx
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 unutar dashboard/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:

arduino
my-nextjs-app/
├── app/
│   ├── [..slug]/
│   │   └── page.tsx
│   ├── layout.tsx
│   └── page.tsx
├── public/
├── next.config.js
└── ...

Implementacija:

tsx
// 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:

jsx
// 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:

jsx
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.

jsx
// 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

  1. Cilj Napadača: Izvršiti CSRF napad da obriše kritičnu datoteku (npr., admin/config.json) manipulišući filePath.
  2. 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.
  1. 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:

jsx
// 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:

jsx
// 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:

go
my-nextjs-app/
├── app/
│   └── api/
│       └── hello/
│           └── route.js
├── package.json
└── ...

Implementacija:

javascript
// 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 ili route.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:

javascript
// 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:

javascript
// 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:

javascript
// 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:

go
goCopy codemy-nextjs-app/
├── pages/
│   └── api/
│       └── hello.js
├── package.json
└── ...

Implementacija:

javascript
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) i res (HTTP odgovor) objekte.
  • Ruting: Ime fajla (hello.js) se mapira na krajnju tačku /api/hello.

Dinamičke API Rute

Struktura fajla:

bash
bashCopy codemy-nextjs-app/
├── pages/
│   └── api/
│       └── users/
│           └── [id].js
├── package.json
└── ...

Implementacija:

javascript
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:

javascript
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:

javascript
// 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:

javascript
// 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:

js
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:

  1. Dolazni zahtev: Middleware presreće zahtev.
  2. Obrada: Izvršava operacije na osnovu zahteva (npr., provera autentifikacije).
  3. 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:

typescript
// 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:

javascript
// 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:

javascript
// 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:

javascript
// 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 NEXT_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:

javascript
// 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:

bash
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:

javascript
// 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:

jsx
// 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:

jsx
// 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:

javascript
// 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:

javascript
// 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 i SameSite.
  • Hashovanje lozinki: Uvek hashujte lozinke pre nego što ih sačuvate.
  • Validacija unosa: Sprečite napade injekcijom validacijom i sanitizacijom unosa.

Primer:

javascript
// 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:

jsx
// 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