NextJS

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) Azure Hacking’i öğrenin ve pratik yapın: HackTricks Training Azure Red Team Expert (AzRTE)

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:

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 Klasörler ve Dosyalar

  • public/: Görseller, fontlar ve diğer dosyalar gibi statik varlıkları barındırır. Buradaki dosyalara kök yolundan (/) erişilebilir.
  • app/: Uygulamanızın sayfaları, layout’ları, bileşenleri ve API route’ları için merkezi dizindir. App Router paradigmasını benimser; gelişmiş yönlendirme özellikleri ve sunucu-istemci bileşen ayrımını sağlar.
  • app/layout.tsx: Uygulamanız için kök layout’u tanımlar; tüm sayfaları sarar ve header, footer ve navigasyon çubukları gibi tutarlı UI öğelerini sağlar.
  • app/page.tsx: Kök rota / için giriş noktası olarak hizmet eder ve ana sayfayı render eder.
  • app/[route]/page.tsx: Statik ve dinamik rotaları ele alır. app/ içindeki her klasör bir rota segmentini temsil eder ve bu klasörlerdeki page.tsx o rotanın bileşenine karşılık gelir.
  • app/api/: HTTP isteklerini işleyen serverless fonksiyonları oluşturmanıza olanak tanıyan API route’larını içerir. Bu route’lar geleneksel pages/api dizininin yerini alır.
  • app/components/: Farklı sayfalar ve layout’lar arasında kullanılabilecek yeniden kullanılabilir React bileşenlerini barındırır.
  • app/styles/: Küresel CSS dosyalarını ve bileşen bazlı stil için CSS Modules’ları içerir.
  • app/utils/: Uygulama genelinde paylaşılabilecek yardımcı fonksiyonlar, yardımcı modüller ve diğer UI dışı mantıkları içerir.
  • .env.local: Yerel geliştirme ortamına özgü environment değişkenlerini depolar. Bu değişkenler versiyon kontrolüne eklenmez.
  • next.config.js: webpack yapılandırmaları, environment değişkenleri ve güvenlik ayarları dahil olmak üzere Next.js davranışını özelleştirir.
  • tsconfig.json: Proje için TypeScript ayarlarını yapılandırır; tip kontrolü ve diğer TypeScript özelliklerini etkinleştirir.
  • package.json: Proje bağımlılıklarını, script’leri ve metadata’yı yönetir.
  • README.md: Kurulum talimatları, kullanım yönergeleri ve diğer ilgili detaylar dahil olmak üzere proje hakkında dokümantasyon ve bilgi sağlar.
  • 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 Dizininin Dosya Tabanlı Yönlendirmesi

app dizini, en son Next.js sürümlerinde yönlendirmenin temel taşını oluşturur. Rotaları tanımlamak için dosya sisteminden yararlanır; bu da rota yönetimini sezgisel ve ölçeklenebilir kılar.

Kök Yol / ile Baş Etme

Dosya Yapısı:

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

Ana Dosyalar:

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

Uygulama:

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:

  • Rota Tanımı: page.tsx dosyası app dizininin hemen altında yer alır ve / rotasına karşılık gelir.
  • Render Etme: Bu bileşen ana sayfa için içeriği render eder.
  • Layout Entegrasyonu: HomePage bileşeni layout.tsx ile sarılır; bu, başlıklar, altbilgiler ve diğer ortak öğeleri içerebilir.
Diğer Statik Yolların Yönetimi

Örnek: /about Rotası

Dosya Yapısı:

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

Uygulama:

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

  • Rota Tanımı: page.tsx dosyası about klasörü içinde /about rotasına karşılık gelir.
  • Renderleme: Bu bileşen about sayfasının içeriğini render eder.
Dynamic Routes

Dinamik rotalar, değişken segmentlere sahip yolları işlemeyi sağlar; uygulamaların ID’ler, slug’lar vb. gibi parametrelere göre içerik göstermesine olanak verir.

Örnek: /posts/[id] Rotası

Dosya Yapısı:

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

