Next.js-এ এসকিউএল ইনজেকশন প্রতিরোধের উপায়

Next.js App Router, Server Actions, Route Handlers এবং আধুনিক ওআরএম ব্যবহারে এসকিউএল ইনজেকশন প্রতিরোধের বিস্তারিত গাইড।

Next.js সার্ভার অ্যাকশন এবং ডাটাবেস বাউন্ডারি আর্কিটেকচার নির্দেশক বিমূর্ত সিকিউরিটি গ্রাফিক

Next.js App Router এবং React Server Components (RSC) আসার পর ফুল-স্ট্যাক ডেভেলপাররা সার্ভার কম্পোনেন্ট এবং সার্ভার অ্যাকশন থেকে সরাসরি ডাটাবেস কোয়েরি করতে পারছেন। এর ফলে আলাদা রেস্ট এপিআই (REST API) লেখার ঝামেলা কমলেও ডাটাবেসের নিরাপত্তা কাঠামো সরাসরি অ্যাপ্লিকেশন লেয়ারে চলে এসেছে। যথাযথ প্যারামিটারাইজেশন নিশ্চিত না করলে ডাটাবেস গুরুতর ইনজেকশন ঝুঁকির মুখোমুখি হতে পারে।

এসকিউএল ইনজেকশনের মূল ধারণা বুঝতে আমাদের এসকিউএল ইনজেকশন কীভাবে কাজ করে ও প্রতিরোধের উপায় গাইডটি দেখুন। এছাড়া সাধারণ নোড সার্ভারের ক্ষেত্রে Node.js ও Express-এ এসকিউএল ইনজেকশন প্রতিরোধ গাইড পড়ে নিতে পারেন।

এই টিউটোরিয়ালে Next.js Server Components, Server Actions, Route Handlers এবং আধুনিক ওআরএম ব্যবহারে ডাটাবেস সুরক্ষিত রাখার উপায় বিশ্লেষণ করা হলো।

Next.js App Router-এ এসকিউএল ইনজেকশনের উৎসসমূহ

Next.js অ্যাপ্লিকেশনে ক্লায়েন্টের ডেটা প্রধানত তিনটি উপায়ে সার্ভারে প্রবেশ করে:

  1. Server Actions ('use server'): ফর্ম সাবমিশন বা ক্লায়েন্ট কম্পোনেন্ট থেকে প্রেরিত সিরিয়ালাইজড আর্গুমেন্ট।
  2. Route Handlers (app/api/.../route.ts): সাধারণ এইচটিটিপি রিকোয়েস্ট বডি কিংবা সার্চ প্যারামিটার।
  3. Server Component Props: ইউআরএল সার্চ প্যারামিটার যা PageProps ({ searchParams }) এর মাধ্যমে আসে।

যখন এই ইনপুটগুলো সরাসরি এসকিউএল স্ট্রিংয়ের ভেতরে টেমপ্লেট লিটারেল হিসেবে বসানো হয়, তখনই দুর্বলতা তৈরি হয়:

// ঝুঁকিপূর্ণ: স্ট্রিং ইন্টারপোলেশনযুক্ত সার্ভার অ্যাকশন
'use server';

import { db } from '@/lib/db';

export async function filterUsers(department: string) {
  // ফর্ম বা ক্লায়েন্ট ইনপুট সরাসরি এসকিউএল স্ট্রিংয়ে বসানো হয়েছে
  const query = `SELECT id, name, role FROM employees WHERE department = '${department}'`;
  const result = await db.query(query);
  return result.rows;
}

যেহেতু সার্ভার অ্যাকশন সরাসরি এইচটিটিপি পোস্ট (HTTP POST) রিকোয়েস্ট পাঠিয়ে বাইরে থেকেও ট্রিগার করা যায়, তাই শুধু ব্রাউজার সাইডে ইনপুট ফিল্টারিংয়ের ওপর নির্ভর করা বিপজ্জনক।

Server Actions সুরক্ষিত করার নিয়ম: Zod ভ্যালিডেশন ও প্যারামিটারাইজেশন

সার্ভার অ্যাকশনে এসকিউএল ইনজেকশন পুরোপুরি বন্ধ করতে দ্বিমুখী নিরাপত্তা নিশ্চিত করতে হবে: Zod দিয়ে ইনপুট স্কিমা ভ্যালিডেশন এবং প্যারামিটারাইজড কোয়েরি বাইন্ডিং:

// নিরাপদ: Zod ভ্যালিডেশন ও প্যারামিটারাইজড কোয়েরি
'use server';

import { z } from 'zod';
import pool from '@/lib/db';

