NextJS

Reading time: 23 minutes

tip

AWS Hacking'i öğrenin ve pratik yapın:HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking'i öğrenin ve pratik yapın: HackTricks Training GCP Red Team Expert (GRTE)

HackTricks'i Destekleyin

Next.js Uygulamasının Genel Mimarisi

Tipik Dosya Yapısı

Standart bir Next.js projesi, yönlendirme, API uç noktaları ve statik varlık yönetimi gibi özelliklerini kolaylaştıran belirli bir dosya ve dizin yapısını takip eder. İşte tipik bir düzen:

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

Temel Dizinler ve Dosyalar

  • public/: Görseller, fontlar ve diğer dosyalar gibi statik varlıkları barındırır. Buradaki dosyalar kök yol (/) üzerinden erişilebilir.
  • app/: Uygulamanızın sayfaları, düzenleri, bileşenleri ve API yolları için merkezi dizin. App Router paradigmasını benimser, gelişmiş yönlendirme özellikleri ve sunucu-müşteri bileşen ayrımı sağlar.
  • app/layout.tsx: Uygulamanız için kök düzeni tanımlar, tüm sayfaları sarar ve başlıklar, alt bilgiler ve navigasyon çubukları gibi tutarlı UI öğeleri sağlar.
  • app/page.tsx: Kök yol / için giriş noktası olarak hizmet eder, ana sayfayı render eder.
  • app/[route]/page.tsx: Statik ve dinamik yolları yönetir. app/ içindeki her klasör bir yol segmentini temsil eder ve bu klasörlerdeki page.tsx, yolun bileşenine karşılık gelir.
  • app/api/: API yollarını içerir, HTTP isteklerini yöneten sunucusuz işlevler oluşturmanıza olanak tanır. Bu yollar geleneksel pages/api dizinini değiştirir.
  • app/components/: Farklı sayfalar ve düzenler arasında kullanılabilecek yeniden kullanılabilir React bileşenlerini barındırır.
  • app/styles/: Bileşen kapsamlı stil için global CSS dosyalarını ve CSS Modüllerini içerir.
  • app/utils/: Uygulama genelinde paylaşılabilecek yardımcı modüller, yardımcı işlevler ve diğer UI dışı mantıkları içerir.
  • .env.local: Yerel geliştirme ortamına özgü ortam değişkenlerini saklar. Bu değişkenler versiyon kontrolüne dahil edilmez.
  • next.config.js: Next.js davranışını özelleştirir, webpack yapılandırmaları, ortam değişkenleri ve güvenlik ayarlarını içerir.
  • tsconfig.json: Proje için TypeScript ayarlarını yapılandırır, tür kontrolü ve diğer TypeScript özelliklerini etkinleştirir.
  • package.json: Proje bağımlılıklarını, betikleri ve meta verileri yönetir.
  • README.md: Proje hakkında belgeler ve bilgiler sağlar, kurulum talimatları, kullanım kılavuzları ve diğer ilgili detayları içerir.
  • yarn.lock / package-lock.json: Projenin bağımlılıklarını belirli sürümlere kilitler, farklı ortamlar arasında tutarlı kurulumlar sağlar.

Next.js'de İstemci Tarafı

app Dizininde Dosya Tabanlı Yönlendirme

app dizini, en son Next.js sürümlerinde yönlendirmenin temel taşıdır. Yolları tanımlamak için dosya sistemini kullanır, bu da yol yönetimini sezgisel ve ölçeklenebilir hale getirir.

Kök Yol / Yönetimi

Dosya Yapısı:

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

Ana Dosyalar:

  • app/page.tsx: Kök yoluna / gelen istekleri işler.
  • app/layout.tsx: Uygulamanın düzenini tanımlar, tüm sayfaların etrafını sarar.

Uygulama:

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>
);
}

Açıklama:

  • Yol Tanımı: app dizininin altındaki page.tsx dosyası / yoluna karşılık gelir.
  • Renderlama: Bu bileşen ana sayfa içeriğini renderlar.
  • Düzen Entegrasyonu: HomePage bileşeni, başlıklar, alt bilgiler ve diğer ortak öğeleri içerebilen layout.tsx ile sarılmıştır.
Diğer Statik Yolları Yönetme

Örnek: /about Yolu

Dosya Yapısı:

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