Uygulama:

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] rota içindeki dinamik bir segmenti belirtir ve URL’den id parametresini yakalar.
  • Parametrelere Erişim: params objesi, bileşen içinde erişilebilen dinamik parametreleri içerir.
  • Rota Eşleşmesi: /posts/* ile eşleşen herhangi bir yol, ör. /posts/1, /posts/abc, vb., bu bileşen tarafından işlenecektir.
İç İçe Rotalar

Next.js, dizin yapısını yansıtan hiyerarşik rota yapılarına izin veren iç içe yönlendirmeyi destekler.

Örnek: /dashboard/settings/profile Rotası

Dosya Yapısı:

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

Uygulama:

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 İç İçe 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 ve açıklığı artırır.
Catch-All Rotaları

Catch-all rotaları birden fazla iç içe geçmiş segmenti veya bilinmeyen yolları işler, rota yönetiminde esneklik sağlar.

Örnek: /* Rota

Dosya Yapısı:

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

Uygulama:

// 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 kategoriler gibi dinamik yönlendirme senaryolarını işlemek için faydalıdır.
  • Rota Eşlemesi: /anything/here, /foo/bar/baz gibi yollar bu bileşen tarafından işlenir.

Potansiyel İstemci Tarafı Zayıflıkları

Next.js güvenli bir temel sağlasa da, yanlış kodlama uygulamaları zayıflıkların ortaya çıkmasına neden olabilir. Önemli istemci tarafı zayıflıkları şunlardır:

Cross-Site Scripting (XSS)

XSS saldırıları, kötü niyetli scriptlerin güvenilir web sitelerine enjekte edilmesiyle meydana gelir. Saldırganlar, kullanıcıların tarayıcılarında scriptleri çalıştırarak veri çalabilir veya kullanıcının adına işlemler gerçekleştirebilir.

Zayıf Kod Örneği:

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

Neden Güvenli Değildir: dangerouslySetInnerHTML’i güvenilmeyen girdilerle kullanmak, saldırganların kötü amaçlı scriptler enjekte etmesine olanak tanır.

Client-Side Template Injection

Kullanıcı girdileri şablonlarda yanlış işlendiğinde meydana gelir; bu da saldırganların şablonlar veya ifadeler enjekte edip çalıştırmasına izin verir.

Zayıf Kod Örneği:

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

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

Neden Güvenlik Açığı Var: Eğer template veya data zararlı içerik içeriyorsa, bu istemeden code yürütülmesine yol açabilir.

Client Path Traversal

Bu, saldırganların istemci tarafı yollarını manipüle ederek Cross-Site Request Forgery (CSRF) gibi istenmeyen eylemleri gerçekleştirmesine izin veren bir zafiyettir. Sunucunun dosya sistemini hedef alan server-side path traversal’dan farklı olarak, CSPT meşru API isteklerini kötü niyetli endpoints’e yönlendirmek için istemci tarafı mekanizmalarını istismar etmeye odaklanır.

Kırılgan Code Örneği:

Bir Next.js uygulaması kullanıcılara dosya yükleme ve indirme imkanı sağlar. İndirme özelliği istemci tarafında uygulanmıştır; kullanıcılar indirmek istedikleri dosyanın yolunu belirtebilir.

// 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ırgan Senaryosu

  1. Saldırganın Hedefi: filePath’ı manipüle ederek kritik bir dosyayı (ör. admin/config.json) silmek amacıyla bir CSRF saldırısı gerçekleştirmek.
  2. CSPT’yi Sömürme:
  • Kötü Amaçlı Girdi: Saldırgan, ../deleteFile/config.json gibi manipüle edilmiş bir filePath içeren bir URL hazırlar.
  • Ortaya Çıkan API Çağrısı: İstemci tarafı kodu /api/files/../deleteFile/config.json adresine bir istek yapar.
  • Sunucunun İşleyişi: Sunucu filePath’ı doğrulamazsa isteği işler ve hassas dosyaları silebilir veya ifşa edebilir.
  1. CSRF’yi Gerçekleştirme:
  • Oluşturulmuş Bağlantı: Saldırgan, kurbana manipüle edilmiş filePath ile indirme isteğini tetikleyen bir bağlantı gönderir veya kötü amaçlı bir script gömer.
  • Sonuç: Kurban farkında olmadan işlemi gerçekleştirir; bu da yetkisiz dosya erişimine veya silinmesine yol açar.

Neden Savunmasız

  • Girdi Doğrulama Eksikliği: İstemci tarafı rastgele filePath girdilerine izin verir; bu da path traversal’a olanak tanır.
  • İstemci Girdilerine Güvenme: Sunucu tarafı API, filePath’ı sanitize etmeden güvenip işler.
  • Olası API Eylemleri: API endpoint’i durum değiştiren eylemler yapıyorsa (ör. dosya silme, değiştirme), CSPT aracılığıyla istismar edilebilir.

Next.js’te Sunucu Tarafı

Sunucu Tarafı Rendering (SSR)

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

Kullanım Durumları:

  • Sık değişen dinamik içerikler.
  • SEO optimizasyonu; çünkü arama motorları tam render edilmiş sayfayı tarayabilir.

Uygulama:

// 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 Oluşturma (SSG)

Sayfalar build zamanında önceden render edilir; bu da daha hızlı yükleme süreleri ve azalan sunucu yükü sağlar.

Kullanım Alanları:

  • Sık değişmeyen içerik.
  • Bloglar, dokümantasyon, pazarlama sayfaları.

Uygulama:

// 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 Fonksiyonlar (API Routes)

Next.js, serverless fonksiyonlar olarak API uç noktaları oluşturulmasına izin verir. Bu fonksiyonlar talep üzerine çalışır ve özel bir sunucuya ihtiyaç duymaz.

Kullanım Durumları:

  • Form gönderimlerini işleme.
  • Veritabanları ile etkileşim.
  • Veri işleme veya üçüncü taraf API’lerle entegrasyon.

Uygulama:

Next.js 13’te app dizininin tanıtılmasıyla, routing ve API işlemleri daha esnek ve güçlü hale geldi. Bu modern yaklaşım dosya tabanlı routing sistemiyle yakından uyumlu olmakla birlikte, server ve client komponentlerini destekleme dahil olmak üzere geliştirilmiş yetenekler sunar.

Temel Rota İşleyici

Dosya Yapısı:

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

Uygulama:

// 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 rotaları app/api/ dizini altında yer alır.
  • Dosya Adlandırma: Her API endpoint’i kendi klasöründe bulunur ve içinde route.js veya route.ts dosyası bulunur.
  • Dışa Aktarılan Fonksiyonlar: Tek bir default export yerine, belirli HTTP yöntemlerini (ör. GET, POST) tanımlayan fonksiyonlar export edilir.
  • Yanıt İşleme: Yanıtları döndürmek için Response constructor’ını kullanın; bu başlıklar ve durum kodları üzerinde daha fazla kontrol sağlar.

Diğer yollar ve yöntemler nasıl ele alınır:

Belirli HTTP Yöntemlerini Ele Alma

Next.js 13+ aynı route.js veya route.ts dosyası içinde belirli HTTP yöntemleri için işleyiciler tanımlamanıza izin verir; bu, daha açık ve düzenli kod sağlar.

Örnek:

// 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 Exports: Her HTTP yöntemi (GET, PUT, DELETE) kendi exported function’ına sahiptir.
  • Parametreler: İkinci argüman, params üzerinden route parametrelerine erişim sağlar.
  • Geliştirilmiş Yanıtlar: response object’ları üzerinde daha fazla kontrol sunar; header ve status code yönetiminde hassasiyet sağlar.
Catch-All ve Nested Rotalar

Next.js 13+ catch-all rotalar ve nested API rotaları gibi gelişmiş routing özelliklerini destekler; bu, daha dinamik ve ölçeklenebilir API yapıları oluşturmayı sağlar.

Catch-All Route Example:

// 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 catch-all segmentini belirtir.
  • Kullanım: Farklı rota derinliklerini veya dinamik segmentleri işlemeleri gereken API’ler için kullanışlıdır.

İç İçe Rotalar Örneği:

// 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 İç İçe Yapılar: Kaynak ilişkilerini yansıtarak hiyerarşik API yapıları oluşturmayı sağlar.
  • Parametre Erişimi: params nesnesi aracılığıyla birden fazla rota parametresine kolayca erişin.
Next.js 12 ve Öncesinde API yollarını Yönetme

pages Dizinindeki API Yolları (Next.js 12 ve Öncesi)

Next.js 13 app dizinini ve geliştirilmiş yönlendirme yeteneklerini tanıtmadan önce, API yolları öncelikle pages dizini içinde tanımlanıyordu. Bu yaklaşım hâlâ Next.js 12 ve öncesi sürümlerde yaygın olarak kullanılır ve desteklenir.

Temel API Yolu

Dosya Yapısı:

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

Uygulama:

javascriptCopy code// pages/api/hello.js

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

Açıklama:

  • Konum: API route’ları pages/api/ dizini altında bulunur.
  • Dışa aktarma: İşleyici fonksiyonunu tanımlamak için export default kullanın.
  • Fonksiyon İmzası: İşleyici req (HTTP request) ve res (HTTP response) nesnelerini alır.
  • Yönlendirme: Dosya adı (hello.js) /api/hello endpoint’ine karşılık gelir.

Dinamik API Rotaları

Dosya Yapısı:

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

Uygulama:

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: Köşeli parantezler ([id].js) dinamik route segmentlerini belirtir.
  • Parametrelere Erişim: Dinamik parametreye erişmek için req.query.id kullanın.
  • Metodları Yönetme: Farklı HTTP yöntemlerini (GET, PUT, DELETE, vb.) işlemek için koşullu mantık kullanın.

Farklı HTTP Yöntemlerini İşleme

Temel API route örneği tüm HTTP yöntemlerini tek bir fonksiyon içinde ele alırken, kodunuzu her yöntemi açıkça ele alacak şekilde yapılandırarak daha iyi açıklık ve sürdürülebilirlik sağlayabilirsiniz.

Örnek:

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:

  • Separation of Concerns: Farklı HTTP yöntemlerine ait mantığı açıkça ayırın.
  • Response Consistency: İstemci tarafı işlemlerini kolaylaştırmak için yanıt yapılarında tutarlılık sağlayın.
  • Error Handling: Desteklenmeyen yöntemleri ve beklenmeyen hataları uygun şekilde ele alın.

CORS Yapılandırması

API rotalarınıza hangi originlerin erişebileceğini kontrol ederek Cross-Origin Resource Sharing (CORS) güvenlik açıklarını azaltın.

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

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

Unutmayın ki CORS tüm API routes’larında da yapılandırılabilir middleware.ts dosyası içinde:

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

Sorun:

  • Access-Control-Allow-Origin: '*': Herhangi bir web sitesinin API’ye erişmesine izin verir; potansiyel olarak kötü amaçlı sitelerin API’nizle sınırlama olmadan etkileşim kurmasına olanak tanır.
  • Geniş Yöntem İzni: Tüm yöntemlere izin vermek, saldırganların istenmeyen eylemler gerçekleştirmesine olanak sağlayabilir.

Saldırganların bunu suistimal etme şekli:

Saldırganlar, API’nize istek yapan kötü amaçlı web siteleri oluşturabilir; bu, veri alma, veri manipülasyonu veya yetkili kullanıcılar adına istenmeyen eylemleri tetikleme gibi işlevlerin kötüye kullanılmasına yol açabilir.

CORS - Misconfigurations & Bypass

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

Sunucu tarafından kullanılan kodun istemci tarafında açığa çıkan ve kullanılan koda kolayca dahil edilmesi mümkündür. Bir kod dosyasının istemci tarafında asla açığa çıkmamasını sağlamak için dosyanın başında şu import’u kullanmak en iyi yoldur:

import "server-only"

Ana Dosyalar ve Roller

middleware.ts / middleware.js

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

Amaç: İstek işlenmeden önce sunucu tarafında serverless fonksiyon içinde kod çalıştırır; kimlik doğrulama, yönlendirmeler veya yanıtları değiştirme gibi görevleri gerçekleştirmeye izin verir.

Çalışma Akışı:

  1. Gelen İstek: middleware isteği yakalar.
  2. İşleme: İstek bazlı işlemler gerçekleştirir (ör. kimlik doğrulamasını kontrol etme).
  3. Yanıtın Değiştirilmesi: Yanıtı değiştirebilir veya kontrolü sonraki işleyiciye aktarabilir.

Örnek Kullanım Durumları:

  • Yetkilendirilmemiş kullanıcıları yönlendirme.
  • Özel header’lar ekleme.
  • İstekleri kaydetme.

Örnek Yapılandırma:

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

Location: Projenin kökü.

Purpose: Next.js davranışını yapılandırır; özellikleri etkinleştirme/devre dışı bırakma, webpack yapılandırmalarını özelleştirme, ortam değişkenlerini ayarlama ve çeşitli güvenlik özelliklerini yapılandırma.

Key Security Configurations:

Güvenlik Başlıkları

Güvenlik başlıkları, tarayıcılara içeriği nasıl işleyeceklerini bildirerek uygulamanızın güvenliğini artırır. Bu başlıklar Cross-Site Scripting (XSS), Clickjacking ve MIME type sniffing gibi çeşitli saldırıları hafifletmeye yardımcı olur:

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

Örnekler:

// 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üvensiz kaynakların kötü amaçlı içerik enjekte etmesine izin verme gibi.

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

// next.config.js

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

Sorun:

  • '*': Görsellerin güvenilmeyen veya kötü amaçlı alanlar dahil olmak üzere herhangi bir dış kaynaktan yüklenmesine izin verir. Saldırganlar, kötü amaçlı yük veya kullanıcıları yanıltan içerik barındıran görseller barındırabilir.
  • Diğer bir sorun, bir alan adının herkesin bir görsel yükleyebileceği şekilde izin verilmesi olabilir (ör. raw.githubusercontent.com)

Saldırganlar bunu nasıl kötüye kullanır:

Kötü amaçlı kaynaklardan gelen görselleri enjekte ederek saldırganlar phishing saldırıları gerçekleştirebilir, yanıltıcı bilgi gösterebilir veya görsel işleme kütüphanelerindeki güvenlik açıklarını istismar edebilir.

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

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

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

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

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

Sorun:

  • SECRET_API_KEY: NEXT_PUBLIC_ öneki olmadan Next.js değişkenleri istemciye açmaz. Ancak yanlışlıkla önek eklendiğinde (ör. NEXT_PUBLIC_SECRET_API_KEY), bu değişken istemci tarafında erişilebilir hale gelir.

Saldırganlar bunu nasıl kötüye kullanır:

Eğer hassas değişkenler istemciye açılırsa, saldırganlar istemci tarafı kodunu veya ağ isteklerini inceleyerek bunları elde edebilir ve API’lara, veritabanlarına veya diğer servislere yetkisiz erişim sağlayabilir.

Redirects

Uygulamanız içinde URL yönlendirmelerini ve yeniden yazımları yönetin; kullanıcıların uygun şekilde yönlendirildiğinden emin olun ve open redirect vulnerabilities riskini önleyin.

a. Open Redirect Vulnerability

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

// 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 open redirect saldırılarına olanak tanır.
  • Kullanıcı Girdisine Güvenme: Kullanıcılar tarafından sağlanan URL’lere doğrulama olmadan yapılan yönlendirmeler phishing, malware distribution veya credential theft’e yol açabilir.

Saldırganlar bunu nasıl kötüye kullanır:

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

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

Orijinal alan adına güvenen kullanıcılar farkında olmadan zararlı web sitelerine yönlendirilebilir.

Webpack Yapılandırması

Next.js uygulamanız için Webpack yapılandırmalarını özelleştirmek, dikkatli kullanılmazsa istemeden güvenlik açıklarına yol açabilir.

a. Hassas Modüllerin Açığa Çıkarılması

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

// next.config.js

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

Sorun:

  • Hassas Yolların Açığa Çıkarılması: Hassas dizinlere alias atanması ve istemci tarafı erişimine izin verilmesi gizli bilgilerin leak olmasına neden olabilir.
  • Gizlerin Paketlenmesi: Eğer hassas dosyalar istemci için paketlenirse, içerikleri source maps veya istemci tarafı kodunun incelenmesi yoluyla erişilebilir hale gelir.

Saldırganlar Bunu Nasıl Kötüye Kullanır:

Saldırganlar uygulamanın dizin yapısına erişebilir veya yeniden oluşturabilir; potansiyel olarak hassas dosyaları veya verileri bulup istismar edebilirler.

pages/_app.js and pages/_document.js

pages/_app.js

Amacı: Varsayılan App bileşenini geçersiz kılar; global state, stiller ve layout bileşenlerine izin verir.

Kullanım Durumları:

  • Küresel CSS ekleme.
  • Layout sarmalayıcıları ekleme.
  • Durum yönetimi (state management) kütüphanelerini entegre etme.

Örnek:

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

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

export default MyApp

pages/_document.js

Amaç: Varsayılan Document’i geçersiz kılar, <html> ve <body> etiketlerinin özelleştirilmesine izin verir.

Kullanım Senaryoları:

  • <html> veya <body> etiketlerini değiştirmek.
  • Meta etiketleri veya özel scriptler eklemek.
  • Üçüncü taraf yazı tiplerini entegre etmek.

Örnek:

// 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 sunucuyla gelirken, özel yönlendirme veya mevcut backend servisleriyle entegrasyon gibi gelişmiş kullanım senaryoları için özel bir sunucu oluşturabilirsiniz.

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

Örnek:

// 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 Hususları

Ortam Değişkenleri ve Yapılandırma

Amaç: Hassas bilgileri ve yapılandırma 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 (sürüm 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:

// 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 sınırlamak için, onları env nesnesinden çıkarın veya istemciye açmak için NEXT_PUBLIC_ ile önekleyin.

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 (ör. Google, GitHub) entegre edin.

Güvenlik Uygulamaları:

  • Güvenli Çerezler: HttpOnly, Secure ve SameSite özniteliklerini ayarlayın.
  • Parola Hashleme: Parolaları depolamadan önce her zaman hashleyin.
  • Girdi Doğrulama: Girdileri doğrulayarak ve temizleyerek enjeksiyon saldırılarını önleyin.

Örnek:

// 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 importları kullanarak kodu bölün ve ilk 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 gerektiğinde yükleyin.

Örnek:

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

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

Next.js Server Actions Enumeration (hash to function name via source maps)

Modern Next.js uses “Server Actions” that execute on the server but are invoked from the client. In production these invocations are opaque: all POSTs land on a common endpoint and are distinguished by a build-specific hash sent in the Next-Action header. Örnek:

POST /
Next-Action: a9f8e2b4c7d1...

productionBrowserSourceMaps etkinleştirildiğinde, minified JS parçaları createServerReference(...) çağrılarını içerir; bunlar action hash ile orijinal fonksiyon adı arasındaki eşlemeyi geri kazanmak için yeterli yapı (ve ilişkili source map’ler) leak eder. Bu, Next-Action’ta gözlemlenen hash’leri deleteUserAccount() veya exportFinancialData() gibi somut hedeflere çevirmenizi sağlar.

Çıkarma yaklaşımı (minified JS üzerinde regex + isteğe bağlı source map’ler)

İndirilen JS parçalarında createServerReference arayın ve hash ile fonksiyon/kaynak sembolünü çıkarın. İki kullanışlı desen:

# Strict pattern for standard minification
createServerReference\)"([a-f0-9]{40,})",\w+\.callServer,void 0,\w+\.findSourceMapURL,"([^"]+)"\)

# Flexible pattern handling various minification styles
createServerReference[^\"]*"([a-f0-9]{40,})"[^\"]*"([^"]+)"\s*\)
  • Grup 1: server action hash (40+ hex chars)
  • Grup 2: sembol veya, source map mevcutsa orijinal fonksiyon adına çözülebilen yol

If the script advertises a source map (trailer comment //# sourceMappingURL=<...>.map), fetch it and resolve the symbol/path to the original function name.

Pratik iş akışı

  • Gözatma sırasında pasif keşif: istekleri Next-Action header’ları ve JS chunk URL’leri ile yakalayın.
  • Başvurulan JS bundle’larını ve beraberindeki *.map dosyalarını (varsa) çekin.
  • Yukarıdaki regex’i çalıştırarak bir hash↔isim sözlüğü oluşturun.
  • Test hedeflemede sözlüğü kullanın:
    • İsim tabanlı triage (ör. transferFunds, exportFinancialData).
    • Fonksiyon ismine göre build’ler arası kapsamı takip edin (hash’ler build’ler arasında döner).

Gizli actions’ları çalıştırma (şablon-temelli istek)

Proxy’de gözlemlenen geçerli bir POST’u şablon olarak alın ve başka bir keşfedilmiş action’ı hedeflemek için Next-Action değerini değiştirin:

# Before
Next-Action: a9f8e2b4c7d1

# After
Next-Action: b7e3f9a2d8c5

Repeater’da yeniden oynatın ve aksi takdirde erişilemeyen eylemlerin yetkilendirmesini, giriş doğrulamasını ve iş mantığını test edin.

Burp otomasyonu

  • NextjsServerActionAnalyzer (Burp uzantısı) yukarıdakileri Burp içinde otomatikleştirir:
  • JS chunk’ları için proxy geçmişini tarar, createServerReference(...) girdilerini çıkarır ve mevcutsa source map’leri çözer.
  • Aranabilir bir hash↔function-name sözlüğü tutar ve function name’e göre build’ler arasında yinelenenleri kaldırır.
  • Geçerli bir template POST’u bulup hedef action’ın hash’i yerleştirilmiş, gönderilmeye hazır bir Repeater sekmesi açabilir.
  • Repo: https://github.com/Adversis/NextjsServerActionAnalyzer

Notlar ve sınırlamalar

  • İsimleri bundle/source map’lerinden kurtarmak için production’da productionBrowserSourceMaps etkin olmasını gerektirir.
  • Function-name disclosure tek başına bir güvenlik açığı değildir; bunu keşfi yönlendirmek ve her action’ın yetkilendirmesini test etmek için kullanın.

React Server Components Flight protocol deserialization RCE (CVE-2025-55182)

Next.js App Router dağıtımları, Server Actions’ı react-server-dom-webpack 19.0.0–19.2.0 (Next.js 15.x/16.x) üzerinde açığa çıkarıyorsa, Flight chunk deserialization sırasında kritik bir server-side prototype pollution içerir. Bir Flight payload’u içinde $ referansları oluşturarak bir saldırgan, kirlenmiş prototiplerden rastgele JavaScript yürütmeye ve ardından Node.js sürecinde OS komut yürütmeye pivot yapabilir.

NodeJS - proto & prototype Pollution

Flight chunk’larındaki saldırı zinciri

  1. Prototype pollution primitive: Set "then": "$1:__proto__:then" so that the resolver writes a then function on Object.prototype. Sonrasında işlenen herhangi bir düz nesne thenable hâline gelir ve saldırganın RSC iç mantığındaki async kontrol akışını etkilemesine izin verir.
  2. Rebinding to the global Function constructor: Point _response._formData.get at "$1:constructor:constructor". Çözümleme sırasında, object.constructorObject, ve Object.constructorFunction olacağından, gelecekte _formData.get() çağrıları aslında Function(...) çalıştırır.
  3. Code execution via _prefix: Place JavaScript source in _response._prefix. Kirlenmiş _formData.get çağrıldığında framework Function(_prefix)(...) değerlendirmesini yapar, bu yüzden enjekte edilen JS require('child_process').exec() veya başka herhangi bir Node ilkelini çalıştırabilir.

Payload skeleton

{
"then": "$1:__proto__:then",
"status": "resolved_model",
"reason": -1,
"value": "{\"then\":\"$B1337\"}",
"_response": {
"_prefix": "require('child_process').exec('id')",
"_chunks": "$Q2",
"_formData": { "get": "$1:constructor:constructor" }
}
}

React Server Function maruziyetinin haritalanması

React Server Functions (RSF), ‘use server’; yönergesini içeren herhangi bir fonksiyondur. Bu fonksiyonlardan birine bağlı her form action, mutation veya fetch helper, attacker-supplied payload’ları memnuniyetle deserialize edecek bir RSC Flight endpoint’e dönüşür. React2Shell değerlendirmelerinden türetilen faydalı keşif adımları:

  • Statik envanter: Yönergeyi arayın; framework tarafından otomatik olarak kaç RSF’nin açığa çıktığını anlamak için.
rg -n "'use server';" -g"*.{js,ts,jsx,tsx}" app/
  • App Router defaults: create-next-app varsayılan olarak App Router + app/ dizinini etkinleştirir; bu, her route’u sessizce bir RSC-yetkin endpoint’e çevirir. App Router varlıkları (ör. /_next/static/chunks/app/) veya text/x-component üzerinden Flight chunk’larını stream eden yanıtlar güçlü Internet-facing parmak izleridir.
  • Implicitly vulnerable RSC deployments: React’in kendi bildirimi, RSC runtime’ını taşıyan uygulamaların açık RSFs olmadan bile sömürülebilir olabileceğini not eder; bu yüzden react-server-dom-* 19.0.0–19.2.0 kullanan herhangi bir build’i şüpheli sayın.
  • Other frameworks bundling RSC: Vite RSC, Parcel RSC, React Router RSC preview, RedwoodSDK, Waku, vb. aynı serializer’ı yeniden kullanır ve düzeltilmiş React build’lerini embed edene kadar aynı uzak saldırı yüzeyini miras alırlar.

Sürüm kapsamı (React2Shell)

  • react-server-dom-webpack, react-server-dom-parcel, react-server-dom-turbopack: etkilenebilir sürümler 19.0.0, 19.1.0–19.1.1 ve 19.2.0; sırasıyla düzeltilmiş sürümler 19.0.1, 19.1.2 ve 19.2.1.
  • Next.js stable: App Router sürümleri 15.0.0–16.0.6 zayıf RSC yığınını embed eder. Patch trenleri 15.0.5 / 15.1.9 / 15.2.6 / 15.3.6 / 15.4.8 / 15.5.7 / 16.0.7 düzeltilmiş bağımlılıkları içerir; bu nedenle bu sürümlerin altındaki herhangi bir build yüksek değer taşır.
  • Next.js canary: 14.3.0-canary.77+ ayrıca hatalı runtime’ı içerir ve şu anda düzeltilmiş canary drops yok, bu yüzden bu parmak izleri güçlü exploitation adaylarıdır.

Remote detection oracle

Assetnote’ın react2shell-scanner candidate path’lere crafted multipart Flight isteği gönderir ve sunucu tarafı davranışı izler:

  • Default mode deterministik bir RCE payload’u çalıştırır (matematiksel işlem X-Action-Redirect aracılığıyla yansıtılır) ve kod çalıştırmayı kanıtlar.
  • --safe-check mode kasıtlı olarak Flight mesajını bozar; böylece yamalanmış sunucular 200/400 dönerken, zayıf hedefler gövdede E{"digest" alt dizisini içeren HTTP/500 yanıtları verir. Bu (500 + digest) çifti şu anda savunucular tarafından yayımlanan en güvenilir remote oracle’dır.
  • Dahili --waf-bypass, --vercel-waf-bypass ve --windows anahtarları payload düzenini ayarlar, çöp verisi önekler ekler veya işletim sistemi komutlarını değiştirir; böylece gerçek Internet varlıklarını sorgulayabilirsiniz.
python3 scanner.py -u https://target.tld --path /app/api/submit --safe-check
python3 scanner.py -l hosts.txt -t 20 --waf-bypass -o vulnerable.json

Referanslar

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) Azure Hacking’i öğrenin ve pratik yapın: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks'i Destekleyin