const SearchSchema = z.object({
  department: z.string().trim().min(1).max(50),
  limit: z.number().int().positive().max(100).default(20)
});

export async function searchEmployeesAction(formData: FormData) {
  const parsed = SearchSchema.safeParse({
    department: formData.get('department'),
    limit: Number(formData.get('limit') || 20)
  });

  if (!parsed.success) {
    return { error: 'ভুল ইনপুট প্যারামিটার', data: [] };
  }

  const { department, limit } = parsed.data;

  // প্যারামিটারাইজড কোয়েরি: $1 এবং $2 শুধুমাত্র লিটারেল ডেটা হিসেবে মূল্যায়ন হবে
  const query = `
    SELECT id, name, department, role 
    FROM employees 
    WHERE department = $1 
    ORDER BY id ASC 
    LIMIT $2
  `;

  try {
    const { rows } = await pool.query(query, [department, limit]);
    return { error: null, data: rows };
  } catch (err) {
    console.error('ডাটাবেস কোয়েরি এরর:', err);
    return { error: 'তথ্য সংগ্রহ করা সম্ভব হয়নি', data: [] };
  }
}

Route Handlers-এ সার্চ প্যারামিটার হ্যান্ডলিং

Next.js Route Handlers-এ (route.ts) ইউআরএল সার্চ প্যারামিটার ব্যবহার করার সময় সর্বদা প্যারামিটারাইজড সিনট্যাক্স মেনে চলতে হবে:

// নিরাপদ: app/api/products/route.ts
import { NextRequest, NextResponse } from 'next/server';
import pool from '@/lib/db';

export async function GET(request: NextRequest) {
  const searchParams = request.nextUrl.searchParams;
  const category = searchParams.get('category');
  const inStock = searchParams.get('inStock') === 'true';

  if (!category) {
    return NextResponse.json({ error: 'Category প্রয়োজন' }, { status: 400 });
  }

  // প্রিপেয়ার্ড স্টেটমেন্টের মাধ্যমে প্যারামিটার পাঠানো
  const text = 'SELECT id, title, price FROM products WHERE category = $1 AND in_stock = $2';
  const values = [category, inStock];

  const { rows } = await pool.query(text, values);
  return NextResponse.json({ products: rows });
}

আধুনিক TypeScript ওআরএম: Drizzle এবং Prisma

Next.js অ্যাপ্লিকেশনে ওআরএম ব্যবহার জনপ্রিয়। আধুনিক ওআরএম স্বয়ংক্রিয়ভাবে কুয়েরি প্যারামিটারাইজ করে, তবে র কুয়েরি লেখার সময় সচেতন হতে হবে।

Drizzle ORM-এ নিরাপদ কোয়েরি

Drizzle তার নিজস্ব sql ট্যাগড টেমপ্লেটের মাধ্যমে স্বয়ংক্রিয় প্যারামিটারাইজেশন নিশ্চিত করে:

import { db } from '@/lib/drizzle';
import { users } from '@/lib/schema';
import { eq, sql } from 'drizzle-orm';

// নিরাপদ: Drizzle কুয়েরি বিল্ডার
export async function getActiveUsers(roleName: string) {
  return db.select()
    .from(users)
    .where(eq(users.role, roleName));
}

// নিরাপদ: Drizzle sql টেমপ্লেট ট্যাগ ইনপুটকে স্বয়ংক্রিয়ভাবে প্যারামিটারাইজ করে
export async function customFilter(userInput: string) {
  return db.execute(sql`
    SELECT id, email, created_at 
    FROM ${users} 
    WHERE status = ${userInput}
  `);
}

// বিপজ্জনক: sql.raw ব্যবহার করলে প্যারামিটারাইজেশন নষ্ট হয়ে যায়
// db.execute(sql.raw(`SELECT * FROM users WHERE status = '${userInput}'`)); // কখনই করবেন না

Prisma ORM ব্যবহার

import { prisma } from '@/lib/prisma';

// নিরাপদ: Prisma টাইপ-সেফ মেথড
export async function findUserByEmail(email: string) {
  return prisma.user.findUnique({
    where: { email }
  });
}

// নিরাপদ: $queryRaw ট্যাগড টেমপ্লেট স্বয়ংক্রিয়ভাবে প্যারামিটার বাইন্ড করে
export async function rawReport(companyId: string) {
  return prisma.$queryRaw`
    SELECT id, total_revenue 
    FROM financial_reports 
    WHERE company_id = ${companyId}
  `;
}

