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

দুই দশকেরও বেশি সময় ধরে OWASP Top 10 তালিকার অন্যতম শীর্ষ ঝুঁকি হিসেবে এসকিউএল ইনজেকশন (SQL Injection বা SQLi) বিদ্যমান রয়েছে। যখন কোনো ওয়েব অ্যাপ্লিকেশন ব্যবহারকারীর ইনপুট যাচাই না করে সরাসরি ডায়নামিক এসকিউএল কোয়েরিতে যুক্ত করে, তখন আক্রমণকারীরা কোয়েরির গঠন পরিবর্তন করে অথেনটিকেশন বাইপাস, ডাটাবেস থেকে সংবেদনশীল তথ্য চুরি কিংবা অ্যাডমিনিস্ট্রেটিভ কমান্ড চালাতে পারে।
যেকোনো ব্যাকএন্ড ডেভেলপার ও সিকিউরিটি ইঞ্জিনিয়ারের জন্য এসকিউএল ইনজেকশনের অভ্যন্তরীণ কার্যপদ্ধতি এবং এর স্থায়ী প্রতিরোধ ব্যবস্থা জানা অপরিহার্য।
এসকিউএল ইনজেকশন কীভাবে ঘটে
এসকিউএল ইনজেকশনের মূল কারণ হলো একটি আর্কিটেকচারাল ভুল: অবিশ্বস্ত ইউজার ইনপুটকে এক্সিকিউটেবল কোড হিসেবে বিবেচনা করা।
একটি সাধারণ দুর্বল কোয়েরির উদাহরণ দেখা যাক:
-- দুর্বল ডায়নামিক কোয়েরি গঠন
SELECT * FROM users WHERE email = 'USER_INPUT' AND password_hash = 'PASSWORD_INPUT';
অ্যাপ্লিকেশনে যদি স্ট্রিং কনক্যাটেনেশন ব্যবহার করা হয়:
// বিপজ্জনক স্ট্রিং কনক্যাটেনেশন
const query = `SELECT * FROM users WHERE email = '${req.body.email}' AND password_hash = '${passwordHash}'`;
তখন একজন আক্রমণকারী ইমেইল ফিল্ডে নিচের মতো পে-লোড প্রদান করতে পারে:
admin@example.com' OR '1'='1
ডাটাবেস ইঞ্জিন সিঙ্গেল কোট (') কে স্ট্রিংয়ের সমাপ্তি হিসেবে গণ্য করে এবং পরিবর্তিত কোয়েরি এক্সিকিউট করে:
SELECT * FROM users WHERE email = 'admin@example.com' OR '1'='1' AND password_hash = '...';
যেহেতু '1'='1' সবসময় সত্য (true), তাই পাসওয়ার্ড যাচাই ছাড়াই ডাটাবেস অ্যাডমিন ব্যবহারকারীর রেকর্ড রিটার্ন করে দেয়।
এসকিউএল ইনজেকশনের প্রধান ধরন
ডাটাবেস পে-লোডের প্রতি কীভাবে প্রতিক্রিয়া জানায়, তার ওপর ভিত্তি করে সিকিউরিটি ইঞ্জিনিয়াররা একে তিনটি প্রধান ভাগে বিভক্ত করেন:
| ক্যাটাগরি | সাব-টাইপ | শনাক্তকরণ ও ডাটা চুরির পদ্ধতি | ঝুঁকির মাত্রা |
|---|---|---|---|
| In-Band (ক্লাসিক্যাল) | Error-Based | ডাটাবেস এরর মেসেজের মাধ্যমে টেবিল ও সিনট্যাক্স তথ্য ফাঁস হয় | উচ্চ (দ্রুত তথ্য ফাঁসের ঝুঁকি) |
| In-Band (ক্লাসিক্যাল) | Union-Based | UNION SELECT ব্যবহার করে অন্য টেবিলের সম্পূর্ণ ডাটা বের করে আনা |
ক্রিটিক্যাল (পূর্ণাঙ্গ টেবিল এক্সফিল্ট্রেশন) |
| Inferential (ব্লাইন্ড) | Boolean-Based | এইচটিটিপি রেসপন্সের পরিবর্তন (True বনাম False) বিশ্লেষণ করে ডাটা অনুমান | উচ্চ (ধাপে ধাপে ডাটা রিকভারি) |
| Inferential (ব্লাইন্ড) | Time-Based | স্লিপ ফাংশন ইনজেক্ট করে (যেমন pg_sleep(5)) রেসপন্স টাইমের মাধ্যমে তথ্য নেওয়া |
উচ্চ (লুকানো অবস্থায় তথ্য চুরি) |
| Out-of-Band (OOB) | DNS / HTTP Trigger | ডাটাবেস সার্ভারকে আক্রমণকারীর নিজস্ব সার্ভারে ডিএনএস রিকোয়েস্ট পাঠাতে বাধ্য করা | ক্রিটিক্যাল (লোকাল ফায়ারওয়াল বাইপাস) |
অ্যাপ্লিকেশনের অথরাইজেশন লেয়ার কীভাবে ডাটাবেসের সাথে যুক্ত থাকে তা বিশদ জানতে আমাদের JWT সিকিউরিটির ভুলসমূহ এবং CORS কনফিগারেশন গাইড পড়ে দেখতে পারেন।
প্রধান সমাধান: প্যারামিটারাইজড কোয়েরি এবং প্রিপেয়ার্ড স্টেটমেন্টস
এসকিউএল ইনজেকশন স্থায়ীভাবে নির্মূল করার সর্বোত্তম ও কার্যকর পদ্ধতি হলো প্যারামিটারাইজড কোয়েরি (Parameterized Queries) বা প্রিপেয়ার্ড স্টেটমেন্টস (Prepared Statements) ব্যবহার করা।
প্রিপেয়ার্ড স্টেটমেন্টে ডাটাবেস ইঞ্জিন প্যারামিটার বাইন্ড করার আগেই মূল কোয়েরির গঠন কম্পাইল করে নেয়। ফলে ইনপুটকে কখনোই এক্সিকিউটেবল কোড হিসেবে নয়, শুধুমাত্র লিটারেল ডাটা (Plain Data) হিসেবে গণ্য করা হয়:
// নোড-পোস্টগ্রেস (pg) লাইব্রেরিতে নিরাপদ প্যারামিটারাইজড কোয়েরি
const query = 'SELECT id, email, role FROM users WHERE email = $1 AND active = $2';
const values = [req.body.email, true];
const result = await db.query(query, values);
আক্রমণকারী যদি ' OR '1'='1 প্রদান করে, তবুও ডাটাবেস এমন ইউজার খুঁজবে যার ইমেইল টেক্সট অবিকল "admin@example.com' OR '1'='1"। ফলে ইনজেকশন পুরোপুরি ব্যর্থ হয়।
বিভিন্ন ফ্রেমওয়ার্কে নিরাপদ প্যারামিটারাইজেশন
| টেকনোলজি | ঝুঁকিপূর্ণ কোড (পরিহার করুন) | নিরাপদ প্যারামিটারাইজড সিনট্যাক্স |
|---|---|---|
| Node.js (pg) | db.query(\SELECT * FROM users WHERE id = ${id}`)` |
db.query('SELECT * FROM users WHERE id = $1', [id]) |
| Python (psycopg2) | cursor.execute("SELECT * FROM items WHERE name = '%s'" % name) |
cursor.execute("SELECT * FROM items WHERE name = %s", (name,)) |
| PHP (PDO) | $pdo->query("SELECT * FROM accounts WHERE id = " . $_GET['id']) |
$stmt = $pdo->prepare('SELECT * FROM accounts WHERE id = ?'); $stmt->execute([$id]); |
| Go (database/sql) | db.Query(fmt.Sprintf("SELECT * FROM logs WHERE tag = '%s'", tag)) |
db.Query("SELECT * FROM logs WHERE tag = ?", tag) |
অতিরিক্ত নিরাপত্তা ব্যবস্থা (ডিফেন্স ইন ডেপথ)
শুধুমাত্র প্রিপেয়ার্ড স্টেটমেন্টসের ওপর নির্ভর না করে মাল্টি-লেয়ার ডিফেন্স নিশ্চিত করা উচিত:
- ওআরএম (ORM) ব্যবহারে সতর্কতা: Prisma, Drizzle বা SQLAlchemy ডিফল্টভাবে প্যারামিটারাইজড কোয়েরি ব্যবহার করে। তবে র কোয়েরি এসকেপ মেকানিজম (
prisma.$queryRawUnsafeবাdb.session.execute(text(...))) ব্যবহারের ক্ষেত্রে অত্যন্ত সতর্ক থাকতে হবে। - ন্যূনতম প্রিভিলেজ নীতি (Least Privilege): অ্যাপ্লিকেশন ডাটাবেস ইউজারকে কেবল প্রয়োজনীয় পারমিশন প্রদান করুন। সাধারণ অ্যাপ্লিকেশনের ইউজারের কাছে কখনই
DROP TABLE,ALTERবা সুপারইউজার প্রিভিলেজ থাকা উচিত নয়। - ইনপুট ভ্যালিডেশন: আইডি বা নিউমেরিক ফিল্ড ডাটাবেসে পাঠানোর আগেই ইন্টিজার হিসেবে নিশ্চিত করুন (যেমন জাভাস্ক্রিপ্টে
parseInt(req.params.id, 10))। - বিস্তারিত এরর মেসেজ প্রদর্শন বন্ধ রাখুন: প্রোডাকশন পরিবেশে কোনো অবস্থাতেই ডাটাবেস এরর বা স্ট্যাক ট্রেস ব্যবহারকারীকে দেখানো যাবে না।
প্রজেক্টের আর্কিটেকচার দীর্ঘমেয়াদে সুরক্ষিত রাখতে আমাদের ক্লিন কোড ও কোড রিভিউ নীতিমালা দেখুন।
কোড রিভিউ ও অডিট চেকলিস্ট
ডাটাবেস কোড প্রোডাকশনে তোলার আগে নিচের বিষয়গুলো যাচাই করুন:
- প্রতিটি এসকিউএল কোয়েরি পজিশনাল বা নেইমড প্যারামিটার ব্যবহার করছে; কোনো স্ট্রিং কনক্যাটেনেশন নেই।
- ডাটাবেস ইউজার ন্যূনতম প্রিভিলেজে রান করছে এবং স্কিমা পরিবর্তন করার অনুমতি নেই।
- প্রোডাকশন এরর ইন্টারনাল লগে সংরক্ষিত হচ্ছে এবং ইউজারের কাছে জেনেরিক HTTP 500 রেসপন্স যাচ্ছে।
- সিআই/সিডি পাইপলাইনে স্ট্যাটিক অ্যানালাইসিস (SAST) টুল ডায়নামিক কোয়েরি স্ক্যান করছে।
সারসংক্ষেপ
এসকিউএল ইনজেকশন পুরোপুরি প্রতিরোধযোগ্য একটি দুর্বলতা। প্যারামিটারাইজড কোয়েরি ব্যবহারের মাধ্যমে ডাটা ও কোডের সুস্পষ্ট বিভাজন বজায় রাখা, ডাটাবেসের সীমিত অ্যাক্সেস নিশ্চিত করা এবং নিয়মিত কোড অডিটের মাধ্যমে যেকোনো অ্যাপ্লিকেশনে এসকিউএল ইনজেকশনের ঝুঁকি চিরতরে দূর করা সম্ভব।
তথ্যসূত্র: OWASP Top 10 Web Application Security Risks, CWE-89: Improper Neutralization of Special Elements used in an SQL Command, NIST SP 800-53 Guidelines (মূল্যায়ন নভেম্বর ২০২৬)।


