ইনপুট ভ্যালিডেশন ও ইনজেকশন টেস্টিং
এই পাঠে যা শিখবেন
- "ট্রাস্ট বাউন্ডারি" ধারণা এবং কেন প্রতিটি বাউন্ডারিতে ভ্যালিডেশন প্রয়োজন
- একজন টেস্টার কীভাবে ইনজেকশন-স্টাইল দুর্বলতা যাচাই করার জন্য প্রতিকূল ইনপুট ডিজাইন করেন
- কেন অতিরিক্ত-কঠোর ভ্যালিডেশনও একটি বাস্তব সমস্যা (বৈধ ইনপুট ভুলভাবে প্রত্যাখ্যান)
- একটি সত্যিকারের, চলমান
unittestস্যুট — ভ্যালিডেশন ফাংশনের সঠিকতা যাচাই
১ · কখনো ইনপুট বিশ্বাস করবেন না
যেকোনো ডেটা যা সিস্টেমের বাইরে থেকে আসে — একটি ফর্ম ফিল্ড, একটি URL প্যারামিটার, একটি API রিকোয়েস্ট বডি, এমনকি একটি ফাইল আপলোড — তা একটি ট্রাস্ট বাউন্ডারি অতিক্রম করে। মূল নীতি সহজ কিন্তু গুরুত্বপূর্ণ: সেই বাউন্ডারিতে ডেটা যাচাই না করে কখনোই এটিকে বিশ্বাস করে সরাসরি কোনো কমান্ড, কোয়েরি, বা আউটপুটে ব্যবহার করা উচিত নয়। এটি M9/L37-এর SAST স্ক্যানার যা খুঁজছিল তার ঠিক বিপরীত দিক — সেখানে আমরা কোডে কোথায় ভ্যালিডেশন নেই তা খুঁজেছিলাম, এখানে আমরা টেস্ট করছি ভ্যালিডেশন লজিক নিজেই সঠিকভাবে কাজ করছে কি না।
২ · টেস্টার কীভাবে প্রতিকূল ইনপুট ডিজাইন করেন
একজন টেস্টার M2-এ শেখা টেকনিকগুলোই এখানে প্রয়োগ করেন — শুধু "সাধারণ" ইনপুটের বদলে ইচ্ছাকৃতভাবে এমন ইনপুট বেছে নেওয়া হয় যা সিস্টেমকে বিভ্রান্ত করার সম্ভাবনা রাখে। কিছু সাধারণ প্রতিকূল ইনপুট প্যাটার্ন:
একটি সিঙ্গেল কোট (
') সাথে একটি SQL কমেন্ট মার্কার (--) বা স্টেটমেন্ট সেপারেটর (;) — কোয়েরির গঠন ভেঙে দেওয়ার চেষ্টা।এমন ইনপুট যা পরে HTML-এ রেন্ডার হলে ব্রাউজারে কোড হিসেবে এক্সিকিউট হতে পারে।
খুব লম্বা স্ট্রিং, খালি স্ট্রিং, বা অপ্রত্যাশিত ক্যারেক্টার এনকোডিং — বাউন্ডারি ভ্যালু অ্যানালাইসিসের (M2/L06) একই চিন্তাভাবনা এখানে প্রযোজ্য।
যেমন একটি অ্যাপোস্ট্রফিসহ নাম ("O'Brien") — এগুলো বাতিল করা উচিত নয়, তাই এগুলোও টেস্ট সেটে থাকা জরুরি।
৩ · একটি সত্যিকারের ইনপুট-ভ্যালিডেশন টেস্ট স্যুট
নিচের কোড সেলে is_safe_input ফাংশনটি একটি সাধারণ ভ্যালিডেশন লজিক প্রয়োগ করে — এটি এমন ইনপুট
প্রত্যাখ্যান করে যাতে (ক) একটি কোট এবং একটি SQL কমেন্ট/সেপারেটর দুটোই আছে, (খ) একটি ক্লাসিক
OR 1=1-স্টাইল প্যাটার্ন আছে, অথবা (গ) একটি স্ক্রিপ্ট-ট্যাগ-স্টাইল প্যাটার্ন আছে। একটি
সত্যিকারের unittest.TestCase এটিকে বেনাইন ও প্রতিকূল উভয় ইনপুট দিয়ে চালিয়ে যাচাই করে।
import re
import unittest
def is_safe_input(value):
"""একটি সরল ভ্যালিডেশন ফাংশন — সন্দেহজনক প্যাটার্নযুক্ত ইনপুট প্রত্যাখ্যান করে।"""
if not isinstance(value, str):
return False
lowered = value.lower()
# কোট + কমেন্ট মার্কার/সেপারেটর একসাথে থাকলে সন্দেহজনক
if "'" in value and ("--" in value or ";" in value):
return False
# ক্লাসিক "OR 1=1"-স্টাইল প্যাটার্ন
if re.search(r"or\s+1\s*=\s*1", lowered):
return False
# স্ক্রিপ্ট-ট্যাগ-স্টাইল প্যাটার্ন
if "<script" in lowered:
return False
return True
class InputValidationTests(unittest.TestCase):
def test_accepts_plain_email(self):
self.assertTrue(is_safe_input("john.doe@example.com"))
def test_accepts_apostrophe_in_name(self):
# বৈধ ব্যবহারকারী — শুধু কোট থাকলেই প্রত্যাখ্যান করা উচিত নয়
self.assertTrue(is_safe_input("O'Brien"))
def test_accepts_semicolon_in_prose(self):
# শুধু সেমিকোলন থাকলেই (কোট ছাড়া) প্রত্যাখ্যান করা উচিত নয়
self.assertTrue(is_safe_input("Please review this; it looks correct"))
def test_rejects_sql_comment_injection(self):
self.assertFalse(is_safe_input("admin'--"))
def test_rejects_sql_drop_table(self):
self.assertFalse(is_safe_input("'; DROP TABLE users;--"))
def test_rejects_or_1_equals_1(self):
self.assertFalse(is_safe_input("' OR 1=1 --"))
def test_rejects_script_tag(self):
self.assertFalse(is_safe_input("<script>alert(1)</script>"))
suite = unittest.TestLoader().loadTestsFromTestCase(InputValidationTests)
unittest.TextTestRunner(verbosity=2).run(suite)
test_accepts_apostrophe_in_name এবং test_accepts_semicolon_in_prose
দুটোই পাস করে — কারণ is_safe_input-এর প্রথম চেকটি শুধু তখনই প্রত্যাখ্যান করে যখন কোট
(') এবং কমেন্ট/সেপারেটর (-- বা ;) দুটোই একসাথে
উপস্থিত থাকে — একা একা কোনোটিই যথেষ্ট নয়। এই "AND" শর্তটিই "O'Brien"-এর মতো বৈধ ইনপুটকে
ভুলভাবে প্রত্যাখ্যান হওয়া থেকে বাঁচায়, অথচ "admin'--"-এর মতো প্রকৃত প্রতিকূল ইনপুট ঠিকই
ধরা পড়ে।
ইনপুট ভ্যালিডেশন টেস্টিং মানে শুধু "খারাপ ইনপুট প্রত্যাখ্যান হচ্ছে কি না" যাচাই করা নয় — সমান গুরুত্বপূর্ণ হলো "বৈধ ইনপুট ভুলভাবে প্রত্যাখ্যান হচ্ছে না তো" তা যাচাই করা। উভয় দিকের টেস্ট কেস ছাড়া একটি ভ্যালিডেশন ফাংশনের প্রকৃত মান বোঝা যায় না — এটিই M2-তে শেখা "ইতিবাচক ও নেতিবাচক টেস্ট কেস" নীতির একটি প্রত্যক্ষ প্রয়োগ।
ভাবনার প্রশ্ন
প্রতিটি প্রশ্ন নিজে কিছুক্ষণ ভাবুন — তারপর "→ উত্তর" চাপুন।
প্র ০১
যদি is_safe_input-এর প্রথম চেকটি শুধু "'" in value হতো (কমেন্ট মার্কার/
সেপারেটরের শর্ত ছাড়াই), তাহলে কোন টেস্ট কেসটি ব্যর্থ হতো, এবং কেন?
test_accepts_apostrophe_in_name ব্যর্থ হতো — কারণ "O'Brien"-এ একটি কোট আছে,
তাই সরলীকৃত চেকটি (শুধু কোট থাকলেই প্রত্যাখ্যান) এটিকে ভুলভাবে অনিরাপদ হিসেবে ফ্ল্যাগ করত। এটি ঠিক সেই
সমস্যা যা "শুধু একটি সন্দেহজনক ক্যারেক্টার থাকলেই প্রত্যাখ্যান" ধরনের অতিরিক্ত-সরল ভ্যালিডেশন লজিকে
ঘটে — বাস্তব ব্যবহারকারীদের জন্য বিরক্তিকর ফলস পজিটিভ তৈরি করে।
প্র ০২ "ট্রাস্ট বাউন্ডারি" ধারণাটি শুধু ওয়েব ফর্মের ক্ষেত্রেই প্রযোজ্য, নাকি আরও ব্যাপক? উদাহরণ দিন।
আরও ব্যাপক — যেকোনো জায়গা যেখানে ডেটা এক নিয়ন্ত্রণ ডোমেইন থেকে অন্যটিতে প্রবেশ করে তা একটি ট্রাস্ট বাউন্ডারি। উদাহরণ: একটি মাইক্রোসার্ভিস অন্য একটি সার্ভিসের API রেসপন্স গ্রহণ করছে, একটি ফাইল আপলোড প্রসেস করা হচ্ছে, এমনকি একটি এনভায়রনমেন্ট ভেরিয়েবল বা কনফিগারেশন ফাইল থেকে পড়া ডেটা — যদি এটি সম্পূর্ণ নিয়ন্ত্রিত সোর্স থেকে না আসে, তবে সেটিও একটি ট্রাস্ট বাউন্ডারি হিসেবে বিবেচনা করা উচিত।
প্র ০৩
উপরের কোড সেলে test_rejects_or_1_equals_1-এর ইনপুট "' OR 1=1 --"
আসলে দুটো আলাদা চেকেই ধরা পড়ে যায় কি না? ব্যাখ্যা করুন।
হ্যাঁ — এই ইনপুটে কোট (') এবং কমেন্ট মার্কার (--) দুটোই আছে, তাই প্রথম চেকেই
এটি প্রত্যাখ্যাত হয়। একই সাথে এতে OR 1=1-স্টাইল প্যাটার্নও আছে, যা দ্বিতীয় চেকেও ধরা পড়ত।
এটি দেখায় বাস্তব প্রতিকূল ইনপুট প্রায়ই একাধিক সন্দেহজনক প্যাটার্ন একসাথে বহন করে — একটি স্তরযুক্ত
(layered) ভ্যালিডেশন লজিক তাই আরও শক্তিশালী হয়।
অনুশীলন
-
চিন্তা করুন:
is_safe_input-এ আর কোন কোন বৈধ-কিন্তু-অস্বাভাবিক ইনপুট টেস্ট করা উচিত বলে আপনার মনে হয়, যা ভুলভাবে প্রত্যাখ্যাত হতে পারে? (হিন্ট: ঠিকানায় সেমিকোলন-পৃথক একাধিক লাইন, অথবা গাণিতিক আলোচনায় "1=1" শব্দগুচ্ছ)যুক্তিসঙ্গত প্রার্থী:
"Line 1; Line 2; Line 3"(একাধিক সেমিকোলন, কিন্তু কোনো কোট নেই — বর্তমান লজিকে ঠিকভাবেই গ্রহণযোগ্য হবে), অথবা"In math, x=1 or y=1 satisfies it"(এখানে "or" ও "1" শব্দ আছে কিন্তুre.search(r"or\s+1\s*=\s*1", ...)প্যাটার্নটি ঠিক মিলবে কি না তা নির্ভর করে স্পেসিং/গঠনের উপর — এটি regex-ভিত্তিক চেকের একটি বাস্তব সীমাবদ্ধতা, সবসময় নিখুঁত নয়)। -
পরীক্ষা করুন: উপরের কোড সেলে
is_safe_input-এর প্রথমifশর্তেand-কেor-এ পরিবর্তন করে (অর্থাৎ কোট অথবা কমেন্ট মার্কার যেকোনো একটি থাকলেই প্রত্যাখ্যান) Run চেপে দেখুন কোন টেস্ট কেসটি এখন ব্যর্থ হয়।test_accepts_apostrophe_in_nameব্যর্থ হবে — কারণor-এ পরিবর্তনের পর শুধু একটি কোট থাকলেই ("O'Brien") শর্তটি সত্য হয়ে যায় এবং ফাংশনটি ভুলভাবেFalseরিটার্ন করে, অথচ টেস্টটিassertTrueআশা করছে। এটি ঠিক সেই ট্রেড-অফ যা প্র ০১-এ আলোচনা করা হয়েছিল।
আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ
- কোর্সের সম্পূর্ণ সিলেবাস দেখুন ৫৭টি পাঠ অথেন্টিকেশন/অথোরাইজেশন টেস্টিং ও SDLC-তে সিকিউরিটি — এই মডিউলের বাকি পাঠগুলো পরবর্তী।
- Cybersecurity কোর্স সহোদর কোর্স ইনজেকশন-স্টাইল অ্যাটাকের টেকনিক্যাল প্রক্রিয়া সেই কোর্সে বিস্তারিতভাবে কভার করা হয়েছে।
- সব Courses দেখুন ABCL TECH C, C++, Python, Java, JavaScript, DSA, DBMS, Discrete Mathematics, System Design, Cybersecurity, Cloud Computing & DevOps, Computer Networks, Operating Systems, Computer Architecture, Programming Languages & Compiler Design, Software Engineering & Git, Theory of Computation, Engineering Economics, Full-Stack Web Frameworks, Mobile App Development, Ethics in Computing & AI Safety ও Software Testing & Quality Assurance — সব এক জায়গায়।