DEV Community

Monirul Islam
Monirul Islam

Posted on Originally published at mislam-dev.vercel.app

Day 6 — API Security — এই ভুলগুলো করলে production-এ কাঁদতে হবে

মনে করুন আপনারা ৪ ভাই। সবাই একসাথেই বসবাস করেন। সৌভাগ্যক্রমে আপনাদের বাবার huge পরিমাণে সম্পদ আছে এবং সম্পদের কারণে না চাইতেও অনেক শত্রু হয়ে গেছে। এখন তাদের নজর আপনাদের এই সম্পত্তির ওপরে। তারা আপনাদের ক্ষতি করতে চায়, সম্পত্তি হাতিয়ে নিতে চায়। এখন তারা কিছুই করতে পারে না। কারণ আপনারা সবাই একসাথে থাকেন।

এখন আপনারা ৪ ভাই যদি আলাদা হয়ে যান এবং গ্রামে বিভিন্ন অংশে move করেন তাহলে কী হতে পারে?

এখন আপনাদের যে শত্রুরা আছে তারা খুব easily-তেই আপনাদের ক্ষতি করতে পারবে। বিভিন্নভাবে আপনাদের ওপর হামলা করবে। তাই বলে কি এগুলো রুখে দেয়া যাবে না? অবশ্যই যাবে, যদি আপনি proper way-তে security maintain করেন।

এখন same way-তে একটা application যখন একসাথে থাকে তখন তার security maintain করা একটু easy। কিন্তু যখন আপনি separate করবেন তখন কিন্তু এর security নিয়ে একটা issue থেকেই তৈরি হবে। উপরের গল্পের মতো hacker-রাও এই issue-গুলো খুঁজে বের করে আপনার application-এর damage করবে। তবে proper standard maintain করলে এই hacker attack থেকে application-কে protect করা যাবে।

আজকে মূলত API security নিয়ে কথা বলবো।


Authentication vs Authorization

Authentication সম্পর্কে মোটামুটি সবাই জানি। কোনো application-এ user_id এবং password দিয়ে access নেয়াই হচ্ছে authentication। কিন্তু এই authorization-টা হচ্ছে authentication-এর পরের step।

একটা office-এর ভেতরে কিন্তু অনেক employee থাকে, সবাই কি সবকিছু ইচ্ছা করলেই করতে পারে? তাদের কি সবার authority আছে?
অবশ্যই না। এখন manager যা যা করতে পারবে সেই same কাজ যদি একজন সাধারণ employee করতে পারে তাহলে তো office-এ অরাজকতার সৃষ্টি হবে। Management-এর অবস্থা খারাপ হয়ে যাবে। এই যার যে যে access, ঐগুলো বাদে অন্য কিছুর access ensure করাই হচ্ছে Authorization।

API-এর authorization-এর ক্ষেত্রে authorization URL বা resource-এর access maintain করতে হয়। Suppose user related যে resource-গুলো আছে সেগুলো শুধুমাত্র admin-ই access করতে পারবে, এই access তো একটা সাধারণ user পেতে পারে না। এটা ensure করাই হচ্ছে API-এর authorization।

একটা application-এর উদাহরণ দিলে easily মনে রাখতে পারবেন:

  • Authentication মানে হচ্ছে আপনি এই application-টা use করতে পারবেন কি না সেটা check করা।
  • Authorization মানে হচ্ছে আপনি কী কী feature/functionality access করতে পারবেন সেগুলো check করা।

OWASP Top 10: সবচেয়ে বড় ভুলগুলো

OWASP প্রতি বছর top security vulnerabilities publish করে।
এখানে নানা security-এর মধ্যে top 10 security issue-গুলো নিয়ে বিস্তারিত থাকে। সাথে তার solution-ও সেখানে বিদ্যমান থাকে। তাই API security ensure করার জন্য এই OWASP report-টা খুব কাজে আসে। নিচে কয়েকটা common security issue নিয়ে আলোচনা করি:

Broken Authentication

  • weak password
  • no token expiry (অনেক ক্ষেত্রে expiry set করলেও তা check করা হয় না।)
  • plain text password storage (password hash না করেই database-এ store করা)

SQL Injection — URL-এর মাধ্যমে or POST request-এর মধ্যে malicious SQL clause inject করা হয়, যেটা server-side database সেটাকে valid SQL হিসেবে execute করে ফেলে। এটাই হচ্ছে SQL Injection। এভাবে attacker চাইলে data চুরি করতে পারে, authentication bypass করতে পারে, এমনকি পুরো table drop করে দিতে পারে।

Broken Access Control — এটা authorization problem। কোন user-এর কোন access থাকবে সেটা control না করা। একজন admin-ও যা যা করতে পারে আবার একজন simple user-ও same করতে পারে।


Rate Limiting: বোকাদের বোকা বানানো

একটা জিনিস চিন্তা করুন আপনি একটা API-কে access করছেন। এখন আপনার ১ মিনিটে কতবার access করা লাগতে পারে? আপনি তো প্রতি sec-এ access করবেন না। মিনিটে maximum ১৫-২০ বার access করবেন। এর বেশি যদি করেন সেটা unnecessary। কিন্তু আপনি না বুঝেই করছেন এই কারণে server-এর resource নষ্ট হচ্ছে। কিছু user-এর application use করতে problem হচ্ছে। তা এখন আমি যদি বলে দিই যে আপনি ১ মিনিটে maximum ১০ বারের বেশি access করতে পারবেন না, এর বেশি করলে error দেখাবে। So এটাই হচ্ছে rate limiting-এর concept।

আবার একটা বিষয় চিন্তা করেন একটা application login করার ক্ষেত্রে আপনি login করতে password + username type করে কতক্ষণ লাগতে পারে? normally ১ মিনিটে ৩-৪ বারের বেশি কেউ login করার try করতে পারবে না। আর password save থাকলে তো একবারেই হয়ে যাবে।

নিচে rate limiting-এর একটা code দেয়া হলো। এটা NestJS-এর ওপরে দেয়া আছে।

// NestJS + nestjs-throttler
@Throttle({ default: { limit: 5, ttl: 60000 } })
@Post('/login')
login() { ... }
Enter fullscreen mode Exit fullscreen mode

ওপরে দেয়া ২টা example আসলে দুইটা hacking attack।

  • প্রথমটা হচ্ছে DDoS attack, এই attack-এ bot-এর মাধ্যমে request send করে server-কে busy করা হয়। একটা সময় server resource শেষ হয়ে যায় এবং server down হয়ে যায়। Rate limiting করলে যখন request limit শেষ হবে, request processing হবে না, error দিবে।
  • দ্বিতীয়টা হচ্ছে brute force attack, এই attack-এ password and username দিয়ে বারবার try করা হয়। যতবার try করা হয় ততবার request server-এ যেতে থাকে। এখন এটা manually করা possible না। Script দিয়ে করা লাগবে। যখন request limit শেষ হবে, request processing হবে না, error দিবে।

এখানে একটা বিষয় মাথায় রাখা জরুরি যে rate limiting-এর সাহায্যে এই দুইটা attack foolproof-ভাবে prevent করা যায় না। তবে attack-এর speed কিছুটা কমানো যায়।


CORS: Browser-এর নিরাপত্তা প্রহরী

মনে করুন আপনার একটা website আছে + একটা backend API-ও আছে। এখন আপনি চাচ্ছেন ঐ website বাদে অন্য কোনো website যেন আমার এই API-তে request দিতে না পারে। মানে শুধু আপনার website-এর জন্য access দিবেন। এটা করা possible। এই কাজটাই করে CORS।