সফটওয়্যার কোডের নিরাপত্তা ও দীর্ঘমেয়াদী স্থায়িত্ব বজায় রাখতে আমাদের ক্লিন কোড ও কোড রিভিউ নীতিমালা দেখুন।

সচরাচর যেসব ভুল পরিলক্ষিত হয়

সাধারণ ভুল ঝুঁকি সমাধান
সার্ভার অ্যাকশনে সরাসরি স্ট্রিং জোড়া দেওয়া অননুমোদিত ইউজার ইনজেকশন পে-লোড পাঠাতে পারে Zod স্কিমা ভ্যালিডেশন ও প্যারামিটারাইজড কুয়েরি নিশ্চিত করুন
Server Components-এ SearchParams বিশ্বাস করা ইউআরএল কারসাজির মাধ্যমে ব্লাইন্ড এসকিউএলআই আক্রমণ page.tsx-এ ডাটাবেস কলে প্যারামিটারাইজেশন বাধ্যতামূলক করুন
sql.raw বা $queryRawUnsafe ব্যবহার ওআরএম-এর নিরাপত্তা সম্পূর্ণ অকার্যকর হয়ে যায় শুধুমাত্র ট্যাগড টেমপ্লেট লিটারেল (sql\...``) ব্যবহার করুন
ক্লায়েন্টে ডাটাবেস এরর দেখানো স্কিমা তথ্য ফাঁসের ঝুঁকি প্রোডাকশনে জেনেরিক এরর মেসেজ রিটার্ন করুন

প্রোডাকশন চেকলিস্ট

Next.js অ্যাপ্লিকেশন প্রোডাকশনে দেওয়ার আগে নিচের বিষয়গুলো মিলিয়ে নিন:

  • সকল সার্ভার অ্যাকশন আর্গুমেন্ট Zod স্কিমা দিয়ে ভ্যালিডেট করা হয়েছে।
  • কোনো searchParams সরাসরি এসকিউএল কোয়েরি স্ট্রিংয়ে বসানো হয়নি।
  • Drizzle বা Prisma-তে র কোয়েরি কেবল ট্যাগড টেমপ্লেট মেকানিজম ব্যবহার করছে।
  • ডাটাবেস ক্রেডেনশিয়াল (DATABASE_URL) সার্ভার-সাইডেই সীমাবদ্ধ রয়েছে (কোনো NEXT_PUBLIC_ নেই)।
  • কোডবেসে $queryRawUnsafe বা sql.raw শনাক্ত করার মতো লিন্টার রুল কার্যকর রয়েছে।

সারসংক্ষেপ

Next.js App Router এবং Server Actions ডেভেলপারদের কাজ অনেক সহজ করেছে। ডাটাবেস কলের ক্ষেত্রে প্যারামিটারাইজড কুয়েরি মেনে চলা, সার্ভার অ্যাকশনে কড়া ইনপুট ভ্যালিডেশন এবং সরাসরি স্ট্রিং কনক্যাটেনেশন এড়িয়ে চললে Next.js অ্যাপ্লিকেশনের ডাটাবেস নিরাপত্তা সম্পূর্ণ সুরক্ষিত থাকে।

তথ্যসূত্র: Next.js Server Actions Security Architecture, Drizzle ORM Documentation on SQL Operators, Prisma Documentation on Raw Queries, OWASP Top 10 (মূল্যায়ন নভেম্বর ২০২৬)।

আরও পড়ুন

Node.js ও Express-এ এসকিউএল ইনজেকশন প্রতিরোধের উপায়

Node.js এবং Express ব্যাকএন্ডে pg, mysql2, কোয়েরি বিল্ডার ও ওআরএম ব্যবহারের মাধ্যমে এসকিউএল ইনজেকশন নির্মূলের ব্যবহারিক গাইড।

নিরাপত্তা•৫ মিনিটে পড়া

এসকিউএল ইনজেকশন: কীভাবে কাজ করে ও প্রতিরোধের উপায়

এসকিউএল ইনজেকশন (SQLi) দুর্বলতার আক্রমণ কৌশল, ক্লাসিক্যাল বনাম ব্লাইন্ড এসকিউএলআই এবং প্যারামিটারাইজড কোয়েরি ব্যবহারের সম্পূর্ণ গাইড।

নিরাপত্তা•৪ মিনিটে পড়া

Embassy ও university-র phishing email: ছাত্ররা যাচাই করবে যেভাবে

দূতাবাস বা university-র মতো দেখতে email জাল হতে পারে। sender ঠিকানা থেকে message header পর্যন্ত লক্ষণ ও যাচাই শিখুন।

ইমেইল নিরাপত্তা•২ মিনিটে পড়া