SQL injection: কীভাবে কাজ করে ও কীভাবে ঠেকাবেন

SQL injection আক্রমণকারীর input-কে আপনার query-র অংশ বানিয়ে দেয়। সমাধান সহজ ও সুপরিচিত: string জুড়ে SQL কখনো বানাবেন না।

query-তে ঢুকছে একটি অবিশ্বস্ত string

SQL injection (SQLi) হয় যখন অ্যাপ user input লেখার মধ্যে বসিয়ে SQL query বানায়, ফলে input query-র অর্থ বদলে দিতে পারে। বছরের পর বছর এটি OWASP Top 10-এ আছে, আর আসল সিস্টেমে এখনও পাওয়া যায়।

একটি দুর্বল উদাহরণ

// বিপজ্জনক: string জোড়া দেওয়া
const sql = "SELECT * FROM users WHERE email = '" + email + "' AND password = '" + pass + "'";

User email হিসেবে ' OR '1'='1 লিখলে query হয়:

SELECT * FROM users WHERE email = '' OR '1'='1' AND password = '...'

শর্ত সবসময় সত্য, আর login যাচাই এড়ানো যেতে পারে। আক্রমণকারীর টেক্সট data নয়, SQL কোড হিসেবে ধরা হয়েছে।

আক্রমণকারী কী করতে পারে

Bug ও database permission অনুযায়ী: login এড়ানো, অন্য user-দের data পড়া, data বদলানো বা মোছা, এবং কিছু setup-এ server পর্যন্ত পৌঁছানো। Data ফাঁস প্রায়ই এখান থেকেই শুরু হয়।

ধরন

  • In-band: ফল বা error স্বাভাবিক response-এ আসে (error-based, UNION-based)।
  • Blind: কোনো data দেখা যায় না, কিন্তু আক্রমণকারী true/false পেজের পার্থক্য বা সময় থেকে উত্তর অনুমান করে।
  • Second-order: ক্ষতিকর input প্রথমে নিরাপদে সংরক্ষিত হয়, পরে অন্য query-তে অনিরাপদে ব্যবহৃত হয়।

আসল সমাধান: parameterized query

SQL ও data আলাদাভাবে পাঠান। Database কখনো data-কে কোড ভাবে না।

const row = await db.query(
  "SELECT * FROM users WHERE email = $1 AND password_hash = $2",
  [email, hash]
);

এটি সব ভাষায় কাজ করে (prepared statement, placeholder ? বা $1)। ORM ডিফল্টে এটি ব্যবহার করে।

সাধারণ ভুল

  • ORM-এর ভেতরে raw query। String interpolation দিয়ে raw SQL বানালে bug ফিরে আসে।
  • Parameter করা যায় না এমন গতিশীল অংশ, যেমন table-এর নাম, column-এর নাম বা ORDER BY দিক। Allow-list ব্যবহার করুন: user-এর পছন্দ নির্দিষ্ট জানা মানের সেটে ম্যাপ করুন।
  • হাতে escape করা। ভুল করা সহজ। Parameter ব্যবহার করুন।
  • ভেতরে SQL string বানানো stored procedure।

Defence in depth

  • Least privilege: অ্যাপের database account যেন table মুছতে বা অন্য schema পড়তে না পারে।
  • Input যাচাই করুন (ধরন, দৈর্ঘ্য, ফরম্যাট)। সাহায্য করে, কিন্তু parameter-এর বিকল্প নয়।
  • User-এর কাছ থেকে database error লুকান। ব্যক্তিগতভাবে log করুন।
  • WAF ঝুঁকি কমাতে পারে, কিন্তু কোড ঠিক করে না।
  • Library হালনাগাদ রাখুন এবং string-দিয়ে-বানানো query-র জন্য কোড স্ক্যান (static analysis) করুন।

নিরাপদে পরীক্ষা

শুধু আপনার নিজের বা লিখিত অনুমতি আছে এমন সিস্টেম পরীক্ষা করুন। শেখার নিরাপদ জায়গা: DVWA-র মতো স্থানীয় practice অ্যাপ বা আপনার নিজের staging কপি। অনুমতি ছাড়া আসল সাইটে কখনো পরীক্ষা করবেন না।

মূল কথা: সর্বত্র parameterized query ব্যবহার করুন, গতিশীল অংশ allow-list করুন, অ্যাপকে কম-অধিকারের database user দিন, এবং error-এর বিবরণ লুকান।


ওয়েব সিকিউরিটি সিরিজ, পর্ব ১ (injection ও access control): 1 নম্বর (মোট 4)।

আরও পড়ুন

Security header checklist: HSTS, CSP, frame সুরক্ষা ও আরও

কয়েকটি response header পুরো এক শ্রেণির আক্রমণ বন্ধ করে। সেট করার সংক্ষিপ্ত তালিকা, প্রতিটির কাজ ও পরীক্ষার উপায় দেখুন।

ওয়েব সিকিউরিটি•২ মিনিটে পড়া

XXE: XML external entity আক্রমণ ও বন্ধ করার উপায়

XML-এর একটি feature ডকুমেন্টকে বাইরের কনটেন্ট টেনে আনতে দেয়। আপনার parser অনুমতি দিলে আক্রমণকারী এটি ব্যবহার করতে পারে। সমাধান একটি parser সেটিং।

ওয়েব সিকিউরিটি•২ মিনিটে পড়া