NextJS

Reading time: 27 minutes

tip

AWS हैकिंग सीखें और अभ्यास करें:HackTricks Training AWS Red Team Expert (ARTE)
GCP हैकिंग सीखें और अभ्यास करें: HackTricks Training GCP Red Team Expert (GRTE)

HackTricks का समर्थन करें

Next.js एप्लिकेशन की सामान्य आर्किटेक्चर

सामान्य फ़ाइल संरचना

एक मानक Next.js प्रोजेक्ट एक विशिष्ट फ़ाइल और निर्देशिका संरचना का पालन करता है जो इसके फीचर्स जैसे राउटिंग, API एंडपॉइंट्स, और स्थैतिक संपत्ति प्रबंधन को सुविधाजनक बनाता है। यहाँ एक सामान्य लेआउट है:

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

Core Directories and Files

  • public/: स्थिर संपत्तियों जैसे छवियों, फ़ॉन्टों और अन्य फ़ाइलों को होस्ट करता है। यहाँ की फ़ाइलें रूट पथ (/) पर सुलभ हैं।
  • app/: आपके एप्लिकेशन के पृष्ठों, लेआउट, घटकों और API मार्गों के लिए केंद्रीय निर्देशिका। App Router पैरेडाइम को अपनाता है, जो उन्नत रूटिंग सुविधाओं और सर्वर-क्लाइंट घटक पृथक्करण को सक्षम बनाता है।
  • app/layout.tsx: आपके एप्लिकेशन के लिए रूट लेआउट को परिभाषित करता है, सभी पृष्ठों के चारों ओर लपेटता है और हेडर, फुटर और नेविगेशन बार जैसे सुसंगत UI तत्व प्रदान करता है।
  • app/page.tsx: रूट मार्ग / के लिए प्रवेश बिंदु के रूप में कार्य करता है, होम पृष्ठ को रेंडर करता है।
  • app/[route]/page.tsx: स्थिर और गतिशील मार्गों को संभालता है। app/ के भीतर प्रत्येक फ़ोल्डर एक मार्ग खंड का प्रतिनिधित्व करता है, और उन फ़ोल्डरों के भीतर page.tsx उस मार्ग के घटक के अनुरूप होता है।
  • app/api/: API मार्गों को समाहित करता है, जिससे आप HTTP अनुरोधों को संभालने के लिए सर्वरलेस फ़ंक्शन बना सकते हैं। ये मार्ग पारंपरिक pages/api निर्देशिका को प्रतिस्थापित करते हैं।
  • app/components/: पुन: प्रयोज्य React घटकों को समाहित करता है जिन्हें विभिन्न पृष्ठों और लेआउट में उपयोग किया जा सकता है।
  • app/styles/: वैश्विक CSS फ़ाइलें और घटक-स्कोप्ड स्टाइलिंग के लिए CSS मॉड्यूल समाहित करता है।
  • app/utils/: उपयोगिता फ़ंक्शन, सहायक मॉड्यूल और अन्य गैर-UI लॉजिक शामिल करता है जो एप्लिकेशन में साझा किया जा सकता है।
  • .env.local: स्थानीय विकास वातावरण के लिए विशिष्ट पर्यावरण चर संग्रहीत करता है। ये चर संस्करण नियंत्रण में नहीं जोड़े जाते हैं।
  • next.config.js: Next.js के व्यवहार को अनुकूलित करता है, जिसमें webpack कॉन्फ़िगरेशन, पर्यावरण चर और सुरक्षा सेटिंग्स शामिल हैं।
  • tsconfig.json: परियोजना के लिए TypeScript सेटिंग्स को कॉन्फ़िगर करता है, प्रकार जांच और अन्य TypeScript सुविधाओं को सक्षम करता है।
  • package.json: परियोजना की निर्भरताओं, स्क्रिप्टों और मेटाडेटा का प्रबंधन करता है।
  • README.md: परियोजना के बारे में दस्तावेज़ीकरण और जानकारी प्रदान करता है, जिसमें सेटअप निर्देश, उपयोग दिशानिर्देश और अन्य प्रासंगिक विवरण शामिल हैं।
  • yarn.lock / package-lock.json: परियोजना की निर्भरताओं को विशिष्ट संस्करणों पर लॉक करता है, विभिन्न वातावरणों में सुसंगत इंस्टॉलेशन सुनिश्चित करता है।

Client-Side in Next.js

File-Based Routing in the app Directory

app निर्देशिका नवीनतम Next.js संस्करणों में रूटिंग का आधार है। यह फ़ाइल प्रणाली का उपयोग करके मार्गों को परिभाषित करता है, जिससे मार्ग प्रबंधन सहज और स्केलेबल हो जाता है।