CORS (Cross-Origin Resource Sharing) হলো browser-এর একটা security feature।
এটা শুধুমাত্র browser-এ support করে। কিন্তু এটা কিন্তু frontend-এর problem না। এটাকে backend থেকেই solve করতে হবে।

আসলে browser কীভাবে এটা process করে সেটা বুঝলে problem solve করা যাবে। Browser যখন request send করে, send করার পরে backend থেকে response পাঠায় সেখানে body থাকে, header থাকে। এই header-এর মধ্যেই browser কয়েকটা field search করে। তার মধ্যে উল্লেখযোগ্য হচ্ছে:

  • Access-Control-Allow-Origin: এখানে উল্লেখ থাকে কোন কোন domain API access করতে পারবে। এখন যে domain থেকে request গেছে তার নাম যদি এই list-এ না থাকে তাহলে CORS error দেখাবে।
  • Access-Control-Allow-Methods: এখানেও same logic but এখানে method-এর নাম check করে।

তবে একটা বিষয় অনেক সময়, অন্য কারণেও CORS-এর দেখা যেতে পারে। Browser এই header-গুলো না পেলেই সে CORS error দেখায়। বাকি বিষয়গুলো মাথা ব্যথা নেই। একটা personal experience share করি তাহলে বুঝতে পারবেন।

আমি একটা VPS-এ Nginx setup করে, একটা frontend application host করেছি। কিন্তু কোনো POST request গেলেই CORS error শুধু CORS। কিন্তু backend-এ একদম ঠিকঠাক আছে। প্রায় ৩-৪ ঘণ্টা try করার পরে discover করলাম, application থেকে প্রায় ৪০-৫০MB-এর data server-এ যাচ্ছে। কিন্তু Nginx by default-ভাবে data size 10MB set করে রাখছে। যে কারণে Nginx request return করে দিচ্ছে। আর browser header পাচ্ছে না বলে CORS error-ই show করছে। সেটা ঠিক করার পরে সব ঠিক হয়ে গেছে।

অতএব, backend-এ CORS configure করলেও অনেক ক্ষেত্রে CORS-এর error দেখা যেতে পারে। একটু carefully handle করা দরকার।

Browser Preflight Request

Browser থেকে যখন কোনো write request (POST, PUT, PATCH, DELETE) server-এ যায় তখন সেই request send করার আগে একটা request send করা হয়ে থাকে। এই request-টা OPTIONS method-এ send হয়ে থাকে। এই request-টাকে preflight request বলে। এই method-এর মাধ্যমে check করা হয় যে, browser এই request send করার জন্য allowed কি না।
ওপরের মতো যদি এই request-এর response header-এ Access-Control-Allow-Origin না থাকে, তাহলে browser সাথে সাথে CORS error throw করবে এবং actual write (POST, PUT, PATCH, DELETE) request server-এ send-ই হবে না।
কোনো কারণে যদি server preflight-এ 404 response throw করে, তাহলেও same problem show করবে। এই জন্য server-এ এই method-টা handle করা অত্যন্ত জরুরি।


Hashing: Password কখনো plain text রাখবেন না

একটা situation দিই আপনাকে, আপনার server সেই আকারে secure কোনো vulnerability নেই। এখানে আপনি একটা কাজ করেছেন আপনি user-দের password plain text হিসেবে database-এ store করেছেন। এই situation-এ আপনার server তো hack করতে পারবে না। কিন্তু আপনার database server hack হয়ে গেলো। এবং এখানে আপনার application-এর database-এর user table publish হয়ে গেলো। তাহলে ব্যাপার কী দাঁড়ালো?

Hacker user-দের name + password দুইটাই পেয়ে গেলো। তাহলে আপনার backend এত secure করেও লাভ হলো না। এই অবস্থায় আপনার application-এর কী হবে বুঝতেই তো পারছেন।

এই অবস্থায় আপনার করণীয় হচ্ছে, যখন কোনো user-এর data add করা হবে তখন password-কে hashing করতে হবে যাতে কেউ easily বুঝতে না পারে। Same কাজ password update করার ক্ষেত্রেও same কাজটাই করতে হবে।

