A04: ইনসিকিউর ডিজাইন
এই পাঠে যা শিখবেন
- Insecure Design কীভাবে একটি ইমপ্লিমেন্টেশন বাগ থেকে ভিন্ন — সমস্যাটা লজিকের পরিকল্পনায়, টাইপিং ভুলে নয়
- বিজনেস-লজিক ফ্ল কীভাবে বাস্তব আর্থিক ক্ষতির কারণ হতে পারে (নেগেটিভ-কোয়ান্টিটি উদাহরণ)
- থ্রেট মডেলিং কী, এবং কেন এটি কোড লেখার আগে করতে হয়
- একটি ইনসিকিউর ও সিকিউর চেকআউট ফাংশনের পাশাপাশি তুলনা — কোড সহ
১ · Insecure Design আসলে কী — এবং কেন এটি একটি নতুন ক্যাটাগরি
OWASP Top 10-এর ২০২১ সংস্করণে Insecure DesignInsecure Designনিরাপত্তা নিয়ন্ত্রণ (security control) সম্পূর্ণ অনুপস্থিত বা অকার্যকর থাকার একটি ক্যাটাগরি — যার শিকড় কোডিং পর্যায়ে নয়, বরং ডিজাইন পর্যায়ে। নামে একটি সম্পূর্ণ নতুন ক্যাটাগরি যুক্ত হয়। আগের অনেক ক্যাটাগরি (যেমন L20-এর SQL Injection) একটি ইমপ্লিমেন্টেশন বাগ — কোড ঠিকভাবে লেখা হলে সমস্যাটাই থাকত না। কিন্তু Insecure Design সম্পূর্ণ ভিন্ন স্তরের সমস্যা: এখানে কোডটি ঠিক যেভাবে ডিজাইন করা হয়েছিল সেভাবেই কাজ করছে — সমস্যা হলো, ডিজাইনের সময়ই কেউ নিরাপত্তার দিকটি চিন্তা করেনি।
একটি বাগ ফিক্স করা যায় কোড ঠিক করে। কিন্তু একটি ডিজাইন ত্রুটি ঠিক করতে হলে প্রায়ই পুরো ফিচারটাই পুনর্বিবেচনা করতে হয় — কারণ "নিরাপদ" এবং "অনিরাপদ" সংস্করণ দুটোই একই লজিক অনুযায়ী নিখুঁতভাবে কাজ করছে বলে মনে হয়, যতক্ষণ না কেউ একটি অস্বাভাবিক ইনপুট দিয়ে দেখায় যে সেই লজিকটাই অসম্পূর্ণ ছিল।
২ · বাস্তব উদাহরণ — নেগেটিভ-কোয়ান্টিটি চেকআউট এক্সপ্লয়েট
কল্পনা করুন একটি ই-কমার্স চেকআউট ফ্লো, যেখানে মোট বিল হিসাব হয় সহজভাবে —
total = quantity × price_per_unit। ডেভেলপার হয়তো ধরে নিয়েছেন ব্যবহারকারী সবসময়
একটি ধনাত্মক সংখ্যা (যেমন ১, ২, ৫) পাঠাবে — ফলে সার্ভার-সাইডে কখনো quantity > 0
যাচাই করার কোড লেখাই হয়নি। কিন্তু একজন আক্রমণকারী API রিকোয়েস্টে সরাসরি quantity = -5
পাঠালে কী হবে? গণিত অনুযায়ী total হয়ে যায় ঋণাত্মক — অর্থাৎ দোকান উল্টো আক্রমণকারীকে
"টাকা ফেরত" দিচ্ছে বা তার অ্যাকাউন্টে ক্রেডিট যোগ করছে।
এটি কোনো ইনজেকশন বা মেমরি-করাপশন বাগ নয় — এটি একটি Business Logic FlawBusiness Logic Flawঅ্যাপ্লিকেশনের ব্যবসায়িক নিয়ম/প্রবাহে (যেমন মূল্য হিসাব, ছাড়, লিমিট) এমন একটি ত্রুটি যা কোনো প্রযুক্তিগত বাগ ছাড়াই অপব্যবহারযোগ্য। — সিস্টেম ঠিক যা করতে বলা হয়েছিল তাই করছে, কিন্তু কেউ কখনো ভাবেননি "নেগেটিভ সংখ্যা এলে কী হবে?"
৩ · থ্রেট মডেলিং — ডিজাইন পর্যায়ের প্রতিরক্ষা
Insecure Design ঠেকানোর প্রধান হাতিয়ার হলো থ্রেট মডেলিংThreat Modelingকোড লেখা শুরুর আগে, ডিজাইন পর্যায়ে, সিস্টেমেটিকভাবে প্রশ্ন করা — "এখানে কী ভুল হতে পারে? কে এটি অপব্যবহার করতে পারে? কীভাবে?" — একটি সহজ কিন্তু শক্তিশালী অভ্যাস: কোড লেখা শুরুর আগেই দলগতভাবে বসে জিজ্ঞাসা করা, "এই ফিচারে কী ভুল হতে পারে?" চেকআউট ফ্লোর ক্ষেত্রে এই প্রশ্নটি করলেই কেউ না কেউ জিজ্ঞাসা করত — "quantity যদি ঋণাত্মক হয়?" — এবং সেই মুহূর্তেই সমাধান (server-side validation) ডিজাইনেই লেখা হয়ে যেত।
- সম্পদ চিহ্নিত করুন — কী সুরক্ষা দরকার (এখানে: মূল্য/বিলিং লজিক)।
- সম্ভাব্য অপব্যবহার তালিকা করুন — নেগেটিভ ইনপুট, চরম মান (extreme values), অপ্রত্যাশিত ক্রম।
- প্রতিটির জন্য নিয়ন্ত্রণ ডিজাইন করুন — সার্ভার-সাইড ভ্যালিডেশন, সীমা (limits), deny-by-default।
- যাচাই করুন — টেস্টিং-এ ইচ্ছাকৃতভাবে "খারাপ" ইনপুট দিয়ে দেখুন নিয়ন্ত্রণগুলো কাজ করছে কি না।
৪ · কোড ডেমো — ইনসিকিউর বনাম সিকিউর চেকআউট
নিচের কোড সেলটি সম্পূর্ণ স্যান্ডবক্সড — এটি একটি ভুয়া ইন-মেমরি "প্রাইস ক্যালকুলেটর" নিয়ে কাজ করছে, কোনো বাস্তব
পেমেন্ট গেটওয়ে বা ডেটাবেস স্পর্শ করছে না। প্রথম ফাংশনটি (checkout_insecure) কোনো ভ্যালিডেশন
ছাড়াই ইনপুট গ্রহণ করে — ঠিক যেভাবে একটি বাস্তব A04 দুর্বলতা কাজ করে।
PRICE_PER_UNIT = 500 # টাকা, প্রতি ইউনিট
def checkout_insecure(quantity):
# ইনসিকিউর ডিজাইন: quantity ধনাত্মক কি না তা কখনো যাচাই করা হয়নি
total = quantity * PRICE_PER_UNIT
return total
def checkout_secure(quantity):
# সিকিউর ডিজাইন: থ্রেট মডেলিং থেকে আসা সার্ভার-সাইড বিজনেস-লজিক নিয়ন্ত্রণ
if quantity <= 0:
raise ValueError("quantity অবশ্যই ধনাত্মক (positive) সংখ্যা হতে হবে")
total = quantity * PRICE_PER_UNIT
return total
# আক্রমণকারী নেগেটিভ quantity পাঠানোর চেষ্টা করছে
attacker_quantity = -5
print("== ইনসিকিউর ভার্সন ==")
result_insecure = checkout_insecure(attacker_quantity)
print(f"quantity={attacker_quantity} পাঠানো হলো -> বিল হলো {result_insecure} টাকা")
print("(ঋণাত্মক বিল মানে দোকান উল্টো আক্রমণকারীকে ক্রেডিট দিয়ে দিচ্ছে!)")
print()
print("== সিকিউর ভার্সন ==")
try:
result_secure = checkout_secure(attacker_quantity)
print(f"quantity={attacker_quantity} গৃহীত হলো -> বিল {result_secure} টাকা")
except ValueError as e:
print(f"রিকোয়েস্ট প্রত্যাখ্যান করা হলো: {e}")
print()
valid_quantity = 3
result_valid = checkout_secure(valid_quantity)
print(f"বৈধ quantity={valid_quantity} -> বিল {result_valid} টাকা (স্বাভাবিকভাবে গৃহীত)")
checkout_insecure-এ কোনো "বাগ" নেই, ঠিক যেভাবে লেখা হয়েছে ঠিক সেভাবেই এটি চলছে।
সমস্যাটা কোডে নয়, ডিজাইনে — কেউ কখনো ভাবেননি "নেগেটিভ সংখ্যা এলে কী হবে?" এই একটি প্রশ্নের অভাবই
একটি সম্পূর্ণ A04 দুর্বলতা তৈরি করে দিতে পারে।
checkout_secure কোনো নতুন "সিকিউরিটি ফিচার" যোগ করেনি — এটি শুধু থ্রেট মডেলিং সেশনে ওঠা একটি
সাধারণ প্রশ্নের উত্তরকে সরাসরি কোডে রূপান্তরিত করেছে। এটাই দেখায় কেন থ্রেট মডেলিং ব্যয়বহুল বা জটিল হতে হয় না —
এটি মূলত একটি নিয়মিত প্রশ্ন-জিজ্ঞাসার অভ্যাস।
৫ · Insecure Design বনাম অন্যান্য OWASP ক্যাটাগরির সম্পর্ক
Insecure Design প্রায়ই অন্যান্য ক্যাটাগরির সাথে ওভারল্যাপ করে — যেমন L18-এর Broken Access Control-ও প্রায়ই একটি ডিজাইন-স্তরের সিদ্ধান্তের ফল (কখনো ভাবা হয়নি "প্রতিটি রিকোয়েস্টে owner চেক করতে হবে")। পার্থক্যটা হলো ফোকাস: A04 নির্দিষ্টভাবে সেই ক্যাটাগরিতে পড়ে যেখানে মূল সমস্যাটি একটি অনুপস্থিত ব্যবসায়িক-লজিক বা স্থাপত্যগত নিয়ন্ত্রণ — কোনো একক কোডিং বাগ নয়।
Insecure Design মনে করিয়ে দেয় যে সিকিউরিটি একটি "পরে যোগ করার" ফিচার নয় — এটি ডিজাইনের প্রথম দিন থেকেই চিন্তাভাবনার অংশ হতে হবে। "এখানে কী ভুল হতে পারে?" — এই একটি প্রশ্ন নিয়মিতভাবে জিজ্ঞাসা করাই থ্রেট মডেলিং-এর পুরো সারমর্ম, এবং এটিই সবচেয়ে সাশ্রয়ী নিরাপত্তা বিনিয়োগ — বাগ প্রোডাকশনে যাওয়ার আগেই ধরা পড়ে।
ভাবনার প্রশ্ন
প্রতিটি প্রশ্ন নিজে কিছুক্ষণ ভাবুন — তারপর "→ উত্তর" চাপুন।
প্র ০১ Insecure Design কেন একটি সাধারণ "কোডিং বাগ" থেকে ভিন্ন — এবং কেন এটি ফিক্স করা প্রায়ই বেশি কঠিন?
একটি সাধারণ কোডিং বাগে (যেমন একটি off-by-one error), কোড যেভাবে ডিজাইন করা হয়েছিল সেভাবে চলছে না — একটি লাইন ঠিক করলেই সমাধান। কিন্তু Insecure Design-এ কোড ঠিক যেভাবে ডিজাইন করা হয়েছিল সেভাবেই চলছে — সমস্যাটা হলো ডিজাইনটাই অসম্পূর্ণ ছিল। ফিক্স করতে প্রায়ই পুরো ফিচারের লজিক পুনর্বিবেচনা করতে হয়, নতুন এজ-কেস চিন্তা করতে হয়, এবং কখনো কখনো ব্যবসায়িক সিদ্ধান্ত (যেমন "রিফান্ড পলিসি কী হবে") নতুন করে নিতে হয় — যা একটি এক-লাইনের কোড ফিক্সের চেয়ে অনেক বেশি সময়সাপেক্ষ।
প্র ০২ থ্রেট মডেলিং কোডিং শুরুর আগে করা কেন এত গুরুত্বপূর্ণ — কোডিং-এর পরে করলে সমস্যা কী?
কোডিং শুরুর আগে থ্রেট মডেলিং করলে "কী ভুল হতে পারে" প্রশ্নের উত্তর সরাসরি ডিজাইনেই লেখা হয়ে যায় — অতিরিক্ত খরচ প্রায় শূন্য। কোডিং-এর পরে করলে (বা একেবারেই না করলে) একটি দুর্বলতা হয় প্রোডাকশনে পৌঁছে যায় (real-world exploit ও ক্ষতির ঝুঁকি), অথবা পরে ধরা পড়লেও পুরো ফিচার রিফ্যাক্টর করতে হয় — যা কোডিং-এর আগে একটি সাধারণ আলোচনার চেয়ে বহুগুণ বেশি ব্যয়বহুল ও সময়সাপেক্ষ।
প্র ০৩ নেগেটিভ-কোয়ান্টিটি ছাড়া Insecure Design-এর আরেকটি বাস্তব উদাহরণ ভাবুন — কোন ফিচারে কী প্রশ্ন করা উচিত ছিল?
উদাহরণ: একটি পাসওয়ার্ড-রিসেট ফিচার যেখানে ডিজাইনে কখনো ভাবা হয়নি "একজন ইউজার কতবার রিসেট-কোড রিকোয়েস্ট করতে পারবে?" — সীমাহীন রিকোয়েস্ট অনুমোদিত থাকায় একজন আক্রমণকারী হাজার হাজার রিসেট-কোড জেনারেট করিয়ে ব্রুট-ফোর্স করার সুযোগ পায় (ties to L25/L30)। সঠিক প্রশ্নটি ছিল: "একজন ইউজার প্রতি ঘণ্টায় সর্বোচ্চ কতবার রিসেট রিকোয়েস্ট করতে পারবে, এবং তার পরে কী হবে?" — এই প্রশ্নের উত্তর ডিজাইনেই লেখা থাকলে rate-limiting স্বাভাবিকভাবেই কোডে চলে আসত।
অনুশীলন
-
চিন্তা করুন: একটি "কুপন কোড" ফিচার ডিজাইন করার সময় থ্রেট মডেলিং করলে কোন কোন প্রশ্ন করা উচিত (উদাহরণ: একই কুপন কতবার ব্যবহার করা যাবে)?
সম্ভাব্য প্রশ্ন: একই কুপন কি একই ইউজার একাধিকবার ব্যবহার করতে পারবে? কুপনের কোনো মেয়াদ শেষ তারিখ আছে কি? একাধিক কুপন কি স্ট্যাক (একসাথে যোগ) করা যাবে, এবং সেক্ষেত্রে ছাড় কি ১০০%-এর বেশি হয়ে যেতে পারে? এই প্রশ্নগুলোর উত্তর ডিজাইনেই নির্ধারণ না করলে, আক্রমণকারী কুপন রিপিট করে বা স্ট্যাক করে কার্যত বিনামূল্যে পণ্য নেওয়ার সুযোগ পেতে পারে — ঠিক নেগেটিভ-কোয়ান্টিটি উদাহরণের মতোই একটি বিজনেস-লজিক ফ্ল।
-
পরীক্ষা করুন: উপরের কোড সেলে
attacker_quantity-এর মান0করে Run চেপে দেখুন —checkout_secureকী প্রতিক্রিয়া দেখায়?0-ওquantity <= 0শর্তে পড়ে যায়, তাইcheckout_secureএটিকেও প্রত্যাখ্যান করবে (ValueError রেইজ করবে)। এটি গুরুত্বপূর্ণ, কারণ শুধু নেগেটিভ সংখ্যা নয় — শূন্য কোয়ান্টিটির অর্ডারও অর্থহীন এবং সম্ভাব্য অপব্যবহারযোগ্য (যেমন কোনো সিস্টেম শূন্য-মূল্যের অর্ডারকে ভুলভাবে "সফল পেমেন্ট" হিসেবে গণনা করলে)। ভালো থ্রেট মডেলিং শুধু "নেগেটিভ" নয়, সব সীমারেখা-মান (boundary values) বিবেচনা করে।
আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ
- কোর্সের সম্পূর্ণ সিলেবাস দেখুন ৬০টি পাঠ পরবর্তী পাঠ — A05: সিকিউরিটি মিসকনফিগারেশন — এবং আরও অনেক কিছু।
- Discrete Mathematics কোর্স সহায়ক কোর্স RSA এনক্রিপশন ও নাম্বার থিওরির গণিত শিখতে দেখুন — M7 ক্রিপ্টোগ্রাফি মডিউলের ভিত্তি।
- System Design & Software Architecture কোর্স সঙ্গী কোর্স থ্রেট মডেলিং ও নিরাপদ আর্কিটেকচার সিদ্ধান্ত কীভাবে বড় সিস্টেমে প্রয়োগ হয় তা শিখতে দেখুন।
- সব Courses দেখুন ABCL TECH C, C++, Python, Java, JavaScript, DSA, DBMS, Discrete Mathematics, System Design ও Cybersecurity — সব এক জায়গায়।