Handling the Root Path /

File Structure:

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

मुख्य फ़ाइलें:

  • app/page.tsx: रूट पथ / पर अनुरोधों को संभालता है।
  • app/layout.tsx: एप्लिकेशन के लिए लेआउट को परिभाषित करता है, सभी पृष्ठों के चारों ओर लपेटता है।

कार्यान्वयन:

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

व्याख्या:

  • रूट परिभाषा: app निर्देशिका के ठीक नीचे page.tsx फ़ाइल / रूट के लिए है।
  • रेंडरिंग: यह घटक होम पेज के लिए सामग्री को रेंडर करता है।
  • लेआउट एकीकरण: HomePage घटक layout.tsx द्वारा लिपटा हुआ है, जिसमें हेडर, फुटर और अन्य सामान्य तत्व शामिल हो सकते हैं।
अन्य स्थिर पथों को संभालना

उदाहरण: /about रूट

फ़ाइल संरचना:

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

क्रियान्वयन:

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

व्याख्या:

  • रूट परिभाषा: about फ़ोल्डर के अंदर page.tsx फ़ाइल /about रूट के लिए है।
  • रेंडरिंग: यह घटक अबाउट पृष्ठ के लिए सामग्री को रेंडर करता है।
डायनामिक रूट्स

डायनामिक रूट्स वेरिएबल सेगमेंट के साथ पथों को संभालने की अनुमति देते हैं, जिससे अनुप्रयोगों को आईडी, स्लग आदि जैसे पैरामीटर के आधार पर सामग्री प्रदर्शित करने में सक्षम बनाते हैं।

उदाहरण: /posts/[id] रूट

फ़ाइल संरचना:

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

क्रियान्वयन:

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