এই hashing করার জন্য অনেক algorithm আছে। এখানে একটা জিনিস মাথায় আসছে, এখানে যেহেতু option অনেক advantage, disadvantage থাকবে, আপনাকে research করে বের করতে হবে।


Hashing Algorithm

বিগিনার হিসেবে hashing algorithm নিয়ে research করে শেষ করার মতো না। এখানে অনেক research করতে হবে। তবে Basic level-এ basic কিছু algorithms সম্পর্কে research করলে অনেক কিছু জানা যাবে।

Password Hashing

bcrypt: এটা key stretching-এর জন্য তৈরি করা হয়েছে। এটা rainbow table-কে counter করতে পারে।

Argon2: এটা passwords hashing এবং key derivation function-এর জন্য তৈরি করা হয়েছে। এটা memory-hard, time-hard, and tunable-by-parameter।

Scrypt: এটা memory-hard, time-hard, and tunable-by-parameter।

import bcrypt from "bcrypt";

const SALT_ROUNDS = 12; // Cost factor: ব্রুটফোর্স স্লো করার জন্য যথেষ্ট শক্তিশালী

// ১. রেজিস্ট্রেশনের সময় পাসওয়ার্ড হ্যাশ করা
async function hashPassword(plainPassword) {
  return await bcrypt.hash(plainPassword, SALT_ROUNDS);
}

// ২. লগইনের সময় পাসওয়ার্ড ভেরিফাই করা
async function verifyPassword(plainPassword, hashedPasswordFromDB) {
  // কখনোই `hash === plainPassword` দিয়ে চেক করবেন না!
  // `bcrypt.compare()` ইন্টারনালি constant-time comparison ব্যবহার করে Timing Attack প্রতিরোধ করে
  return await bcrypt.compare(plainPassword, hashedPasswordFromDB);
}
Enter fullscreen mode Exit fullscreen mode

Input Validation ও Parameterized Queries 🛡️

SQL Injection বা NoSQL Injection থেকে বাঁচার একমাত্র সমাধান হলো: User-এর কোনো input-কে সরাসরি query string-এ না বসানো।

  • সর্বদা Parameterized Queries / Prepared Statements বা টাইপ-সেফ ORM (যেমন Prisma, TypeORM, Drizzle) ব্যবহার করুন।
  • রিকোয়েস্ট বডি ভ্যালিডেশনের জন্য Zod বা class-validator ব্যবহার করুন।

JWT Security Best Practices

  • স্বল্পমেয়াদী Access Token: access token-এর expiry time ১৫–৩০ minutes থেকে বেশি রাখবেন না। seesion long time রাখতে Refresh Token Rotation ব্যবহার করতে হবে।
  • টোকেন স্টোরেজ: browser-এর localStorage-এ store করলে XSS অ্যাটাকে এটা চুরি হতে পারে। তাই refresh token সবসময় httpOnly, secure, sameSite কুকিতে সংরক্ষণ করতে হবে।

SSL/TLS: সব traffic encrypted রাখুন

SSL নিয়ে আগেই কথাবার্তা হয়েছে, এখানে কথা বলে লাভ নাই।


বটম লাইন

একটা কথা বলি, আমাকে একজন একটা কথা বলেছিল, যে security নাকি একটা bogus জিনিস। এখানে কোনো কিছুই নাই। আসলে security জিনিসটা কখনো bogus হবে না। Past-এও ছিল না, future-এও হবে না।

API security-এর OWASP Top 10 জানলেই বেশিরভাগ security-গুলো encounter করতে পারবেন। আর নিজের logical thinking + business requirement অনুযায়ী security ensure করেন।

আপনার কাছে security জিনিসটা কীভাবে দেখছেন? নিচে comment-এ জানাবেন।

Top comments (0)