Uygulama:

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>
)
}

Açıklama:

  • Yol Tanımı: about klasörü içindeki page.tsx dosyası /about yoluna karşılık gelir.
  • Renderlama: Bu bileşen, hakkında sayfası için içeriği renderlar.
Dinamik Yollar

Dinamik yollar, değişken segmentlere sahip yolları yönetmeyi sağlar, uygulamaların ID'ler, slug'lar gibi parametrelere dayalı içerik göstermesine olanak tanır.

Örnek: /posts/[id] Yolu

Dosya Yapısı:

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

Uygulama:

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>
);
}

Açıklama:

  • Dinamik Segment: [id], URL'den id parametresini yakalayan bir dinamik segmenti belirtir.
  • Parametrelere Erişim: params nesnesi, bileşen içinde erişilebilen dinamik parametreleri içerir.
  • Yol Eşleşmesi: /posts/* ile eşleşen herhangi bir yol, örneğin /posts/1, /posts/abc vb., bu bileşen tarafından işlenecektir.
İç İçe Yollar

Next.js, dizin yapısını yansıtan hiyerarşik yol yapıları için iç içe yönlendirmeyi destekler.

Örnek: /dashboard/settings/profile Yolu

Dosya Yapısı:

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

Uygulama:

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>
);
}

Açıklama:

  • Derin Yerleştirme: dashboard/settings/profile/ içindeki page.tsx dosyası, /dashboard/settings/profile rotasına karşılık gelir.
  • Hiyerarşi Yansıması: Dizin yapısı, URL yolunu yansıtarak bakım kolaylığı ve netlik sağlar.
Her Şeye Açık Rotalar

Her şeye açık rotalar, birden fazla iç içe segmenti veya bilinmeyen yolları yönetir, rota yönetiminde esneklik sağlar.

Örnek: /* Rotası

Dosya Yapısı:

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

Uygulama:

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>
)
}

Açıklama:

  • Catch-All Segment: [...slug] kalan tüm yol segmentlerini bir dizi olarak yakalar.
  • Kullanım: Kullanıcı tarafından oluşturulan yollar, iç içe geçmiş kategoriler gibi dinamik yönlendirme senaryolarını yönetmek için yararlıdır.
  • Yol Eşleştirme: /anything/here, /foo/bar/baz gibi yollar bu bileşen tarafından işlenir.

Potansiyel İstemci Tarafı Güvenlik Açıkları

Next.js güvenli bir temel sağlasa da, yanlış kodlama uygulamaları güvenlik açıkları oluşturabilir. Ana istemci tarafı güvenlik açıkları şunlardır:

Cross-Site Scripting (XSS)

XSS saldırıları, kötü niyetli betiklerin güvenilir web sitelerine enjekte edilmesiyle gerçekleşir. Saldırganlar, kullanıcıların tarayıcılarında betikleri çalıştırarak verileri çalabilir veya kullanıcı adına eylemler gerçekleştirebilir.

Güvenlik Açığı Olan Kod Örneği:

jsx
// Dangerous: Injecting user input directly into HTML
function Comment({ userInput }) {
return <div dangerouslySetInnerHTML={{ __html: userInput }} />
}

Neden Zayıf: dangerouslySetInnerHTML'yi güvenilmeyen girdi ile kullanmak, saldırganların kötü niyetli scriptler enjekte etmesine olanak tanır.

İstemci Tarafı Şablon Enjeksiyonu

Kullanıcı girdilerinin şablonlarda yanlış bir şekilde işlenmesi durumunda meydana gelir, bu da saldırganların şablonları veya ifadeleri enjekte edip çalıştırmasına olanak tanır.

Zayıf Kodu Örneği:

jsx
import React from "react"
import ejs from "ejs"

function RenderTemplate({ template, data }) {
const html = ejs.render(template, data)
return <div dangerouslySetInnerHTML={{ __html: html }} />
}

Neden Zayıf: Eğer template veya data kötü niyetli içerik içeriyorsa, istenmeyen kodun çalıştırılmasına yol açabilir.

Müşteri Yol Geçişi

Bu, saldırganların istemci tarafı yollarını manipüle ederek istenmeyen eylemler gerçekleştirmesine olanak tanıyan bir zayıflıktır; örneğin, Cross-Site Request Forgery (CSRF). Sunucu tarafı yol geçişinin sunucunun dosya sistemini hedef almasının aksine, CSPT, meşru API isteklerini kötü niyetli uç noktalara yönlendirmek için istemci tarafı mekanizmalarını istismar etmeye odaklanır.

Zayıf Kod Örneği:

Bir Next.js uygulaması, kullanıcıların dosya yüklemesine ve indirmesine olanak tanır. İndirme özelliği istemci tarafında uygulanmıştır; burada kullanıcılar indirmek için dosya yolunu belirtebilir.

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>
)
}

Saldırı Senaryosu

  1. Saldırganın Amacı: filePath'ı manipüle ederek kritik bir dosyayı (örneğin, admin/config.json) silmek için bir CSRF saldırısı gerçekleştirmek.
  2. CSPT'yi Kötüye Kullanma:
  • Kötü Amaçlı Girdi: Saldırgan, filePath'ı manipüle edilmiş bir URL oluşturur, örneğin ../deleteFile/config.json.
  • Sonuçlanan API Çağrısı: İstemci tarafındaki kod, /api/files/../deleteFile/config.json adresine bir istek gönderir.
  • Sunucunun İşlemesi: Sunucu filePath'ı doğrulamıyorsa, isteği işler ve hassas dosyaları silme veya ifşa etme riski taşır.
  1. CSRF'yi Gerçekleştirme:
  • Hazırlanan Bağlantı: Saldırgan, kurbanına manipüle edilmiş filePath ile indirme isteğini tetikleyen bir bağlantı gönderir veya kötü amaçlı bir script gömülü bir şekilde iletir.
  • Sonuç: Kurban, farkında olmadan işlemi gerçekleştirir ve yetkisiz dosya erişimi veya silme ile sonuçlanır.

Neden Zayıf

  • Girdi Doğrulama Eksikliği: İstemci tarafı, keyfi filePath girdilerine izin vererek yol geçişine olanak tanır.
  • İstemci Girdilerine Güvenme: Sunucu tarafındaki API, filePath'ı temizlemeden güvenerek işler.
  • Potansiyel API Eylemleri: Eğer API uç noktası durum değiştiren eylemler gerçekleştiriyorsa (örneğin, dosyaları silme, değiştirme), CSPT aracılığıyla kötüye kullanılabilir.

Next.js'de Sunucu Tarafı

Sunucu Tarafı Render'ı (SSR)

Sayfalar, her istekte sunucuda render edilir ve kullanıcının tamamen render edilmiş HTML almasını sağlar. Bu durumda, istekleri işlemek için kendi özel sunucunuzu oluşturmalısınız.

Kullanım Durumları:

  • Sık sık değişen dinamik içerik.
  • Arama motorlarının tamamen render edilmiş sayfayı tarayabilmesi nedeniyle SEO optimizasyonu.

Uygulama:

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

Statik Site Üretimi (SSG)

Sayfalar, inşa zamanında önceden işlenir, bu da daha hızlı yükleme süreleri ve azaltılmış sunucu yükü sağlar.

Kullanım Durumları:

  • Sık sık değişmeyen içerikler.
  • Bloglar, belgeler, pazarlama sayfaları.

Uygulama:

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

Sunucusuz Fonksiyonlar (API Yolları)

Next.js, sunucusuz fonksiyonlar olarak API uç noktalarının oluşturulmasına olanak tanır. Bu fonksiyonlar, özel bir sunucuya ihtiyaç duymadan talep üzerine çalışır.

Kullanım Durumları:

  • Form gönderimlerini işleme.
  • Veritabanlarıyla etkileşim.
  • Verileri işleme veya üçüncü taraf API'lerle entegrasyon.

Uygulama:

Next.js 13'te app dizininin tanıtılmasıyla, yönlendirme ve API yönetimi daha esnek ve güçlü hale geldi. Bu modern yaklaşım, dosya tabanlı yönlendirme sistemiyle yakından uyumlu olup, sunucu ve istemci bileşenleri desteği gibi geliştirilmiş yetenekler sunar.

Temel Yönlendirme İşleyici

Dosya Yapısı:

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

Uygulama:

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))

Açıklama:

  • Konum: API yolları app/api/ dizini altında yer alır.
  • Dosya İsimlendirme: Her API uç noktası, içinde bir route.js veya route.ts dosyası bulunan kendi klasöründe bulunur.
  • Dışa Aktarılan Fonksiyonlar: Tek bir varsayılan dışa aktarma yerine, belirli HTTP yöntem fonksiyonları (örneğin, GET, POST) dışa aktarılır.
  • Yanıt Yönetimi: Yanıtları döndürmek için Response yapıcısını kullanın, bu da başlıklar ve durum kodları üzerinde daha fazla kontrol sağlar.

Diğer yollar ve yöntemler nasıl yönetilir:

Belirli HTTP Yöntemlerini Yönetme

Next.js 13+ aynı route.js veya route.ts dosyası içinde belirli HTTP yöntemleri için işleyiciler tanımlamanıza olanak tanır, bu da daha net ve düzenli bir kodu teşvik eder.

Örnek:

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" },
})
}

Açıklama:

  • Birden Fazla İhracat: Her HTTP yöntemi (GET, PUT, DELETE) kendi ihraç edilen fonksiyonuna sahiptir.
  • Parametreler: İkinci argüman, params aracılığıyla rota parametrelerine erişim sağlar.
  • Gelişmiş Yanıtlar: Yanıt nesneleri üzerinde daha fazla kontrol, hassas başlık ve durum kodu yönetimi sağlar.
Catch-All ve İç İçe Rotalar

Next.js 13+ gelişmiş yönlendirme özelliklerini destekler, bu da catch-all rotaları ve iç içe API rotalarını mümkün kılarak daha dinamik ve ölçeklenebilir API yapıları sağlar.

Catch-All Rota Örneği:

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" },
})
}

Açıklama:

  • Sözdizimi: [...] tüm iç içe geçmiş yolları yakalayan bir kapsayıcı segmenti belirtir.
  • Kullanım: Farklı yol derinliklerini veya dinamik segmentleri işlemek için gereken API'ler için yararlıdır.

İç İçe Geçmiş Yollar Örneği:

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" },
}
)
}

Açıklama:

  • Derin Yerleştirme: Kaynak ilişkilerini yansıtan hiyerarşik API yapıları için olanak tanır.
  • Parametre Erişimi: params nesnesi aracılığıyla birden fazla rota parametresine kolayca erişim sağlar.
Next.js 12 ve Öncesinde API Rotalarını Yönetme

pages Dizini İçindeki API Rotaları (Next.js 12 ve Öncesi)

Next.js 13, app dizinini tanıttıktan ve yönlendirme yeteneklerini geliştirdikten önce, API rotaları esasen pages dizini içinde tanımlanıyordu. Bu yaklaşım hala yaygın olarak kullanılmakta ve Next.js 12 ve önceki sürümlerde desteklenmektedir.

Temel API Rotası

Dosya Yapısı:

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

Uygulama:

javascript
javascriptCopy code// pages/api/hello.js

export default function handler(req, res) {
res.status(200).json({ message: 'Hello, World!' });
}

Açıklama:

  • Konum: API yolları pages/api/ dizini altında bulunur.
  • İhracat: İşlev tanımlamak için export default kullanın.
  • Fonksiyon İmzası: İşlev, req (HTTP isteği) ve res (HTTP yanıtı) nesnelerini alır.
  • Yönlendirme: Dosya adı (hello.js), /api/hello uç noktasına karşılık gelir.

Dinamik API Yolları

Dosya Yapısı:

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

Uygulama:

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`);
}
}

Açıklama:

  • Dinamik Segmentler: Kare parantezler ([id].js) dinamik rota segmentlerini belirtir.
  • Parametrelere Erişim: Dinamik parametreye erişmek için req.query.id kullanın.
  • Yöntemleri Yönetme: Farklı HTTP yöntemlerini (GET, PUT, DELETE, vb.) yönetmek için koşullu mantık kullanın.

Farklı HTTP Yöntemlerini Yönetme

Temel API rota örneği tüm HTTP yöntemlerini tek bir fonksiyon içinde yönetirken, kodunuzu her yöntemi açıkça yönetmek için yapılandırabilirsiniz, bu da daha iyi bir netlik ve sürdürülebilirlik sağlar.

Örnek:

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`);
}
}

En İyi Uygulamalar:

  • Endişelerin Ayrılması: Farklı HTTP yöntemleri için mantığı net bir şekilde ayırın.
  • Yanıt Tutarlılığı: İstemci tarafında işleme kolaylığı için tutarlı yanıt yapıları sağlayın.
  • Hata Yönetimi: Desteklenmeyen yöntemleri ve beklenmeyen hataları nazikçe yönetin.

CORS Yapılandırması

API rotalarınıza hangi kökenlerin erişebileceğini kontrol edin, Cross-Origin Resource Sharing (CORS) zafiyetlerini azaltın.

Kötü Yapılandırma Örneği:

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",
},
})
}

Not edin ki CORS, tüm API yollarında da yapılandırılabilir middleware.ts dosyası içinde:

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: '*': Herhangi bir web sitesinin API'ye erişmesine izin verir, bu da kötü niyetli sitelerin API'nizle sınırsız etkileşimde bulunmasına olanak tanıyabilir.
  • Geniş Yöntem İzni: Tüm yöntemlere izin vermek, saldırganların istenmeyen eylemler gerçekleştirmesine olanak tanıyabilir.

Saldırganların bunu nasıl kullandığı:

Saldırganlar, API'nize isteklerde bulunan kötü niyetli web siteleri oluşturabilir, bu da veri alma, veri manipülasyonu veya kimlik doğrulaması yapılmış kullanıcılar adına istenmeyen eylemleri tetikleme gibi işlevleri kötüye kullanmalarına neden olabilir.

CORS - Misconfigurations & Bypass

Sunucu kodunun İstemci Tarafında Açığa Çıkması

Sunucu tarafından kullanılan kodun istemci tarafında da kullanılmasını sağlamak kolaydır, bir kod dosyasının istemci tarafında asla açığa çıkmadığından emin olmanın en iyi yolu, dosyanın başında bu import'u kullanmaktır:

js
import "server-only"

Ana Dosyalar ve Rolleri

middleware.ts / middleware.js

Konum: Projenin kökünde veya src/ içinde.

Amaç: Bir isteğin işlenmesinden önce sunucu tarafında sunucusuz işlevde kodu çalıştırarak kimlik doğrulama, yönlendirmeler veya yanıtları değiştirme gibi görevleri yerine getirir.

İşlem Akışı:

  1. Gelen İstek: Middleware isteği yakalar.
  2. İşleme: İsteğe bağlı olarak işlemler gerçekleştirir (örneğin, kimlik doğrulama kontrolü).
  3. Yanıt Değişikliği: Yanıtı değiştirebilir veya kontrolü bir sonraki işleyiciye geçirebilir.

Örnek Kullanım Durumları:

  • Kimliği doğrulanmamış kullanıcıları yönlendirme.
  • Özel başlıklar ekleme.
  • İstekleri günlüğe kaydetme.

Örnek Konfigürasyon:

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

Konum: Projenin kökü.

Amaç: Next.js davranışını yapılandırır, özellikleri etkinleştirir veya devre dışı bırakır, webpack yapılandırmalarını özelleştirir, ortam değişkenlerini ayarlar ve çeşitli güvenlik özelliklerini yapılandırır.

Ana Güvenlik Yapılandırmaları:

Güvenlik Başlıkları

Güvenlik başlıkları, tarayıcılara içeriği nasıl işleyecekleri konusunda talimat vererek uygulamanızın güvenliğini artırır. Cross-Site Scripting (XSS), Clickjacking ve MIME türü sniffing gibi çeşitli saldırıları azaltmaya yardımcı olurlar:

  • Content Security Policy (CSP)
  • X-Frame-Options
  • X-Content-Type-Options
  • Strict-Transport-Security (HSTS)
  • Referrer Policy

Örnekler:

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...
],
},
]
},
}
Görüntü Optimizasyonu Ayarları

Next.js, performans için görüntüleri optimize eder, ancak yanlış yapılandırmalar güvenlik açıklarına yol açabilir, örneğin, güvenilmeyen kaynakların kötü niyetli içerik enjekte etmesine izin vermek.

Kötü Yapılandırma Örneği:

javascript
// next.config.js

module.exports = {
images: {
domains: ["*"], // Allows images from any domain
},
}

Sorun:

  • '*': Resimlerin herhangi bir dış kaynaktan, güvenilmeyen veya kötü niyetli alanlardan yüklenmesine izin verir. Saldırganlar, kötü niyetli yükler veya kullanıcıları yanıltan içerikler içeren resimleri barındırabilir.
  • Başka bir sorun, herkesin bir resim yükleyebileceği bir alanın izin verilmesidir (örneğin raw.githubusercontent.com).

Saldırganların bunu nasıl kötüye kullandığı:

Kötü niyetli kaynaklardan resimler enjekte ederek, saldırganlar kimlik avı saldırıları gerçekleştirebilir, yanıltıcı bilgiler gösterebilir veya resim işleme kütüphanelerindeki zafiyetleri istismar edebilir.

Ortam Değişkenlerinin Açığa Çıkması

API anahtarları ve veritabanı kimlik bilgileri gibi hassas bilgileri, istemciye açığa çıkarmadan güvenli bir şekilde yönetin.

a. Hassas Değişkenlerin Açığa Çıkması

Kötü Yapılandırma Örneği:

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: NEXT_PUBLIC_ ön eki olmadan, Next.js değişkenleri istemciye açmaz. Ancak, yanlışlıkla ön ek verilirse (örneğin, NEXT_PUBLIC_SECRET_API_KEY), istemci tarafında erişilebilir hale gelir.

How attackers abuse it:

Eğer hassas değişkenler istemciye açılırsa, saldırganlar bunları istemci tarafı kodunu veya ağ isteklerini inceleyerek alabilir, API'lere, veritabanlarına veya diğer hizmetlere yetkisiz erişim kazanabilirler.

Redirects

Uygulamanız içinde URL yönlendirmelerini ve yeniden yazmalarını yönetin, kullanıcıların uygun şekilde yönlendirilmesini sağlayın ve açık yönlendirme güvenlik açıkları oluşturmaktan kaçının.

a. Open Redirect Vulnerability

Bad Configuration Example:

javascript
// next.config.js

module.exports = {
async redirects() {
return [
{
source: "/redirect",
destination: (req) => req.query.url, // Dynamically redirects based on query parameter
permanent: false,
},
]
},
}

Sorun:

  • Dinamik Hedef: Kullanıcıların herhangi bir URL belirtmesine izin verir, bu da açık yönlendirme saldırılarına olanak tanır.
  • Kullanıcı Girdisine Güvenme: Kullanıcılar tarafından sağlanan URL'lere doğrulama olmadan yönlendirme yapmak, kimlik avı, kötü amaçlı yazılım dağıtımı veya kimlik bilgisi hırsızlığına yol açabilir.

Saldırganların bunu nasıl kötüye kullandığı:

Saldırganlar, sizin alan adınızdan geliyormuş gibi görünen URL'ler oluşturabilir, ancak kullanıcıları kötü amaçlı sitelere yönlendirebilir. Örneğin:

bash
https://yourdomain.com/redirect?url=https://malicious-site.com

Kullanıcılar, orijinal alan adına güvenerek, farkında olmadan zararlı web sitelerine gidebilirler.

Webpack Yapılandırması

Next.js uygulamanız için Webpack yapılandırmalarını özelleştirin; bu, dikkatli bir şekilde ele alınmadığında güvenlik açıkları oluşturabilir.

a. Hassas Modülleri Açığa Çıkarma

Kötü Yapılandırma Örneği:

javascript
// next.config.js

module.exports = {
webpack: (config, { isServer }) => {
if (!isServer) {
config.resolve.alias["@sensitive"] = path.join(__dirname, "secret-folder")
}
return config
},
}

Sorun:

  • Hassas Yolları Açığa Çıkarma: Hassas dizinlerin takma adını vermek ve istemci tarafı erişimine izin vermek, gizli bilgilerin sızmasına neden olabilir.
  • Sırları Paketleme: Hassas dosyalar istemci için paketlenirse, içerikleri kaynak haritaları veya istemci tarafı kodunu inceleyerek erişilebilir hale gelir.

Saldırganların bunu nasıl kötüye kullandığı:

Saldırganlar, uygulamanın dizin yapısına erişebilir veya bunu yeniden oluşturabilir, bu da hassas dosyaları veya verileri bulup istismar etmelerini sağlayabilir.

pages/_app.js ve pages/_document.js

pages/_app.js

Amaç: Varsayılan App bileşenini geçersiz kılar, global durum, stiller ve düzen bileşenleri için olanak tanır.

Kullanım Durumları:

  • Global CSS ekleme.
  • Düzen sarmalayıcıları ekleme.
  • Durum yönetim kütüphanelerini entegre etme.

Örnek:

jsx
// pages/_app.js
import "../styles/globals.css"

function MyApp({ Component, pageProps }) {
return <Component {...pageProps} />
}

export default MyApp

pages/_document.js

Amaç: Varsayılan Belgeyi geçersiz kılar, HTML ve Body etiketlerinin özelleştirilmesine olanak tanır.

Kullanım Durumları:

  • <html> veya <body> etiketlerini değiştirme.
  • Meta etiketleri veya özel betikler ekleme.
  • Üçüncü taraf yazı tiplerini entegre etme.

Örnek:

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

Özel Sunucu (İsteğe Bağlı)

Amaç: Next.js yerleşik bir sunucu ile birlikte gelse de, özel yönlendirme veya mevcut arka uç hizmetleri ile entegrasyon gibi gelişmiş kullanım senaryoları için özel bir sunucu oluşturabilirsiniz.

Not: Özel bir sunucu kullanmak, özellikle Next.js'in yerleşik sunucusu için optimize edilen Vercel gibi platformlarda dağıtım seçeneklerini sınırlayabilir.

Örnek:

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")
})
})

Ek Mimari ve Güvenlik Dikkatleri

Ortam Değişkenleri ve Konfigürasyon

Amaç: Hassas bilgileri ve konfigürasyon ayarlarını kod tabanının dışında yönetmek.

En İyi Uygulamalar:

  • .env Dosyalarını Kullanın: API anahtarları gibi değişkenleri .env.local içinde saklayın (versiyon kontrolünden hariç).
  • Değişkenlere Güvenli Erişim: Ortam değişkenlerine erişmek için process.env.VARIABLE_NAME kullanın.
  • Gizli Bilgileri İstemci Tarafında Asla Açığa Çıkarmayın: Hassas değişkenlerin yalnızca sunucu tarafında kullanıldığından emin olun.

Örnek:

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
},
}

Not: Değişkenleri yalnızca sunucu tarafında kısıtlamak için, env nesnesinden çıkarın veya istemciye maruz kalma için NEXT_PUBLIC_ ile öne ekleyin.

Kimlik Doğrulama ve Yetkilendirme

Yaklaşım:

  • Oturum Tabanlı Kimlik Doğrulama: Kullanıcı oturumlarını yönetmek için çerezleri kullanın.
  • Token Tabanlı Kimlik Doğrulama: Durumsuz kimlik doğrulama için JWT'leri uygulayın.
  • Üçüncü Taraf Sağlayıcılar: next-auth gibi kütüphaneler kullanarak OAuth sağlayıcılarıyla (örn., Google, GitHub) entegre edin.

Güvenlik Uygulamaları:

  • Güvenli Çerezler: HttpOnly, Secure ve SameSite niteliklerini ayarlayın.
  • Şifre Hashleme: Şifreleri saklamadan önce her zaman hashleyin.
  • Girdi Doğrulama: Girdi doğrulama ve temizleme ile enjeksiyon saldırılarını önleyin.

Örnek:

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" })
}
}

Performans Optimizasyonu

Stratejiler:

  • Görüntü Optimizasyonu: Otomatik görüntü optimizasyonu için Next.js'in next/image bileşenini kullanın.
  • Kod Bölme: Dinamik içe aktarmaları kullanarak kodu bölün ve başlangıç yükleme sürelerini azaltın.
  • Önbellekleme: API yanıtları ve statik varlıklar için önbellekleme stratejileri uygulayın.
  • Tembel Yükleme: Bileşenleri veya varlıkları yalnızca ihtiyaç duyulduğunda yükleyin.

Örnek:

jsx
// Dynamic Import with Code Splitting
import dynamic from "next/dynamic"

const HeavyComponent = dynamic(() => import("../components/HeavyComponent"), {
loading: () => <p>Loading...</p>,
})

tip

AWS Hacking'i öğrenin ve pratik yapın:HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking'i öğrenin ve pratik yapın: HackTricks Training GCP Red Team Expert (GRTE)

HackTricks'i Destekleyin