व्याख्या:

  • डायनामिक सेगमेंट: [id] एक डायनामिक सेगमेंट को दर्शाता है, जो URL से id पैरामीटर को कैप्चर करता है।
  • पैरामीटर तक पहुँच: params ऑब्जेक्ट में डायनामिक पैरामीटर होते हैं, जो कंपोनेंट के भीतर पहुँच योग्य होते हैं।
  • रूट मिलान: कोई भी पथ जो /posts/* से मेल खाता है, जैसे /posts/1, /posts/abc, आदि, इस कंपोनेंट द्वारा संभाला जाएगा।
नेस्टेड रूट्स

Next.js नेस्टेड रूटिंग का समर्थन करता है, जो हायरार्किकल रूट संरचनाओं की अनुमति देता है जो डायरेक्टरी लेआउट को दर्शाती हैं।

उदाहरण: /dashboard/settings/profile रूट

फाइल संरचना:

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

क्रियान्वयन:

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

व्याख्या:

  • गहरा नेस्टिंग: dashboard/settings/profile/ के अंदर page.tsx फ़ाइल /dashboard/settings/profile रूट के अनुरूप है।
  • हायरार्की परावर्तन: निर्देशिका संरचना URL पथ को दर्शाती है, रखरखाव और स्पष्टता को बढ़ाती है।
कैच-ऑल रूट्स

कैच-ऑल रूट्स कई नेस्टेड सेगमेंट या अज्ञात पथों को संभालते हैं, रूट हैंडलिंग में लचीलापन प्रदान करते हैं।

उदाहरण: /* रूट

फ़ाइल संरचना:

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

क्रियान्वयन:

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

व्याख्या:

  • कैच-ऑल खंड: [...slug] सभी शेष पथ खंडों को एक ऐरे के रूप में कैप्चर करता है।
  • उपयोग: उपयोगकर्ता-जनित पथ, नेस्टेड श्रेणियों आदि जैसे गतिशील रूटिंग परिदृश्यों को संभालने के लिए उपयोगी।
  • रूट मिलान: /anything/here, /foo/bar/baz जैसे पथ इस घटक द्वारा संभाले जाते हैं।

संभावित क्लाइंट-साइड कमजोरियाँ

हालांकि Next.js एक सुरक्षित आधार प्रदान करता है, गलत कोडिंग प्रथाएँ कमजोरियों को पेश कर सकती हैं। प्रमुख क्लाइंट-साइड कमजोरियों में शामिल हैं:

क्रॉस-साइट स्क्रिप्टिंग (XSS)

XSS हमले तब होते हैं जब दुर्भावनापूर्ण स्क्रिप्ट विश्वसनीय वेबसाइटों में इंजेक्ट की जाती हैं। हमलावर उपयोगकर्ताओं के ब्राउज़रों में स्क्रिप्ट्स को निष्पादित कर सकते हैं, डेटा चुरा सकते हैं या उपयोगकर्ता की ओर से क्रियाएँ कर सकते हैं।

कमजोर कोड का उदाहरण:

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

क्यों यह कमजोर है: dangerouslySetInnerHTML का उपयोग अविश्वसनीय इनपुट के साथ करने से हमलावरों को दुर्भावनापूर्ण स्क्रिप्ट इंजेक्ट करने की अनुमति मिलती है।

क्लाइंट-साइड टेम्पलेट इंजेक्शन

यह तब होता है जब उपयोगकर्ता इनपुट को टेम्पलेट में ठीक से संभाला नहीं जाता, जिससे हमलावरों को टेम्पलेट या अभिव्यक्तियों को इंजेक्ट और निष्पादित करने की अनुमति मिलती है।

कमजोर कोड का उदाहरण:

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

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

क्यों यह कमजोर है: यदि template या data में दुर्भावनापूर्ण सामग्री शामिल है, तो यह अनपेक्षित कोड के निष्पादन का कारण बन सकता है।

क्लाइंट पथ ट्रैवर्सल

यह एक कमजोरी है जो हमलावरों को क्लाइंट-साइड पथों में हेरफेर करने की अनुमति देती है ताकि अनपेक्षित क्रियाएँ की जा सकें, जैसे कि क्रॉस-साइट अनुरोध धोखाधड़ी (CSRF)। सर्वर-साइड पथ ट्रैवर्सल के विपरीत, जो सर्वर की फ़ाइल प्रणाली को लक्षित करता है, CSPT वैध API अनुरोधों को दुर्भावनापूर्ण एंडपॉइंट्स पर पुनः मार्गनिर्देशित करने के लिए क्लाइंट-साइड तंत्रों का शोषण करने पर ध्यान केंद्रित करता है।

कमजोर कोड का उदाहरण:

एक Next.js एप्लिकेशन उपयोगकर्ताओं को फ़ाइलें अपलोड और डाउनलोड करने की अनुमति देता है। डाउनलोड सुविधा क्लाइंट साइड पर लागू की गई है, जहाँ उपयोगकर्ता डाउनलोड करने के लिए फ़ाइल पथ निर्दिष्ट कर सकते हैं।

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

हमला परिदृश्य

  1. हमलावर का उद्देश्य: filePath को हेरफेर करके एक महत्वपूर्ण फ़ाइल (जैसे, admin/config.json) को हटाने के लिए CSRF हमला करना।
  2. CSPT का शोषण:
  • दुष्ट इनपुट: हमलावर एक URL तैयार करता है जिसमें हेरफेर किया गया filePath होता है जैसे ../deleteFile/config.json
  • परिणामी API कॉल: क्लाइंट-साइड कोड /api/files/../deleteFile/config.json पर एक अनुरोध करता है।
  • सर्वर का प्रबंधन: यदि सर्वर filePath को मान्य नहीं करता है, तो यह अनुरोध को संसाधित करता है, संभावित रूप से संवेदनशील फ़ाइलों को हटा या उजागर कर सकता है।
  1. CSRF को निष्पादित करना:
  • तैयार लिंक: हमलावर पीड़ित को एक लिंक भेजता है या एक दुष्ट स्क्रिप्ट एम्बेड करता है जो हेरफेर किए गए filePath के साथ डाउनलोड अनुरोध को ट्रिगर करता है।
  • परिणाम: पीड़ित अनजाने में क्रिया को निष्पादित करता है, जिससे अनधिकृत फ़ाइल पहुंच या हटाने की स्थिति उत्पन्न होती है।

यह क्यों कमजोर है

  • इनपुट मान्यता की कमी: क्लाइंट-साइड मनमाने filePath इनपुट की अनुमति देता है, जिससे पथ यात्रा की अनुमति मिलती है।
  • क्लाइंट इनपुट पर भरोसा करना: सर्वर-साइड API filePath को बिना सफाई के भरोसा करता है और संसाधित करता है।
  • संभावित API क्रियाएँ: यदि API एंडपॉइंट स्थिति-परिवर्तनकारी क्रियाएँ करता है (जैसे, फ़ाइलें हटाना, संशोधित करना), तो इसे CSPT के माध्यम से शोषित किया जा सकता है।

Next.js में सर्वर-साइड

सर्वर-साइड रेंडरिंग (SSR)

पृष्ठों को प्रत्येक अनुरोध पर सर्वर पर रेंडर किया जाता है, यह सुनिश्चित करते हुए कि उपयोगकर्ता को पूरी तरह से रेंडर किया गया HTML प्राप्त होता है। इस मामले में आपको अनुरोधों को संसाधित करने के लिए अपना कस्टम सर्वर बनाना चाहिए।

उपयोग के मामले:

  • गतिशील सामग्री जो बार-बार बदलती है।
  • SEO अनुकूलन, क्योंकि खोज इंजन पूरी तरह से रेंडर किए गए पृष्ठ को क्रॉल कर सकते हैं।

कार्यान्वयन:

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)

पृष्ठों को निर्माण के समय पूर्व-रेंडर किया जाता है, जिससे लोड समय तेज और सर्वर लोड कम होता है।

उपयोग के मामले:

  • सामग्री जो अक्सर नहीं बदलती।
  • ब्लॉग, दस्तावेज़, विपणन पृष्ठ।

कार्यान्वयन:

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 API एंडपॉइंट्स को सर्वरलेस फ़ंक्शंस के रूप में बनाने की अनुमति देता है। ये फ़ंक्शंस मांग पर बिना किसी समर्पित सर्वर की आवश्यकता के चलते हैं।

उपयोग के मामले:

  • फ़ॉर्म सबमिशन को संभालना।
  • डेटाबेस के साथ इंटरैक्ट करना।
  • डेटा को प्रोसेस करना या थर्ड-पार्टी APIs के साथ एकीकृत करना।

कार्यान्वयन:

Next.js 13 में app डायरेक्टरी के परिचय के साथ, रूटिंग और API हैंडलिंग अधिक लचीली और शक्तिशाली हो गई है। यह आधुनिक दृष्टिकोण फ़ाइल-आधारित रूटिंग सिस्टम के साथ निकटता से मेल खाता है लेकिन इसमें सर्वर और क्लाइंट घटकों के लिए समर्थन सहित उन्नत क्षमताएँ शामिल हैं।

बेसिक रूट हैंडलर

फाइल संरचना:

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

कार्यान्वयन:

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

व्याख्या:

  • स्थान: API रूट app/api/ निर्देशिका के अंतर्गत रखे जाते हैं।
  • फाइल नामकरण: प्रत्येक API एंडपॉइंट अपने स्वयं के फ़ोल्डर में स्थित होता है जिसमें route.js या route.ts फ़ाइल होती है।
  • निर्यातित फ़ंक्शन: एकल डिफ़ॉल्ट निर्यात के बजाय, विशिष्ट HTTP विधि फ़ंक्शन (जैसे, GET, POST) निर्यात किए जाते हैं।
  • प्रतिक्रिया प्रबंधन: प्रतिक्रियाएँ लौटाने के लिए Response कंस्ट्रक्टर का उपयोग करें, जो हेडर और स्थिति कोड पर अधिक नियंत्रण की अनुमति देता है।

अन्य पथों और विधियों को कैसे संभालें:

विशिष्ट HTTP विधियों को संभालना

Next.js 13+ आपको एक ही route.js या route.ts फ़ाइल के भीतर विशिष्ट HTTP विधियों के लिए हैंडलर परिभाषित करने की अनुमति देता है, जो कोड को स्पष्ट और अधिक संगठित बनाता है।

उदाहरण:

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

व्याख्या:

  • कई निर्यात: प्रत्येक HTTP विधि (GET, PUT, DELETE) का अपना निर्यातित फ़ंक्शन है।
  • पैरामीटर: दूसरा तर्क params के माध्यम से रूट पैरामीटर तक पहुँच प्रदान करता है।
  • सुधारित प्रतिक्रियाएँ: प्रतिक्रिया वस्तुओं पर अधिक नियंत्रण, सटीक हेडर और स्थिति कोड प्रबंधन की अनुमति देता है।
कैच-ऑल और नेस्टेड रूट्स

Next.js 13+ उन्नत रूटिंग सुविधाओं का समर्थन करता है जैसे कैच-ऑल रूट्स और नेस्टेड API रूट्स, जो अधिक गतिशील और स्केलेबल API संरचनाओं की अनुमति देते हैं।

कैच-ऑल रूट उदाहरण:

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

व्याख्या:

  • सिंटैक्स: [...] एक कैच-ऑल खंड को दर्शाता है, जो सभी नेस्टेड पथों को कैप्चर करता है।
  • उपयोग: उन APIs के लिए उपयोगी है जिन्हें विभिन्न मार्ग गहराइयों या गतिशील खंडों को संभालने की आवश्यकता होती है।

नेस्टेड रूट्स उदाहरण:

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

व्याख्या:

  • गहरा नेस्टिंग: हाइरार्किकल API संरचनाओं की अनुमति देता है, जो संसाधन संबंधों को दर्शाता है।
  • पैरामीटर एक्सेस: params ऑब्जेक्ट के माध्यम से कई रूट पैरामीटर आसानी से एक्सेस करें।
Next.js 12 और पहले API रूट्स को संभालना

pages डायरेक्टरी में API रूट्स (Next.js 12 और पहले)

Next.js 13 ने app डायरेक्टरी और रूटिंग क्षमताओं को बढ़ाने से पहले, API रूट्स मुख्य रूप से pages डायरेक्टरी के भीतर परिभाषित किए गए थे। यह दृष्टिकोण अभी भी व्यापक रूप से उपयोग किया जाता है और Next.js 12 और पहले के संस्करणों में समर्थित है।

बुनियादी API रूट

फाइल संरचना:

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

क्रियान्वयन:

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

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

व्याख्या:

  • स्थान: API रूट pages/api/ निर्देशिका के अंतर्गत होते हैं।
  • निर्यात: हैंडलर फ़ंक्शन को परिभाषित करने के लिए export default का उपयोग करें।
  • फ़ंक्शन सिग्नेचर: हैंडलर req (HTTP अनुरोध) और res (HTTP प्रतिक्रिया) ऑब्जेक्ट प्राप्त करता है।
  • रूटिंग: फ़ाइल का नाम (hello.js) एंडपॉइंट /api/hello से मैप होता है।

गतिशील API रूट्स

फ़ाइल संरचना:

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

क्रियान्वयन:

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

व्याख्या:

  • गतिशील खंड: वर्गाकार ब्रैकेट ([id].js) गतिशील मार्ग खंड को दर्शाते हैं।
  • पैरामीटर तक पहुँच: गतिशील पैरामीटर तक पहुँचने के लिए req.query.id का उपयोग करें।
  • विधियों को संभालना: विभिन्न HTTP विधियों (GET, PUT, DELETE, आदि) को संभालने के लिए शर्तीय तर्क का उपयोग करें।

विभिन्न HTTP विधियों को संभालना

जबकि बुनियादी API मार्ग उदाहरण एकल फ़ंक्शन के भीतर सभी HTTP विधियों को संभालता है, आप बेहतर स्पष्टता और रखरखाव के लिए प्रत्येक विधि को स्पष्ट रूप से संभालने के लिए अपने कोड को संरचित कर सकते हैं।

उदाहरण:

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

सर्वश्रेष्ठ प्रथाएँ:

  • चिंताओं का पृथक्करण: विभिन्न HTTP विधियों के लिए लॉजिक को स्पष्ट रूप से अलग करें।
  • प्रतिक्रिया स्थिरता: क्लाइंट-साइड हैंडलिंग की सुविधा के लिए प्रतिक्रियाओं की संरचना को स्थिर रखें।
  • त्रुटि प्रबंधन: असमर्थित विधियों और अप्रत्याशित त्रुटियों को सुचारू रूप से संभालें।

CORS कॉन्फ़िगरेशन

नियंत्रित करें कि कौन से मूल आपके API रूट्स तक पहुँच सकते हैं, Cross-Origin Resource Sharing (CORS) कमजोरियों को कम करते हुए।

खराब कॉन्फ़िगरेशन उदाहरण:

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

ध्यान दें कि CORS को सभी API रूट्स में भी कॉन्फ़िगर किया जा सकता है middleware.ts फ़ाइल के अंदर:

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
}

समस्या:

  • Access-Control-Allow-Origin: '*': किसी भी वेबसाइट को API तक पहुँचने की अनुमति देता है, जिससे संभावित रूप से दुर्भावनापूर्ण साइटों को आपकी API के साथ बिना किसी प्रतिबंध के इंटरैक्ट करने की अनुमति मिलती है।
  • व्यापक विधि अनुमति: सभी विधियों की अनुमति देना हमलावरों को अवांछित क्रियाएँ करने में सक्षम बना सकता है।

हमलावर इसका कैसे लाभ उठाते हैं:

हमलावर दुर्भावनापूर्ण वेबसाइटें बना सकते हैं जो आपकी API को अनुरोध भेजती हैं, संभावित रूप से डेटा पुनर्प्राप्ति, डेटा हेरफेर, या प्रमाणित उपयोगकर्ताओं की ओर से अवांछित क्रियाएँ ट्रिगर करने जैसी कार्यक्षमताओं का दुरुपयोग कर सकती हैं।

CORS - Misconfigurations & Bypass

क्लाइंट साइड में सर्वर कोड का प्रदर्शन

यह सर्वर द्वारा उपयोग किए गए कोड का उपयोग क्लाइंट साइड द्वारा प्रदर्शित और उपयोग किए गए कोड में करना आसान हो सकता है, यह सुनिश्चित करने का सबसे अच्छा तरीका है कि कोड की कोई फ़ाइल कभी भी क्लाइंट साइड में प्रदर्शित न हो, फ़ाइल की शुरुआत में इस आयात का उपयोग करना है:

js
import "server-only"

मुख्य फ़ाइलें और उनकी भूमिकाएँ

middleware.ts / middleware.js

स्थान: प्रोजेक्ट की जड़ या src/ के भीतर।

उद्देश्य: एक अनुरोध संसाधित होने से पहले सर्वर-साइड सर्वरलेस फ़ंक्शन में कोड निष्पादित करता है, जैसे कि प्रमाणीकरण, रीडायरेक्ट या प्रतिक्रियाओं को संशोधित करना।

निष्पादन प्रवाह:

  1. आगामी अनुरोध: मिडलवेयर अनुरोध को इंटरसेप्ट करता है।
  2. प्रसंस्करण: अनुरोध के आधार पर संचालन करता है (जैसे, प्रमाणीकरण की जांच करना)।
  3. प्रतिक्रिया संशोधन: प्रतिक्रिया को बदल सकता है या अगले हैंडलर को नियंत्रण सौंप सकता है।

उदाहरण उपयोग के मामले:

  • अप्रमाणित उपयोगकर्ताओं को रीडायरेक्ट करना।
  • कस्टम हेडर जोड़ना।
  • अनुरोधों को लॉग करना।

नमूना कॉन्फ़िगरेशन:

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

स्थान: प्रोजेक्ट की जड़।

उद्देश्य: Next.js के व्यवहार को कॉन्फ़िगर करता है, सुविधाओं को सक्षम या अक्षम करता है, वेबपैक कॉन्फ़िगरेशन को कस्टमाइज़ करता है, पर्यावरण चर सेट करता है, और कई सुरक्षा सुविधाओं को कॉन्फ़िगर करता है।

मुख्य सुरक्षा कॉन्फ़िगरेशन:

सुरक्षा हेडर

सुरक्षा हेडर आपके एप्लिकेशन की सुरक्षा को बढ़ाते हैं, ब्राउज़रों को यह निर्देश देकर कि सामग्री को कैसे संभालना है। ये विभिन्न हमलों जैसे कि क्रॉस-साइट स्क्रिप्टिंग (XSS), क्लिकजैकिंग, और MIME प्रकार स्निफ़िंग को कम करने में मदद करते हैं:

  • सामग्री सुरक्षा नीति (CSP)
  • X-Frame-Options
  • X-Content-Type-Options
  • स्ट्रिक्ट-ट्रांसपोर्ट-सेक्योरिटी (HSTS)
  • रेफरर नीति

उदाहरण:

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...
],
},
]
},
}
छवि अनुकूलन सेटिंग्स

Next.js प्रदर्शन के लिए छवियों का अनुकूलन करता है, लेकिन गलत कॉन्फ़िगरेशन सुरक्षा कमजोरियों का कारण बन सकता है, जैसे कि अविश्वसनीय स्रोतों को दुर्भावनापूर्ण सामग्री इंजेक्ट करने की अनुमति देना।

खराब कॉन्फ़िगरेशन उदाहरण:

javascript
// next.config.js

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

समस्या:

  • '*': किसी भी बाहरी स्रोत से चित्रों को लोड करने की अनुमति देता है, जिसमें अविश्वसनीय या दुर्भावनापूर्ण डोमेन शामिल हैं। हमलावर चित्रों को होस्ट कर सकते हैं जिनमें दुर्भावनापूर्ण पेलोड या सामग्री होती है जो उपयोगकर्ताओं को भ्रामित करती है।
  • एक और समस्या यह हो सकती है कि एक डोमेन की अनुमति दी जाए जहां कोई भी चित्र अपलोड कर सकता है (जैसे raw.githubusercontent.com)

हमलावर इसका दुरुपयोग कैसे करते हैं:

दुर्भावनापूर्ण स्रोतों से चित्रों को इंजेक्ट करके, हमलावर फ़िशिंग हमले कर सकते हैं, भ्रामक जानकारी प्रदर्शित कर सकते हैं, या चित्र रेंडरिंग लाइब्रेरी में कमजोरियों का लाभ उठा सकते हैं।

पर्यावरण चर का प्रदर्शन

संवेदनशील जानकारी जैसे API कुंजी और डेटाबेस क्रेडेंशियल्स को सुरक्षित रूप से प्रबंधित करें बिना उन्हें क्लाइंट के सामने उजागर किए।

क. संवेदनशील चर का प्रदर्शन

खराब कॉन्फ़िगरेशन उदाहरण:

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

समस्या:

  • SECRET_API_KEY: NEXT_PUBLIC_ उपसर्ग के बिना, Next.js क्लाइंट को वेरिएबल्स को उजागर नहीं करता है। हालाँकि, यदि गलती से उपसर्ग जोड़ा गया (जैसे, NEXT_PUBLIC_SECRET_API_KEY), तो यह क्लाइंट साइड पर उपलब्ध हो जाता है।

हमलावर इसका कैसे दुरुपयोग करते हैं:

यदि संवेदनशील वेरिएबल्स क्लाइंट को उजागर होते हैं, तो हमलावर उन्हें क्लाइंट-साइड कोड या नेटवर्क अनुरोधों की जांच करके प्राप्त कर सकते हैं, जिससे APIs, डेटाबेस, या अन्य सेवाओं तक अनधिकृत पहुंच प्राप्त होती है।

रीडायरेक्ट्स

अपने एप्लिकेशन के भीतर URL रीडायरेक्शंस और री-राइट्स का प्रबंधन करें, यह सुनिश्चित करते हुए कि उपयोगकर्ताओं को उचित रूप से निर्देशित किया जाए बिना ओपन रीडायरेक्ट कमजोरियों को पेश किए।

क. ओपन रीडायरेक्ट कमजोरियाँ

खराब कॉन्फ़िगरेशन उदाहरण:

javascript
// next.config.js

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

समस्या:

  • गतिशील गंतव्य: उपयोगकर्ताओं को कोई भी URL निर्दिष्ट करने की अनुमति देता है, जिससे ओपन रीडायरेक्ट हमले संभव होते हैं।
  • उपयोगकर्ता इनपुट पर भरोसा करना: उपयोगकर्ताओं द्वारा प्रदान किए गए URLs पर बिना सत्यापन के रीडायरेक्ट करना फ़िशिंग, मैलवेयर वितरण, या क्रेडेंशियल चोरी का कारण बन सकता है।

हमलावर इसका दुरुपयोग कैसे करते हैं:

हमलावर ऐसे URLs तैयार कर सकते हैं जो आपके डोमेन से उत्पन्न होने का आभास देते हैं लेकिन उपयोगकर्ताओं को दुर्भावनापूर्ण साइटों पर रीडायरेक्ट करते हैं। उदाहरण के लिए:

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

उपयोगकर्ता मूल डोमेन पर भरोसा करते हुए अनजाने में हानिकारक वेबसाइटों पर जा सकते हैं।

Webpack कॉन्फ़िगरेशन

अपने Next.js एप्लिकेशन के लिए Webpack कॉन्फ़िगरेशन को अनुकूलित करें, जो सावधानी से न संभाले जाने पर सुरक्षा कमजोरियों को अनजाने में पेश कर सकता है।

क. संवेदनशील मॉड्यूल को उजागर करना

खराब कॉन्फ़िगरेशन उदाहरण:

javascript
// next.config.js

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

समस्या:

  • संवेदनशील पथों का उजागर होना: संवेदनशील निर्देशिकाओं का उपनामकरण और क्लाइंट-साइड पहुंच की अनुमति देना गोपनीय जानकारी को लीक कर सकता है।
  • गुप्त जानकारियों का बंडलिंग: यदि संवेदनशील फ़ाइलें क्लाइंट के लिए बंडल की जाती हैं, तो उनकी सामग्री स्रोत मानचित्रों के माध्यम से या क्लाइंट-साइड कोड की जांच करके सुलभ हो जाती है।

हमलावर इसका कैसे दुरुपयोग करते हैं:

हमलावर एप्लिकेशन की निर्देशिका संरचना तक पहुंच प्राप्त कर सकते हैं या उसे पुनर्निर्मित कर सकते हैं, संभावित रूप से संवेदनशील फ़ाइलों या डेटा को खोजकर और उनका दुरुपयोग करके।

pages/_app.js और pages/_document.js

pages/_app.js

उद्देश्य: डिफ़ॉल्ट ऐप घटक को ओवरराइड करता है, वैश्विक स्थिति, शैलियाँ, और लेआउट घटकों की अनुमति देता है।

उपयोग के मामले:

  • वैश्विक CSS को इंजेक्ट करना।
  • लेआउट रैपर जोड़ना।
  • स्थिति प्रबंधन पुस्तकालयों का एकीकरण।

उदाहरण:

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

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

export default MyApp

pages/_document.js

उद्देश्य: डिफ़ॉल्ट दस्तावेज़ को ओवरराइड करता है, HTML और Body टैग्स के अनुकूलन की अनुमति देता है।

उपयोग के मामले:

  • <html> या <body> टैग्स को संशोधित करना।
  • मेटा टैग्स या कस्टम स्क्रिप्ट जोड़ना।
  • थर्ड-पार्टी फॉन्ट्स को एकीकृत करना।

उदाहरण:

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

कस्टम सर्वर (वैकल्पिक)

उद्देश्य: जबकि Next.js एक अंतर्निहित सर्वर के साथ आता है, आप कस्टम राउटिंग या मौजूदा बैकएंड सेवाओं के साथ एकीकृत करने जैसे उन्नत उपयोग के मामलों के लिए एक कस्टम सर्वर बना सकते हैं।

नोट: कस्टम सर्वर का उपयोग करने से तैनाती के विकल्प सीमित हो सकते हैं, विशेष रूप से उन प्लेटफार्मों पर जैसे Vercel जो Next.js के अंतर्निहित सर्वर के लिए अनुकूलित हैं।

उदाहरण:

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

अतिरिक्त आर्किटेक्चरल और सुरक्षा विचार

पर्यावरण चर और कॉन्फ़िगरेशन

उद्देश्य: संवेदनशील जानकारी और कॉन्फ़िगरेशन सेटिंग्स को कोडबेस के बाहर प्रबंधित करना।

सर्वोत्तम प्रथाएँ:

  • .env फ़ाइलों का उपयोग करें: API कुंजी जैसी चर को .env.local में स्टोर करें (संस्करण नियंत्रण से बाहर)।
  • चर को सुरक्षित रूप से एक्सेस करें: पर्यावरण चर को एक्सेस करने के लिए process.env.VARIABLE_NAME का उपयोग करें।
  • क्लाइंट पर कभी भी रहस्य उजागर न करें: सुनिश्चित करें कि संवेदनशील चर केवल सर्वर-साइड पर उपयोग किए जाते हैं।

उदाहरण:

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

नोट: सर्वर-साइड के लिए वेरिएबल्स को सीमित करने के लिए, उन्हें env ऑब्जेक्ट से हटा दें या क्लाइंट एक्सपोजर के लिए NEXT_PUBLIC_ से प्रीफिक्स करें।

प्रमाणीकरण और प्राधिकरण

पद्धति:

  • सत्र-आधारित प्रमाणीकरण: उपयोगकर्ता सत्रों को प्रबंधित करने के लिए कुकीज़ का उपयोग करें।
  • टोकन-आधारित प्रमाणीकरण: Stateless प्रमाणीकरण के लिए JWTs लागू करें।
  • तीसरे पक्ष के प्रदाता: next-auth जैसी लाइब्रेरी का उपयोग करके OAuth प्रदाताओं (जैसे, Google, GitHub) के साथ एकीकृत करें।

सुरक्षा प्रथाएँ:

  • सुरक्षित कुकीज़: HttpOnly, Secure, और SameSite विशेषताओं को सेट करें।
  • पासवर्ड हैशिंग: उन्हें स्टोर करने से पहले हमेशा पासवर्ड को हैश करें।
  • इनपुट मान्यता: इनपुट को मान्य और साफ करके इंजेक्शन हमलों को रोकें।

उदाहरण:

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

प्रदर्शन अनुकूलन

रणनीतियाँ:

  • छवि अनुकूलन: स्वचालित छवि अनुकूलन के लिए Next.js के next/image घटक का उपयोग करें।
  • कोड विभाजन: प्रारंभिक लोड समय को कम करने के लिए कोड को विभाजित करने के लिए गतिशील आयात का लाभ उठाएँ।
  • कैशिंग: API प्रतिक्रियाओं और स्थिर संपत्तियों के लिए कैशिंग रणनीतियों को लागू करें।
  • आलसी लोडिंग: घटकों या संपत्तियों को केवल तब लोड करें जब उनकी आवश्यकता हो।

उदाहरण:

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

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

tip

AWS हैकिंग सीखें और अभ्यास करें:HackTricks Training AWS Red Team Expert (ARTE)
GCP हैकिंग सीखें और अभ्यास करें: HackTricks Training GCP Red Team Expert (GRTE)

HackTricks का समर्थन करें