সরাসরি পর্বে যান
পর্ব ৮০ · ৮০-এর মধ্যে · মডিউল ১৩

Security engineer ইন্টারভিউ — নকশা, secure coding, cloud আর আচরণগত প্রশ্ন

Security Engineer Interview — Design, Secure Coding, Cloud and Behavioural Questions

Taught in Bangla, this page prepares security engineer interviews: role types, spoken threat modelling with a rubric, 12 secure code review drills with runnable checkers, authentication and session design, cryptography choices, cloud, Kubernetes, supply chain and CI/CD gates, AI security, incidents and prioritisation, a mock interview, STAR behavioural answers and a 30-day revision plan.

এই পর্বে যা শিখবেন

  • File-sharing, payment আর internal admin tool-এর threat model গুছিয়ে মুখে বলা
  • ছোট কোড পড়ে ত্রুটি ধরা, সমাধান লেখা আর finding-এর গুরুত্ব বোঝানো
  • Authentication, session, cryptography, cloud, Kubernetes, supply chain আর AI-র প্রশ্নে যুক্তিসহ উত্তর দেওয়া
  • সীমিত সময়ে কোন কাজ আগে, তা হিসাব করে ঠিক করা আর ডেভেলপার ও নেতৃত্বকে ঝুঁকি বোঝানো
  • STAR কাঠামোয় নিজের সত্যি ঘটনা বলা, আর ৩০ দিনে পুরো কোর্স ঝালিয়ে নেওয়া

এই পাতা সম্পর্কে: প্রশ্নগুলো কোনো নির্দিষ্ট কোম্পানি, পরীক্ষা বা নিয়োগ থেকে নেওয়া নয়। এ ধরনের প্রশ্ন প্রায়ই আসে, তবে আপনার ইন্টারভিউ ভিন্ন হতে পারে। সব প্রতিষ্ঠান, সেবা আর ঘটনা কাল্পনিক, শুধু প্রকাশিত রিপোর্টের ঘটনাগুলো ছাড়া। কোড snippet-এ <user-input> মানে বাইরের কোনো মান, এটি কোনো হামলার লেখা নয়। চলার যোগ্য ব্লকগুলোর আউটপুট আসলেই চালিয়ে নেওয়া, আর তাদের ডেটা নমুনা।

মহল্লায় নতুন ব্যাংক শাখা খোলার আগে মালিক নিরাপত্তা প্রধানকে শুধু জিজ্ঞেস করেন না, “তালার নাম কী?” তিনি বলেন, “এই নকশাটা দেখুন। টাকা কোন পথে যায়? কোথায় ভুল হতে পারে? আগামী মাসে বাজেট মাত্র তিনটি কাজের, কোন তিনটি করবেন?” Security engineer ইন্টারভিউও এমন। সংজ্ঞা জানা শুরু মাত্র। আসল পরীক্ষা হলো আপনি নকশা পড়তে পারেন কি না, কোড পড়ে ত্রুটি ধরতে পারেন কি না, আর মানুষকে বুঝিয়ে সিদ্ধান্তে আনতে পারেন কি না।

প্রশ্নের কঠিনতার চিহ্ন: (সহজ), (মাঝারি), (কঠিন). SOC-র দিকের log আর triage-এর প্রশ্ন আছে পর্ব ৭৯ · SOC analyst ইন্টারভিউ-তে। লিখিত আর মৌখিক ধারণার প্রশ্ন আছে পর্ব ৭৮-এ।

১ · ভূমিকার ধরন আর ইন্টারভিউর মানচিত্র

রিভিশন: পর্ব ০১, পর্ব ০৩, পর্ব ০৬ · আইন আর নৈতিকতা, পর্ব ৬৭

“Security engineer” নামটি একেক জায়গায় একেক কাজ বোঝায়। আবেদনের আগে job description পড়ে বুঝুন, আপনার কাজ কোন ঘরে পড়ে। নিচের ভাগটি মোটা দাগের। অনেক ছোট দলে একজনই কয়েকটি ভূমিকা সামলান।

ভূমিকামূল কাজপ্রশ্ন সাধারণত যেদিকে যায়
Application বা product security engineerDesign review, code review, developer-দের সাহায্যThreat model, OWASP, secure code, auth (অংশ ২–৪)
Security engineer (সাধারণ)নিরাপত্তার টুল ও ব্যবস্থা বানানো, চালানোসব দিকের মিশ্রণ, কোড আর automation
Cloud security engineerপরিচয়, network, cloud-এর সেটিং, KubernetesIAM, misconfiguration, leaked key, CI/CD (অংশ ৬)
Detection বা SOC engineerLog, detection rule, incidentTriage, Sigma, hunting (পর্ব ৭৯)
Security architectবড় নকশা, মান ঠিক করাTrade-off, zero trust, দলের সাথে কাজ
GRC বিশ্লেষকঝুঁকি, policy, audit, vendorISO 27001, risk register, প্রমাণ (পর্ব ৬৯)

ধাপগুলো প্রতিষ্ঠানভেদে আলাদা। সাধারণত যা দেখা যায়: একটি প্রাথমিক আলাপ, একটি কারিগরি আলাপ, একটি নকশার সেশন, একটি code review বা বাড়ির কাজ, আর একটি আচরণগত আলাপ। সব জায়গায় সব ধাপ থাকবে, তা নয়।

প্র ১Security engineer আর SOC analyst-এর কাজে পার্থক্য কী? (সহজ)

উত্তর: SOC analyst সাধারণত চলমান সতর্কতা দেখেন, তদন্ত করেন আর সাড়া দেন। Security engineer সাধারণত ব্যবস্থা বানান, যাতে সমস্যা কম ঘটে আর ঘটলে দ্রুত ধরা পড়ে: নকশা review, secure default, টুল, automation. একটি দারোয়ানের কাজের মতো, অন্যটি বাড়ির নকশা আর তালার ব্যবস্থার মতো। দুটি একে অন্যকে শক্ত করে: SOC-র ঘটনা থেকেই engineer শেখেন কোন control দুর্বল।

ফলো-আপ: “কোনটিতে কোডিং বেশি?” — সাধারণত engineer ভূমিকায়, তবে detection engineering-এও কোড লাগে। প্রতিষ্ঠান দেখে বলুন।

প্র ২একজন ভালো security engineer-এর মূল গুণ কী মনে করেন? (সহজ)

উত্তর: “না” বলা নয়, নিরাপদ পথ খুঁজে দেওয়া। আমি তিনটি জিনিস বলব। এক, সিস্টেম কীভাবে ভাঙতে পারে তা ধারণার স্তরে বোঝা। দুই, ঝুঁকিকে ক্রম আর সংখ্যায় আনা, কারণ সব সারানো যায় না। তিন, ডেভেলপারের সাথে এমনভাবে কাজ করা যাতে নিরাপদ পথটিই সহজ পথ হয়। যেমন, একটি নিরাপদ library বা default, যা বারবার পরামর্শ দেওয়ার দরকারই কমায়।

ফলো-আপ: “একটি উদাহরণ?” — এখানে নিজের প্রজেক্টের সত্যি উদাহরণ দিন। “ভালো উত্তর” হলো নির্দিষ্ট উত্তর।

প্র ৩নিরাপত্তা অনুশীলন কোথায় করেন? কোনো সাইটের ত্রুটি খুঁজে দেখেছেন? (মাঝারি)

উত্তর: এই প্রশ্নে আইনি বিচারবোধও দেখা হয়। আমি নিজের lab, নিজের যন্ত্র, অনুশীলনের জন্য বানানো আইনসম্মত পরিবেশ আর লিখিত অনুমতি আছে এমন জায়গায় কাজ করি। Bug bounty করলে প্রোগ্রামের লেখা scope মেনে চলি। অনুমতি ছাড়া কারও system পরীক্ষা করা অপরাধ হতে পারে, উদ্দেশ্য ভালো হলেও। বাংলাদেশের আইন আর দায়িত্বশীল প্রকাশের নিয়ম পর্ব ০৬-এ আছে।

ফলো-আপ: “ইন্টারভিউর বাড়ির কাজে একটি লক্ষ্য দিলে?” — শুধু তাদের দেওয়া লিখিত লক্ষ্য আর সীমার ভেতরে। সীমা অস্পষ্ট হলে আগে জিজ্ঞেস করব।

প্র ৪যে প্রশ্নের উত্তর জানেন না, সেখানে কী বলবেন? (সহজ)

উত্তর: তিন অংশে বলুন: যা জানি, যা জানি না, আর কীভাবে জানব। যেমন: “এই নির্দিষ্ট CVE আমি পড়িনি। ধরনটি বুঝলে প্রভাব বলতে পারি। আমি vendor-এর advisory, KEV আর আমাদের SBOM দেখব।” অনুমান করলে আগে বলে নিন, “এটি আমার অনুমান।” নিরাপত্তায় বানানো CVE নম্বর বা standard বলা খুব খারাপ সংকেত, কারণ এই কাজের ভিত্তিই বিশ্বাস।

২ · Secure design ইন্টারভিউ — threat model মুখে বলা

রিভিশন: পর্ব ০৪ · Threat modeling, পর্ব ০৩, পর্ব ৪৫, পর্ব ৭৫ · ক্যাপস্টোন, System Design · নিরাপত্তার নকশা

নকশার সেশনে প্রশ্ন প্রায়ই খোলা থাকে: “এই সেবার threat model করুন।” তাড়াহুড়ো করে OWASP-এর তালিকা বলা সবচেয়ে সাধারণ ভুল। পর্ব ০৪-এর চারটি প্রশ্ন মনে রাখুন: কী নিয়ে কাজ করছি, কী ভুল হতে পারে, কী করব, কাজটি ভালো হলো কি না। ইন্টারভিউর জন্য এটিকে পাঁচ ধাপে ভাঙুন।

  1. পরিধি: কারা ব্যবহার করে, কী ডেটা, কত বড়, কোন নিয়ম খাটে? দুই-তিনটি প্রশ্ন করে নিন।
  2. সম্পদ: কী হারালে সবচেয়ে ক্ষতি? ক্রম দিন।
  3. ছবি: একটি DFD আঁকুন, আর trust boundary দাগান।
  4. ঝুঁকির ক্রম: STRIDE দিয়ে খুঁজুন, তারপর likelihood × impact দিয়ে ওপরের পাঁচটি বাছুন।
  5. Control আর trade-off: প্রতিটি threat-এর control, তার দাম, যা বাকি থাকে (residual risk), আর কীভাবে ধরা পড়বে।

আদর্শ উত্তর ১: file-sharing সেবা

ধরা যাক “ফাইলঘর” নামের একটি কাল্পনিক সেবা। প্রতিষ্ঠানের কর্মীরা ফাইল তোলেন, আর link দিয়ে বাইরের মানুষের সাথে ভাগ করেন। আগে ছবিটি দেখুন।

ফাইলঘরের DFD আর trust boundary

Data flow diagram with three trust boundaries

ফাইলঘরের data flow আর trust boundary কর্মী (login) বাইরের গ্রাহক (link) API পরিচয় আর অনুমতি যাচাই Metadata কে, কোন link Object store ফাইলের বাইট Scanner আলাদা sandbox TB1: internet → app TB2: app → ডেটা TB3: অচেনা ফাইল → scanner TB = trust boundary, যেখানে বিশ্বাসের মাত্রা বদলায়
ছবি ৮০.১ — প্রতিটি দাগ পার হওয়ার জায়গাই প্রশ্ন তোলে: কে যাচাই করছে, আর ভুল হলে ক্ষতি কতদূর যায়?
ফাইলঘর · কাল্পনিক সেবা
ধাপ
মুখে বলুন
  1. পরিধি। আগে প্রশ্ন করুন। উত্তরগুলো নকশা বদলায়: NID-এর scan থাকলে এটি পর্ব ৭০-এর উপাত্ত সুরক্ষার বিষয়, আর লগইনহীন link মানে পরিচয়ের একমাত্র প্রমাণ link নিজেই।
  2. সম্পদ। ক্রম দিন, কারণ ক্রম না থাকলে সবই সমান জরুরি মনে হয়। ফাইলের ডেটাই এখানে মূল। Audit log তালিকায় থাকে, কারণ ঘটনার পরে সেটিই প্রমাণ।
  3. DFD. ছবি ৮০.১ মুখে বর্ণনা করুন। TB3-ই লক্ষ করার মতো: scanner অচেনা ফাইল খোলে, তাই তাকেই সবচেয়ে কম বিশ্বাস করুন, আর ডেটা থেকে আলাদা রাখুন।
  4. শীর্ষ threat. ১৫ বা বেশি উঁচু, ৮ থেকে ১৪ মাঝারি: এটি পর্ব ০৪-এর মাপ। সংখ্যা মতামত, মাপ নয়, তাই সংখ্যার পেছনের কারণটিও বলুন। T1-ই সবার ওপরে, কারণ multi-tenancy-তে একটি ভুলই সব গ্রাহকের ক্ষতি।
  5. Control. প্রতিটি threat-এর সাথে একটি test জুড়ুন: “দুই tenant-এর দুই account দিয়ে automated test”. Presigned URL শুধু API-র অনুমতি যাচাইয়ের পরেই দিন, আর মেয়াদ রাখুন মিনিটে।
  6. Trade-off. এটিই সিনিয়র উত্তরের চিহ্ন। Presigned URL সাধারণত মেয়াদের আগে বাতিল করা যায় না, তাই গ্রাহকের দেখা স্থায়ী link হবে আমাদের API-তে, যা বাতিল করা যায়, আর সে প্রতিবার ছোট মেয়াদের URL বানাবে।

এবার নিজের উত্তরে নম্বর দিন। “ইন-হাউস চ্যাট সেবা” বা নিজের পছন্দের কোনো সেবার threat model ১৫ মিনিটে জোরে বলুন, তারপর নিচের নম্বর বদলে চালান। মাপটি আমাদের বানানো, কোনো মান নয়।

// Score your own design answer. Change the marks, then run again.
// 0 = missing, 1 = named only, 2 = named with a reason or a number.
const rubric = [
  ['Scope questions asked first',     10, 2],
  ['Assets named and ranked',         15, 1],
  ['DFD with trust boundaries',       15, 2],
  ['Top threats ranked, not listed',  20, 1],
  ['Control mapped to each threat',   20, 2],
  ['Trade-offs and residual risk',    10, 0],
  ['Detection and response',          10, 1],
];
let total = 0;
const gaps = [];
for (const [item, weight, mark] of rubric) {
  const got = weight * mark / 2;
  total += got;
  if (got < weight) gaps.push({ item, lost: weight - got });
}
gaps.sort((a, b) => b.lost - a.lost);
console.log('Score: ' + total + ' / 100');
console.log('Fix first:');
for (const g of gaps) console.log('  -' + String(g.lost).padStart(4) + '  ' + g.item);
const band = total >= 80 ? 'strong' : total >= 60 ? 'fair, practise the gaps' : 'redo the walk-through';
console.log('Band (our own toy scale): ' + band);
Score: 67.5 / 100
Fix first:
  -  10  Top threats ranked, not listed
  -  10  Trade-offs and residual risk
  - 7.5  Assets named and ranked
  -   5  Detection and response
Band (our own toy scale): fair, practise the gaps

নমুনা নম্বরে ৬৭.৫. লক্ষ করুন, কম নম্বরের কারণ জ্ঞানের অভাব নয়। Threat-গুলো বলা হয়েছে, কিন্তু ক্রম দেওয়া হয়নি (১০ হারিয়েছে), আর trade-off একেবারেই বলা হয়নি (১০ হারিয়েছে)। ইন্টারভিউতে এই দুটিই সবচেয়ে সস্তায় নম্বর বাড়ায়। ওজন বদলে দেখুন: cloud ভূমিকার জন্য detection-এর ওজন বাড়াতে পারেন।

আদর্শ উত্তর ২: payment flow

“তাজা বাজার” (পর্ব ৭৫-এর কাল্পনিক দোকান) কার্ড আর মোবাইল ওয়ালেটে টাকা নেয়, একটি gateway-র মাধ্যমে। ছবিতে সবচেয়ে ঝুঁকির জায়গা দুটি: দামের সংখ্যাটি কে ঠিক করছে, আর “টাকা এসেছে” বার্তাটি কে বিশ্বাস করছে।

Payment flow-এর চার ধাপ

Server sets the amount; a signed webhook confirms it

Payment flow: অর্ডার, gateway session, পেমেন্ট আর webhook ক্রেতা দোকানের API Gateway ১ · অর্ডার, দাম ছাড়া ২ · দাম server থেকে ৩ · টাকা দেওয়া, gateway-র পাতায় ৪ · স্বাক্ষরিত webhook
ছবি ৮০.২ — কার্ডের নম্বর দোকানের server-এ আসে না। “টাকা এসেছে” কথাটি browser-এর redirect থেকে নয়, স্বাক্ষর যাচাই করা webhook থেকে মানা হয়।
প্র ৫একটি online দোকানের payment flow-এর threat model বলুন। (কঠিন)

উত্তর: পরিধি: কার্ড না ওয়ালেট, দিনে কত লেনদেন, refund কে করেন? সম্পদ: টাকা, অর্ডারের অবস্থা, গ্রাহকের তথ্য, gateway-র key.

শীর্ষ threat ও control (L × I):

ThreatL × IControlTest
Client দাম বদলায়4×5 = 20দাম server-এ হিসাব, client-এর সংখ্যা উপেক্ষাভিন্ন দামের request-এ server-এর দামই থাকে
নকল “paid” বার্তা3×5 = 15Webhook-এর স্বাক্ষর, সময়ের সীমাভুল স্বাক্ষরে প্রত্যাখ্যান
দুইবার চার্জ বা দুইবার ডেলিভারি3×4 = 12Idempotency key, এক event এক বারএকই event দুইবার পাঠানো
কর্মীর ভুয়া refund2×5 = 10Separation of duties, audit logএকা অনুমোদন ব্যর্থ
কার্ডের ডেটা ফাঁস2×5 = 10Hosted page বা SDK, tokenizationLog-এ কার্ড নম্বর নেই

Trade-off: সন্দেহে fail secure: gateway উত্তর না দিলে অর্ডার “pending”, “paid” নয়। এতে কিছু ভালো গ্রাহক অপেক্ষা করেন, কিন্তু বিনামূল্যে পণ্য যায় না। Hosted page-এ নকশার স্বাধীনতা কমে, কিন্তু PCI DSS-এর পরিধি অনেক ছোট হতে পারে। শূন্য হয় না, ঠিক কোন ফর্ম লাগবে তা acquirer-এর সাথে নিশ্চিত করতে হয় (পর্ব ৬৯)।

Detection: প্রতিদিন gateway-র হিসাব আর নিজের খাতা মেলানো (reconciliation). অমিলই সবচেয়ে শক্ত alert, কারণ এটি যে ত্রুটিই হোক, ফল ধরে ফেলে।

ফলো-আপ: “Webhook হারিয়ে গেলে?” — Gateway আবার পাঠায় কি না দেখব, আর pending অর্ডারের জন্য নিজে থেকে gateway-র API-তে অবস্থা জিজ্ঞেস করব।

প্র ৬Support দলের জন্য একটি internal admin tool-এর threat model বলুন। (কঠিন)

উত্তর: প্রথম বাক্যেই বলব: “ভেতরের tool মানেই নিরাপদ” ধারণাটি ভুল। এই panel একবারে সব গ্রাহকের ডেটা দেখতে পারে, তাই এটিই সবচেয়ে দামি লক্ষ্য। সম্পদ: গ্রাহকের ডেটা, বদলানোর ক্ষমতা (refund, password reset), audit log.

শীর্ষ threat: (১) কর্মীর account দখল, phishing-এর মাধ্যমে: 4×5 = 20. (২) প্রয়োজনের চেয়ে বেশি দেখা, কৌতূহল বা অপব্যবহার: 3×4 = 12. (৩) বড় আকারে export: 3×5 = 15. (৪) ভেতরের panel-এ XSS বা CSRF, কারণ গ্রাহকের লেখা ticket panel-এ দেখা যায়: 3×5 = 15. (৫) Log মুছে ফেলা: 2×4 = 8.

Control: SSO আর phishing-প্রতিরোধী MFA, passkey হলে ভালো। VPN-এর ওপর ভরসা না করে প্রতি request-এ পরিচয় আর যন্ত্রের অবস্থা দেখা (পর্ব ৭৪)। ভূমিকাভিত্তিক অনুমতি, আর সম্ভব হলে ticket-এ বাঁধা অনুমতি: ticket নেই তো গ্রাহকের ডেটাও নেই। Export-এ দ্বিতীয় জনের অনুমোদন, আর সীমা। বড় ক্ষমতা just-in-time. Audit log এমন জায়গায়, যা admin মুছতে পারেন না।

Trade-off: ticket-বাঁধা অনুমতি সাড়ার গতি কমায়। জরুরি অবস্থার জন্য break-glass রাখুন, যা ব্যবহার হলেই alert যায় আর পরে review হয়।

ফলো-আপ: “কীভাবে ধরবেন?” — একজন কর্মী তাঁর স্বাভাবিকের চেয়ে অনেক বেশি গ্রাহকের রেকর্ড খুললে alert. বেসলাইন কর্মীপিছু, কারণ দলের গড় লুকিয়ে ফেলে।

প্র ৭STRIDE, DREAD আর likelihood × impact: কোনটি কখন? (মাঝারি)

উত্তর: STRIDE খোঁজার হাতিয়ার: কী ভুল হতে পারে তা ভুলে না যেতে সাহায্য করে। অন্য দুটি ক্রম ঠিক করার হাতিয়ার। DREAD-এ দুজন একই ঝুঁকিতে ভিন্ন স্কোর দেন, আর discoverability “লুকানো আছে” ভাবনাকে পুরস্কার দেয়। তাই আমি L × I নিই, আর বলি সংখ্যা আলোচনার শুরু, সিদ্ধান্ত নয়। প্রতিষ্ঠানে আগে থেকে লেখা bug bar থাকলে সেটি মতভেদ আরও কমায়।

প্র ৮সময় মাত্র ১৫ মিনিট। ৪০টি threat-এর তালিকা না বানিয়ে কী করবেন? (মাঝারি)

উত্তর: শুধু trust boundary পার হওয়ার জায়গায় তাকাব, আর জোরে বলব, “সময় কম, তাই আমি ওপরের তিনটি গভীরে দেখব।” প্রথম ২ মিনিট প্রশ্ন, ৩ মিনিট ছবি, ৭ মিনিট তিনটি threat আর control, ৩ মিনিট trade-off আর detection. কম কিন্তু গভীর উত্তর, দীর্ঘ তালিকার চেয়ে ভালো, কারণ তালিকা দেখায় মুখস্থ, আর ক্রম দেখায় বিচারবোধ।

প্র ৯ডিজাইন review-তে ডেভেলপার বললেন, “এটি ভেতরের service, auth লাগবে না।” কী বলবেন? (মাঝারি)

উত্তর: তর্ক নয়, প্রশ্ন করব: “একটি পাশের service দখল হলে এখান থেকে সে কী পড়তে বা বদলাতে পারে?” সমতল নেটওয়ার্কে একটি ভাঙা service থেকে পুরোটায় পৌঁছানো যায়, এটিই lateral movement (পর্ব ২২)। প্রস্তাব দেব সহজ পথের: platform-এর দেওয়া mTLS বা workload identity, যাতে দলের বাড়তি কোড না লাগে। ডেটা কম গুরুত্বের হলে ঝুঁকি লিখে রেখে পরে করা যায়, মালিক আর তারিখসহ।

৩ · Secure code review ড্রিল — ত্রুটি খুঁজুন, সমাধান লিখুন

রিভিশন: পর্ব ৪৬, পর্ব ৪৯, পর্ব ৩৭, পর্ব ৩৮, পর্ব ৩৯, পর্ব ৪০, পর্ব ৪২, পর্ব ৪৭, Code review

Code review-তে সব লাইন সমান মনোযোগে পড়লে সময় ফুরিয়ে যায়। ডাকঘরের চিঠির মতো ডেটার পথ ধরুন: কোথা থেকে এলো (source), কোথায় গেল (sink), আর মাঝখানে কে যাচাই করল। নিচের stepper-এ একটি ছোট handler একবার পড়ে দেখা যাক।

def download(request, file_id):      # file_id: <user-input>
    user = session_user(request)
    row = db.find_file(file_id)
    log.info("download %s", file_id)
    return stream(row.path)
পাঁচটি প্রশ্ন
প্রশ্ন
এই কোডে
অবস্থা
  1. Source. বাইরে থেকে কী আসে, তা আগে চিহ্নিত করুন। Path, query, header, cookie, ফাইলের নাম, এমনকি webhook-এর body-ও বাইরের ডেটা।
  2. পরিচয়। session_user বলে দিচ্ছে “কে”. এটি ঠিক আছে, তবে “কে” জানা মানে “অনুমতি আছে” জানা নয়।
  3. অনুমতি। user চলকটি নেওয়া হলো, কিন্তু আর ব্যবহারই হলো না। অব্যবহৃত পরিচয় একটি ভালো সংকেত: যাচাই ভুলে গেছে।
  4. Sink. stream ক্ষতির জায়গা। Source থেকে sink পর্যন্ত কোনো অনুমতি যাচাই নেই।
  5. Finding. শুধু “IDOR আছে” না বলে বলুন: কোথায়, প্রভাব কী, সমাধান কী, কোন test এটি ফিরতে দেবে না। সমাধান: row.tenant_id == user.tenant_id যাচাই, আর দুই account-এর একটি automated test.

এবার ১২টি ড্রিল। প্রতিটি কোড আগে পড়ুন, কাগজে ত্রুটির নাম, প্রভাব আর সমাধান লিখুন, তারপর উত্তর খুলুন। সবগুলো উদাহরণ, চালানোর জন্য নয়। এগুলো শুধু অনিরাপদ ধরন দেখায়।

ড্রিল D1 · খোঁজা

q = "SELECT * FROM orders WHERE id = '" + order_id + "'"   # order_id: <user-input>
cur.execute(q)
প্র ১০D1-এর ত্রুটি আর সমাধান কী? (সহজ)

উত্তর: SQL injection-এর ধরন (CWE-89, OWASP A05:2025). Input SQL-এর লেখার অংশ হয়ে যায়, তাই input query-র গঠন বদলাতে পারে। সমাধান parameterized query: cur.execute("SELECT id, status FROM orders WHERE id = ?", (order_id,)). সাথে SELECT * বাদ, আর মালিকানার শর্ত যোগ। ডেটাবেসের account-কেও ন্যূনতম অনুমতি দিন।

ফলো-আপ: “Table-এর নাম বা ORDER BY-র কলাম input থেকে এলে?” — Parameter সেখানে চলে না। Allowlist থেকে বেছে নিন।

ড্রিল D2 · মালিকানা

@app.get("/invoices/<invoice_id>")      # invoice_id: <user-input>
@login_required
def invoice(invoice_id):
    return db.invoices.get(invoice_id)
প্র ১১D2-তে login আছে, তবু ত্রুটি কোথায়? (সহজ)

উত্তর: IDOR (CWE-639, OWASP A01:2025, API-তে BOLA). পরিচয় আছে, মালিকানা যাচাই নেই। সমাধান: inv = db.invoices.get(invoice_id), তারপর if inv is None or inv.owner_id != current_user.id: abort(404). ৪০৪ দিলে অন্যের রেকর্ড আছে কি না, সেটিও জানা যায় না। আরও ভালো: query-তেই মালিকের শর্ত দেওয়া। অনুমান-কঠিন ID সহায়ক, কিন্তু যাচাইয়ের বিকল্প নয়।

ড্রিল D3 · মন্তব্য দেখানো

// comment: <user-input>, saved earlier by another user
box.innerHTML = "<p>" + comment + "</p>";
প্র ১২D3-এর ত্রুটি, সমাধান আর দ্বিতীয় স্তরের প্রতিরক্ষা কী? (সহজ)

উত্তর: Stored XSS-এর ধরন (CWE-79, OWASP A05:2025). ব্যবহারকারীর ডেটা HTML হিসেবে পড়া হচ্ছে। সমাধান: box.textContent = comment. HTML সত্যিই লাগলে একটি পরিচিত sanitizer ব্যবহার করুন। দ্বিতীয় স্তর CSP, আর session cookie-তে HttpOnly. এগুলো ক্ষতি কমায়, মূল কারণ সরায় না। মূল নীতি output encoding প্রসঙ্গ দেখে।

ড্রিল D4 · ফাইল খোলা

name = request.args["name"]          # name: <user-input>
return open("/srv/shares/" + name, "rb").read()
প্র ১৩D4-এর ঝুঁকি আর সবচেয়ে ভালো নকশা কী? (মাঝারি)

উত্তর: Path traversal-এর ধরন (CWE-22). নাম দিয়ে path বানালে নির্দিষ্ট ফোল্ডারের বাইরের ফাইলেও পৌঁছানো যেতে পারে। সবচেয়ে ভালো নকশা: ব্যবহারকারীর নাম path-এ ব্যবহারই না করা। Server নিজে random ID বানায়, মূল নাম থাকে metadata-য়। পুরোনো কোডে অন্তত:

base = Path("/srv/shares").resolve()
target = (base / name).resolve()
if not target.is_relative_to(base):
    abort(400)

সাথে অনুমতি যাচাই, আর সেবার process-কে শুধু ওই ফোল্ডারের অধিকার।

ড্রিল D5 · URL আনা

url = request.json["image_url"]      # image_url: <user-input>
data = requests.get(url, timeout=5).content
প্র ১৪D5-এ কী ঝুঁকি, আর কোন কোন স্তরে সমাধান করবেন? (কঠিন)

উত্তর: SSRF (CWE-918). Server ব্যবহারকারীর হয়ে যে ঠিকানায় বলা হয় সেখানে যায়, এমনকি ভেতরের সেবা বা cloud-এর metadata সেবাতেও। সমাধান স্তরে স্তরে:

  • কোড: scheme আর host-এর allowlist, redirect বন্ধ বা প্রতিটি redirect আবার যাচাই, সময় আর আকারের সীমা।
  • Network: আলাদা fetcher সেবা, যার বাইরের পথ egress proxy দিয়ে সীমিত, আর ভেতরের ঠিকানায় পৌঁছানো নিষেধ।
  • Cloud: metadata সেবায় token বাধ্য, আর ওই workload-এর role ন্যূনতম।

শুধু input-এর লেখা মেলানো দুর্বল, কারণ নামের ঠিকানা (DNS) পরে বদলাতে পারে। তাই সংযোগের সময়ের আসল IP-ও যাচাই করতে হয়। সবচেয়ে ভালো: URL না নিয়ে সরাসরি ফাইল upload নেওয়া।

ড্রিল D6 · ভেতরের API ডাকা

API_KEY = "example-token"
r = requests.get(url, headers={"X-Key": API_KEY}, verify=False)
প্র ১৫D6-এ দুটি সমস্যা। কোনটি আগে সারাবেন? (সহজ)

উত্তর: (১) কোডে secret (CWE-798): Git-এর ইতিহাসে চিরকাল থেকে যায়। আসল key হলে আগে বাতিল করে নতুন key, তারপর secret manager, আর secret scanning. (২) verify=False (CWE-295): TLS থাকলেও সার্ভারের পরিচয় যাচাই হয় না, তাই মাঝের কেউ নিজেকে সার্ভার বলে চালাতে পারে, আর key-টিও তার হাতে যায়। সমাধান: যাচাই চালু রাখা, private CA হলে verify="/etc/ssl/internal-ca.pem". কেউ “error সারাতে” verify=False দিলে আসল কারণ, সাধারণত chain বা নামের সমস্যা, ঠিক করুন।

ড্রিল D7 · Password আর ফাইল সুরক্ষা

digest = hashlib.md5(password.encode()).hexdigest()   # password: <user-input>
box = AES.new(key, AES.MODE_ECB).encrypt(pad(data))
প্র ১৬D7-এর দুই লাইনে কী ভুল, কী বসাবেন? (সহজ)

উত্তর: MD5 দ্রুত hash, salt নেই, আর ফাঁস হলে অনুমান সস্তা (CWE-916, OWASP A04:2025). বসান Argon2id, পরিচিত library দিয়ে, OWASP-এর ন্যূনতম m=19 MiB, t=2, p=1 থেকে শুরু করে নিজের server-এ মেপে। ECB একই block-কে একই ciphertext দেয়, তাই ডেটার ধরন ফুটে ওঠে, আর অখণ্ডতাও নেই। বসান AES-GCM-এর মতো AEAD, প্রতি বার্তায় নতুন nonce. দুই ক্ষেত্রেই নিজে না বানিয়ে উঁচু-স্তরের library নিন।

ড্রিল D8 · স্বাক্ষর মেলানো

want = hmac.new(key, body, hashlib.sha256).hexdigest()
if request.headers["X-Sig"] == want:     # X-Sig: <user-input>
    mark_paid(body)
প্র ১৭D8-এ ভুল কোথায়? HMAC তো আছে। (মাঝারি)

উত্তর: সাধারণ == প্রথম অমিলে থামতে পারে, তাই সময়ের পার্থক্য থেকে তথ্য বেরোতে পারে (CWE-208, timing side channel). সমাধান constant-time তুলনা: hmac.compare_digest(got, want). সাথে আরও দুটি ফাঁক: সময় বা event ID নেই, তাই পুরোনো বার্তা আবার পাঠানো যায়, আর mark_paid একই event দুইবার চালাতে পারে। পুরো সমাধান অংশ ৫-এর চলার যোগ্য ব্লকে আছে।

ড্রিল D9 · Profile হালনাগাদ

user.update(**request.json)          # JSON body: <user-input>
db.save(user)
প্র ১৮D9-এর ত্রুটি কী? (মাঝারি)

উত্তর: Mass assignment (CWE-915, API Top 10-এর API3). Client যে field পাঠায়, সবই বসে যায়, এমনকি role বা balance-এর মতো যা তার বদলানোর কথা নয়। সমাধান: অনুমোদিত field-এর তালিকা। আলাদা input schema, যেমন শুধু name আর phone, আর অজানা field প্রত্যাখ্যান। Role বা balance কখনো client-এর লেখা থেকে নয়।

ড্রিল D10 · ছবি রূপান্তর

os.system("convert " + filename + " out.png")   # filename: <user-input>
প্র ১৯D10-কে কীভাবে নিরাপদ করবেন? (মাঝারি)

উত্তর: Command injection-এর ধরন (CWE-78). Shell পুরো লেখাটিকে আদেশ হিসেবে পড়ে, আর input তার অংশ। সমাধান ক্রমে: (১) সম্ভব হলে library দিয়ে করুন, কোনো process নয়। (২) না হলে shell ছাড়া তালিকা-রূপে: subprocess.run(["convert", safe_path, "out.png"], check=True), যেখানে safe_path server-এর বানানো, ব্যবহারকারীর নয়। (৩) এই কাজ আলাদা sandbox-এ, কম অনুমতিতে, সময়ের সীমাসহ।

ড্রিল D11 · ওয়ালেট থেকে টাকা কাটা

bal = get_balance(user_id)
if bal >= amount:                    # amount: <user-input>
    set_balance(user_id, bal - amount)
প্র ২০D11-এ দেখতে সব ঠিক। সমস্যা কী? (কঠিন)

উত্তর: Race condition (CWE-362, ধরন TOCTOU). যাচাই আর কাটার মাঝে ফাঁক। একই সময়ের দুটি request দুটিই পুরোনো balance দেখে পাস করে। আরেকটি ফাঁক: amount ঋণাত্মক হলে যাচাই পাস করে balance বেড়ে যায়। সমাধান: ধনাত্মক সংখ্যা যাচাই, আর একটি atomic SQL:

UPDATE wallet SET bal = bal - ?
WHERE user_id = ? AND bal >= ?

Affected row ১ না হলে “অপর্যাপ্ত”. সাথে idempotency key, আর প্রতিটি লেনদেনের অপরিবর্তনীয় ledger. টাকার হিসাবে দশমিক ভগ্নাংশের float নয়, পূর্ণসংখ্যায় পয়সা রাখুন।

ড্রিল D12 · C-তে নাম কপি

char name[32];
strcpy(name, user_input);   /* user_input: <user-input> */
প্র ২১D12-এর ত্রুটি কী, আর আধুনিক উত্তর কী? (মাঝারি)

উত্তর: Buffer overflow (CWE-120). strcpy দৈর্ঘ্য দেখে না, তাই ৩২ byte-এর বাইরের memory নষ্ট হতে পারে। সমাধান: আগে দৈর্ঘ্য যাচাই, তারপর snprintf(name, sizeof name, "%s", user_input), আর ফেরত মান দেখে কেটে যাওয়া ধরা। পরের স্তরে compiler ও OS-এর mitigation, sanitizer আর fuzzing. নতুন কোডে memory-safe ভাষা বিবেচনা করা (পর্ব ৪৭)।

এবার সমাধান নিজে লিখুন। নিচের ব্লকে mine লাইনে আপনার কোড বসান। D2 আর D6 ইচ্ছা করে ভুল রাখা আছে: আগে সেগুলো ঠিক করুন, তারপর আবার চালান।

// Review drill: write your fix in `mine`, then run again.
// This matches text patterns only. Passing is not proof of safety.
const drills = [
  { id: 'D1 SQL', need: /execute\(.*[?].*,/, ban: /\+|f"/,
    mine: 'cur.execute("SELECT id FROM orders WHERE id = ?", (order_id,))' },
  { id: 'D2 owner check', need: /owner\w*\s*(!=|==)/, ban: /^$/,
    mine: 'doc = db.get(doc_id)\nreturn doc' },
  { id: 'D3 DOM', need: /textContent/, ban: /innerHTML/,
    mine: 'box.textContent = comment' },
  { id: 'D5 SSRF', need: /ALLOWED_HOSTS/, ban: /verify\s*=\s*False/,
    mine: 'if host in ALLOWED_HOSTS: fetch(url, allow_redirects=False)' },
  { id: 'D6 TLS', need: /verify\s*=\s*True|verify=CA_FILE/, ban: /verify\s*=\s*False/,
    mine: 'requests.get(url, verify=False)' },
  { id: 'D8 compare', need: /compare_digest/, ban: /==/,
    mine: 'hmac.compare_digest(got_tag, want_tag)' },
];
let pass = 0;
for (const d of drills) {
  const ok = d.need.test(d.mine) && !d.ban.test(d.mine);
  if (ok) pass++;
  const why = ok ? '' : d.ban.test(d.mine) ? '  (unsafe pattern still here)'
                                           : '  (the safe pattern is missing)';
  console.log((ok ? 'PASS ' : 'FAIL ') + d.id + why);
}
console.log(pass + ' of ' + drills.length + ' drills pass the pattern check');
PASS D1 SQL
FAIL D2 owner check  (the safe pattern is missing)
PASS D3 DOM
PASS D5 SSRF
FAIL D6 TLS  (unsafe pattern still here)
PASS D8 compare
4 of 6 drills pass the pattern check

D2-তে মালিকের শর্তই নেই, আর D6-এ verify=False রয়ে গেছে। এই checker শুধু লেখার ধরন মেলায়, ঠিক যেমন SAST টুল মেলায়, তাই “PASS” মানে নিরাপদ নয়। একটি সরল regex owner != দেখলে খুশি, শর্তটি উল্টো হলেও। তাই SAST-এর পরেও মানুষের review আর test লাগে (পর্ব ৪৯)।

এখন parameterized query-র মূল কারণটি নিজের চোখে দেখুন। Python-এর in-memory sqlite3 দিয়ে, যা ব্লক শেষে মুছে যায়। Concatenated লেখাটি শুধু তুলনার জন্য বানানো, চালানো হয় না।

# In-memory toy database. The value "<user-input>" is only a placeholder.
import sqlite3

db = sqlite3.connect(":memory:")
db.execute("CREATE TABLE orders (id TEXT, owner TEXT)")
db.executemany("INSERT INTO orders VALUES (?, ?)",
               [("A-1", "mina"), ("A-2", "rafi")])

values = ["A-1", "A-2", "<user-input>"]
concat_texts = set()   # built only to compare the text; never executed
param_texts = set()

for value in values:
    concat_texts.add("SELECT id FROM orders WHERE id = '" + value + "'")
    sql = "SELECT id FROM orders WHERE id = ? AND owner = ?"
    param_texts.add(sql)
    rows = db.execute(sql, (value, "mina")).fetchall()
    print(f"{value:14} rows for mina: {rows}")

print("distinct statement texts, concatenated:", len(concat_texts))
print("distinct statement texts, parameterized:", len(param_texts))
db.close()
A-1            rows for mina: [('A-1',)]
A-2            rows for mina: []
<user-input>   rows for mina: []
distinct statement texts, concatenated: 3
distinct statement texts, parameterized: 1

তিনটি মানে concatenation তিনটি আলাদা SQL লেখা বানিয়েছে: ডেটা আদেশের লেখায় মিশে গেছে। Parameter-এর ক্ষেত্রে SQL লেখা একটিই, আর মান আলাদা পথে যায়। তাই <user-input> শুধু একটি মান হিসেবে মেলানো হলো, পাওয়া গেল না। A-2 মিনার নয়, তাই ফাঁকা ফল: মালিকের শর্ত D2-এর সমস্যাও একই সাথে থামাল।

প্র ২২Code review-তে finding কীভাবে লিখবেন, যাতে ডেভেলপার রাগ না করে কাজটি করেন? (মাঝারি)

উত্তর: মানুষ নয়, কোড নিয়ে কথা বলব। পাঁচটি অংশ: কোথায়, কী ঘটতে পারে, গুরুত্ব কেন, নির্দিষ্ট সমাধান, আর পরীক্ষার test. যেমন: “invoice()-তে মালিকের যাচাই নেই। লগইন করা যে কেউ অন্যের invoice পড়তে পারেন। গ্রাহকের ডেটা, তাই merge-এর আগে দরকার। এই দুই লাইন বসালে হয়, আর এই test-টি যোগ করুন।” যা ছোট, তা “nit” বলে আলাদা করুন, যাতে আসল বিষয় হারিয়ে না যায়।

ফলো-আপ: “Review-র সময়ে কী বেশি মূল্যবান, লাইন পড়া না নকশা?” — আগে auth, টাকা, ডেটা-ভাগের অংশ। ASVS 5.0.0-র মতো মান থেকে চেকলিস্ট বানানো যায়।

৪ · Authentication আর session নকশা

রিভিশন: পর্ব ১৩, পর্ব ১৫, পর্ব ১৬, পর্ব ১৭, পর্ব ১৮, পর্ব ১৯, পর্ব ৪১

প্র ২৩একটি নতুন সেবার login নকশা করুন। (মাঝারি)

উত্তর: আগে সম্ভব হলে নিজে password রাখবই না: SSO বা passkey. Password রাখলে: NIST SP 800-63B-4 ধরে একক factor হলে অন্তত ১৫ অক্ষর, MFA-র অংশ হলে অন্তত ৮, লম্বা password-এর অনুমতি, ফাঁস হওয়া তালিকায় মেলানো, আর চিহ্নের জোরাজুরি বা নিয়মিত বদল নয়। Argon2id-তে রাখা। Login-এ IP আর account দুই দিকেই rate limit, আর সবার জন্য একই error বার্তা। Login সফল হলে নতুন session ID, যাতে session fixation না চলে। Log-এ সফল আর ব্যর্থ login, কিন্তু password কখনো নয়।

ফলো-আপ: “Lockout দেবেন?” — কড়া lockout নিজেই অন্যকে আটকে দেওয়ার উপায় হয়। তাই ধাপে ধাপে ধীর করা ভালো।

প্র ২৪TOTP, SMS আর passkey: phishing-এর সামনে কে কোথায় দাঁড়ায়? (মাঝারি)

উত্তর: TOTP-র কোড মানুষ নিজে টাইপ করেন, তাই নকল পাতায় দিয়ে ফেলতে পারেন। SMS-এ বাড়তি ঝুঁকি SIM বদল, আর বার্তা আটকানো। Passkey (WebAuthn) key-কে আসল origin-এর সাথে বাঁধে, তাই নকল domain-এ সে স্বাক্ষরই করে না। তাই এটি phishing-প্রতিরোধী। এটিই admin আর উচ্চ-ঝুঁকির কাজে প্রথম পছন্দ। তবে account recovery যদি দুর্বল থাকে, পুরো লাভ সেখান দিয়ে হারায়।

ফলো-আপ: “MFA fatigue ঠেকাবেন কীভাবে?” — Number matching, সীমা, আর সন্দেহজনক অনুরোধের রিপোর্ট বোতাম।

প্র ২৫Session token কোথায় রাখবেন: cookie না localStorage? (মাঝারি)

উত্তর: Browser app-এ সাধারণত cookie: __Host- নাম, Secure, HttpOnly, SameSite, Path=/. কারণ localStorage XSS-এ সরাসরি পড়া যায়। HttpOnly শুধু token চুরি কঠিন করে: XSS থাকলে ওই পাতা থেকে কাজ চালানো যায়, তাই XSS সারানো তবুও দরকার। Cookie নিজে থেকে যায় বলে CSRF-এর ভাবনা আসে: SameSite-এর সাথে পরিবর্তনের অনুরোধে CSRF token বা উৎস যাচাই।

প্র ২৬Server-side session না JWT? “JWT stateless, তাই ভালো” কথাটি ঠিক? (মাঝারি)

উত্তর: একটি web app-এ server-side session প্রায়ই সহজ আর নিরাপদ: খাতার সারি মুছলেই বাতিল। JWT অনেক service-এ ছড়ানো যাচাইয়ে কাজে আসে, কারণ প্রতি বার ডেটাবেস লাগে না। দাম: মেয়াদের আগে ফেরত নেওয়া কঠিন। তাই access token ছোট মেয়াদের, আর refresh token rotation, যেখানে পুরোনো refresh token ফিরলে পুরো পরিবার বাতিল। সত্যি logout বা জরুরি বাতিল লাগলে কিছু state ফিরে আসেই। JWT স্বাক্ষর করা, গোপন নয়: body পড়া যায়।

JWT যাচাইয়ের ক্রমটি হাতে-কলমে দেখুন। RFC 8725-এর মূল কথা: algorithm আপনি ঠিক করবেন, token নয়।

// Toy JWT check on decoded claims. The signature result is given as a
// boolean here, so no crypto runs. The clock is simulated.
const NOW = 1000;
const POLICY = { algs: ['RS256'], iss: 'https://id.example.com', aud: 'orders-api', skew: 30 };

function verify(t) {
  if (!POLICY.algs.includes(t.alg)) return 'reject: algorithm not on our list';
  if (!t.sigOk) return 'reject: bad signature';
  if (t.iss !== POLICY.iss) return 'reject: wrong issuer';
  if (t.aud !== POLICY.aud) return 'reject: token meant for another service';
  if (NOW > t.exp + POLICY.skew) return 'reject: expired';
  if (t.nbf > NOW + POLICY.skew) return 'reject: not valid yet';
  return 'accept';
}
const base = { alg: 'RS256', sigOk: true, iss: POLICY.iss, aud: 'orders-api', nbf: 900, exp: 1200 };
const cases = {
  'good token     ': base,
  'other algorithm': { ...base, alg: 'HS256' },
  'body changed   ': { ...base, sigOk: false },
  'other issuer   ': { ...base, iss: 'https://id.example.org' },
  'other audience ': { ...base, aud: 'admin-api' },
  'expired by 100 ': { ...base, exp: 900 },
  'expired by 20  ': { ...base, exp: 980 },
};
for (const [name, t] of Object.entries(cases)) console.log(name + ' -> ' + verify(t));
good token      -> accept
other algorithm -> reject: algorithm not on our list
body changed    -> reject: bad signature
other issuer    -> reject: wrong issuer
other audience  -> reject: token meant for another service
expired by 100  -> reject: expired
expired by 20   -> accept

সাতটির মধ্যে দুটি গ্রহণ। ভালো token গ্রহণ হলো। “expired by 20” গ্রহণ হলো, কারণ ঘড়ির ৩০ সেকেন্ড ছাড় (skew) আছে: মেয়াদ ৯৮০, ঘড়ি ১০০০, ২০ সেকেন্ড পেরিয়েছে, ছাড়ের ভেতরে। “expired by 100” ছাড়ের বাইরে। “other audience”-এর শিক্ষা বড়: একটি service-এর জন্য বানানো ঠিকঠাক স্বাক্ষরের token অন্য service-এ চলা উচিত নয়। স্বাক্ষর এখানে শুধু একটি boolean, আসল কাজে library যাচাই করবে।

প্র ২৭নিরাপদ password reset নকশা করুন। (মাঝারি)

উত্তর: সবচেয়ে দুর্বল দরজাই আসল শক্তি, তাই reset login-এর সমান গুরুত্বের। অনুরোধে সবসময় একই উত্তর, যাতে account আছে কি না বোঝা না যায়। CSPRNG থেকে লম্বা, এক-বার ব্যবহারের, ছোট মেয়াদের token, যার শুধু hash ডেটাবেসে থাকে। Reset-এর পর অন্য সব session বাতিল, আর ব্যবহারকারীকে নোটিশ। Rate limit, আর link-এর host নিজের config থেকে, request-এর header থেকে নয়। MFA থাকলে reset যেন MFA এড়িয়ে না যায়।

প্র ২৮OAuth-এ authorization code flow-তে PKCE আর state কী থামায়? ID token আর access token-এর পার্থক্য কী? (কঠিন)

উত্তর: PKCE code-কে সেই client-এর সাথে বাঁধে, যে flow শুরু করেছে, তাই মাঝপথে code হাতে পেলেও সে একা কাজে লাগে না। RFC 9700 (২০২৫) public client-এ এটি বাধ্য করে। state callback-কে শুরু করা session-এর সাথে বাঁধে, CSRF ঠেকাতে। Redirect URI হুবহু মেলাতে হবে। ID token client-কে বলে “কে login করল”, আর তার aud client নিজে। Access token API-র জন্য। Access token দিয়ে পরিচয় ধরে নেওয়া একটি পরিচিত ভুল (পর্ব ১৮)।

প্র ২৯Multi-tenant SaaS-এ authorization কোথায় রাখবেন? RBAC, ABAC না সম্পর্কভিত্তিক? (কঠিন)

উত্তর: শুরু RBAC দিয়ে, কারণ সহজ আর audit করা যায়। “নিজের দপ্তরের, কাজের সময়ের” মতো শর্ত লাগলে ABAC. নথি-ভাগের সেবার মতো “এই ফাইল এই মানুষের সাথে ভাগ” ধরনের কাজে সম্পর্কভিত্তিক মডেল। মূল নীতি একই: যাচাই server-এ, প্রতিটি request-এ, deny by default, এক জায়গার policy থেকে। tenant_id আসবে session থেকে, কখনো request-এর লেখা থেকে নয়। ডেটাবেসের row-level security দ্বিতীয় দেয়াল হতে পারে।

ফলো-আপ: “কীভাবে test করবেন?” — দুই tenant, দুই ভূমিকা, আর প্রতিটি endpoint-এ অনুমতি-না-থাকার automated test. এই নেতিবাচক test-ই পর্ব ৩৮-এর ত্রুটি আটকায়।

৫ · Cryptography — পছন্দ আর সাধারণ ভুল

রিভিশন: পর্ব ০৭, পর্ব ০৮, পর্ব ০৯, পর্ব ১০, পর্ব ১১, পর্ব ১২, পর্ব ১৪

ইন্টারভিউতে সাধারণত গণিত নয়, পছন্দ দেখা হয়: কোন কাজে কোন যন্ত্র, আর কোথায় ভুল হয়। তালা, সিলমোহর আর রেজিস্টার খাতার পার্থক্য বুঝলে অর্ধেক কাজ শেষ।

প্রয়োজনভালো পছন্দসাধারণ ভুল
ডেটা গোপন ও অক্ষতAES-GCM, ChaCha20-Poly1305ECB, tag ছাড়া CBC, nonce ফেরানো
Password রাখাArgon2id, না থাকলে scrypt বা bcryptSHA-256, MD5, salt ছাড়া hash, encryption
ফাইলের অখণ্ডতাSHA-256 (hash একই জায়গা থেকে না এলে স্বাক্ষরও)Hash-কেই পরিচয়ের প্রমাণ ভাবা
দুই পক্ষে বার্তার প্রমাণHMAC-SHA-256== দিয়ে তুলনা, hash(key + msg)
কে লিখল তার প্রমাণEd25519, ECDSA, RSA-2048 বা বড়ছোট key, ফেরানো nonce (ECDSA)
Key বিনিময়X25519, নতুন সিস্টেমে hybrid ML-KEMস্থির RSA key exchange, যাতে forward secrecy থাকে না
পথে ডেটাTLS 1.3, অন্তত 1.2, certificate যাচাইverify=False, পুরোনো version
Random মানOS-এর CSPRNG (secrets)random, সময় দিয়ে seed
প্র ৩০Encoding, hashing, MAC, encryption আর signature: এক বাক্যে পার্থক্য বলুন। (সহজ)

উত্তর: Encoding শুধু রূপ বদলায়, কোনো গোপনীয়তা নেই। Hash একমুখী ছাপ, key নেই। MAC একটি ভাগ করা key দিয়ে অখণ্ডতা আর উৎস দেখায়। Encryption key ছাড়া পড়া আটকায়। Signature private key দিয়ে সই, যে কেউ public key দিয়ে যাচাই করেন, তাই পরে অস্বীকার করা কঠিন। base64 encryption নয়, Kubernetes Secret-এর ক্ষেত্রে এই ভুলটিই বারবার হয়।

প্র ৩১AES-GCM-এ একই key-তে nonce ফিরলে কী হয়? কীভাবে এড়াবেন? (কঠিন)

উত্তর: গোপনীয়তা আর অখণ্ডতা দুটোই ক্ষতিগ্রস্ত হয়। একই keystream ফেরে, তাই দুই বার্তার XOR ফাঁস হয়, আর tag-এর গোপন মান H-ও বিপদে পড়ে, ফলে নকল tag সম্ভব হতে পারে। এড়ানোর উপায়: counter, যা কখনো ফেরে না, অথবা ৯৬ bit random nonce, তবে একটি key-তে বার্তার সংখ্যা সীমিত রাখা: NIST SP 800-38D random nonce-এ প্রায় 232 বার সীমা দেয়। আরেক পথ: key ঘন ঘন বদলানো, অথবা AES-GCM-SIV-এর মতো nonce ভুলে কম ভঙ্গুর mode (RFC 8452).

ফলো-আপ: “VM clone বা snapshot থেকে ফেরার সময়ে counter?” — ফিরে যেতে পারে। তাই counter-এর অবস্থা নিরাপদ জায়গায়, অথবা প্রতি চালুতে নতুন key.

প্র ৩২Database-এর সংবেদনশীল কলাম encrypt করবেন। Key কোথায় থাকবে? (কঠিন)

উত্তর: Envelope encryption: প্রতিটি ডেটা বা tenant-এর জন্য ডেটা key (DEK), আর সেটিকে মুড়িয়ে রাখে KMS বা HSM-এ থাকা KEK. ডেটাবেসে শুধু মোড়ানো DEK থাকে। সুবিধা: KEK বদলাতে সব ডেটা আবার encrypt করা লাগে না, শুধু DEK আবার মোড়ালেই হয়। KMS-এর প্রতিটি ব্যবহার audit log-এ যায়। Tenant ধরে key হলে একটি key মুছে সেই ডেটা অকেজো করা যায়।

ফলো-আপ: “এটি কী থেকে রক্ষা করে না?” — App নিজে দখল হলে সে key ব্যবহার করতে পারে। Encryption অনুমতির বিকল্প নয়। Encrypted কলামে search-ও জটিল হয়।

প্র ৩৩Post-quantum নিয়ে আপনার প্রতিষ্ঠান এখন কী করবে? (কঠিন)

উত্তর: আতঙ্ক নয়, পরিকল্পনা। এখনই সব বদলানোর দরকার নেই, কিন্তু “এখন জমাও, পরে খোলো” ঝুঁকি দীর্ঘমেয়াদি গোপন ডেটার জন্য বাস্তব। ধাপ: (১) কোথায় কোন crypto চলে তার তালিকা। (২) Crypto agility: সব crypto কল এক wrapper বা config-এ। (৩) সহজ জায়গায় hybrid TLS দিয়ে শুরু। (৪) Vendor-এর পরিকল্পনা জানা। মান: FIPS 203 (ML-KEM), 204 (ML-DSA), 205 (SLH-DSA), ২০২৪. বিস্তারিত পর্ব ১৪-এ।

এবার নিচের তালিকা নিজে দেখে আগে বলুন, কোন কোনটি বদলাবেন। তারপর চালান।

// Review crypto choices written as plain data. Toy rules, not a standard.
const items = [
  { use: 'password store', algo: 'MD5' },
  { use: 'password store', algo: 'Argon2id', mMiB: 19, t: 2, p: 1 },
  { use: 'file encryption', algo: 'AES-128-ECB' },
  { use: 'file encryption', algo: 'AES-256-GCM', nonces: ['n1', 'n2', 'n1'] },
  { use: 'file encryption', algo: 'AES-256-GCM', nonces: ['n1', 'n2', 'n3'] },
  { use: 'signature', algo: 'RSA', bits: 1024 },
  { use: 'signature', algo: 'Ed25519' },
  { use: 'transport', algo: 'TLS', version: 1.0 },
  { use: 'transport', algo: 'TLS', version: 1.3 },
];
function review(c) {
  if (c.use === 'password store') {
    if (c.algo !== 'Argon2id') return 'FIX fast hash, use a password hash';
    return c.mMiB >= 19 && c.t >= 2 ? 'ok, then tune cost on your server' : 'FIX cost too low';
  }
  if (/ECB/.test(c.algo)) return 'FIX ECB shows patterns, use an AEAD mode';
  if (c.nonces && new Set(c.nonces).size < c.nonces.length) return 'FIX nonce reused under one key';
  if (c.algo === 'RSA' && c.bits < 2048) return 'FIX key too short';
  if (c.algo === 'TLS' && c.version < 1.2) return 'FIX old TLS version';
  return 'ok';
}
let fixes = 0;
for (const c of items) {
  const verdict = review(c);
  if (verdict.startsWith('FIX')) fixes++;
  console.log((c.use + ' / ' + c.algo).padEnd(30) + verdict);
}
console.log(fixes + ' of ' + items.length + ' need a fix');
password store / MD5          FIX fast hash, use a password hash
password store / Argon2id     ok, then tune cost on your server
file encryption / AES-128-ECB FIX ECB shows patterns, use an AEAD mode
file encryption / AES-256-GCM FIX nonce reused under one key
file encryption / AES-256-GCM ok
signature / RSA               FIX key too short
signature / Ed25519           ok
transport / TLS               FIX old TLS version
transport / TLS               ok
5 of 9 need a fix

নয়টির মধ্যে পাঁচটি বদলাতে হবে। লক্ষ করুন, একই AES-256-GCM একবার ভুল, একবার ঠিক: ['n1', 'n2', 'n1']-তে n1 ফিরেছে। Algorithm-এর নাম ঠিক থাকলেই ব্যবহার ঠিক হয় না। শেষ পদের “ok”-ও পূর্ণ রায় নয়। Key কোথায় থাকে, তা এই টেবিল দেখছে না।

এখন D8-এর পুরো সমাধান, Python-এর আসল hmac দিয়ে। Payment webhook-এ তিনটি দেয়াল: স্বাক্ষর, সময়ের সীমা, আর এক event এক বার।

# Payment webhook check with real HMAC-SHA256. Secret and events are fake.
import hashlib
import hmac

SECRET = b"example-token"
NOW = 1_800_000_000       # fixed clock, so the output never changes
TOLERANCE = 300           # seconds
seen = set()              # event ids already processed

def tag(ts, body):
    return hmac.new(SECRET, f"{ts}.{body}".encode(), hashlib.sha256).hexdigest()

def receive(event_id, ts, body, got):
    if not hmac.compare_digest(tag(ts, body), got):
        return "reject: tag mismatch"
    if abs(NOW - ts) > TOLERANCE:
        return "reject: outside time window"
    if event_id in seen:
        return "ignore: already processed"
    seen.add(event_id)
    return "accept: mark order paid"

body = '{"order":"A-1","amount":1500}'
good = tag(NOW - 10, body)
print("tag starts:", good[:16])
print("fresh event   ->", receive("ev-1", NOW - 10, body, good))
print("same again    ->", receive("ev-1", NOW - 10, body, good))
print("amount edited ->", receive("ev-2", NOW - 10, body.replace("1500", "15"), good))
old = tag(NOW - 900, body)
print("old event     ->", receive("ev-3", NOW - 900, body, old))
tag starts: 97b06eec2274cfc9
fresh event   -> accept: mark order paid
same again    -> ignore: already processed
amount edited -> reject: tag mismatch
old event     -> reject: outside time window

দ্বিতীয় লাইনে একই event ফিরে এলেও অর্ডার দুইবার paid হয়নি: এটিই idempotency. তৃতীয় লাইনে দাম ১৫০০ থেকে ১৫ হলো, পুরোনো tag আর মিলল না। চতুর্থ লাইনের tag ঠিক ছিল, কিন্তু সময় ৯০০ সেকেন্ড পুরোনো, সীমা ৩০০. Timestamp-টিও স্বাক্ষরের ভেতরে, তাই বদলানো যায় না। ক্রম লক্ষ করুন: স্বাক্ষর যাচাইয়ের আগে body-কে বিশ্বাস করা হয়নি।

৬ · Cloud, Kubernetes, supply chain আর CI/CD গেট

রিভিশন: পর্ব ৭২, পর্ব ৭৩, পর্ব ৭৪, পর্ব ৪৮, পর্ব ৪৫, IAM policy, Kubernetes নিরাপত্তা, DevSecOps

Cloud-এর পরিস্থিতি

প্র ৩৪একটি cloud access key public repository-তে চলে গেছে। প্রথম ৩০ মিনিটে কী করবেন? (মাঝারি)

উত্তর: Key ফাঁস মানে key মৃত, commit মুছলেও। ক্রম: (১) Key বন্ধ করা, আর সেবা যেন না ভাঙে তাই নতুন পরিচয় প্রস্তুত করা। (২) সেই পরিচয়ের চলমান session-ও বাতিল, কারণ শুধু key বন্ধ করলে সাময়িক credential চলতে পারে। (৩) Audit log-এ দেখা: কখন থেকে, কোন IP, কী পড়ল, কী বানাল। নতুন user, key বা role আছে কি না। (৪) প্রভাব বুঝে incident ঘোষণা, আর ব্যক্তিগত ডেটা গেলে আইনি ধাপ। (৫) শেষে মূল কারণ: long-lived key-র বদলে workload identity, আর push-এর আগে secret scanning.

ফলো-আপ: “Git history থেকে মুছলেই হবে?” — না। অন্যরা আগেই পেয়ে থাকতে পারেন, তাই বাতিল করাই মূল কাজ।

প্র ৩৫একটি storage bucket ভুলে public ছিল। কী করবেন, আর কীভাবে আবার ঘটা ঠেকাবেন? (মাঝারি)

উত্তর: প্রথমে বন্ধ করব, তবে সেটিং আগে নথিতে রাখব। Access log থেকে দেখব কেউ পড়েছে কি না। Log চালু না থাকলে সত্যি বলব: “প্রমাণ নেই” মানে “ঘটেনি” নয়। ডেটার ধরন দেখে আইনি আর গ্রাহক-যোগাযোগের সিদ্ধান্ত (পর্ব ৭০)। প্রতিরোধ: account বা organization-স্তরে public বন্ধ, IaC-তে policy check, CSPM-এর alert, আর প্রতিটি resource-এর মালিক। ব্যতিক্রম লাগলে লিখিত।

প্র ৩৬Shared responsibility কী? Serverless-এ গেলে নিরাপত্তার কাজ কি ফুরায়? (সহজ)

উত্তর: Provider তার অংশ সামলায়, আপনি আপনারটি। IaaS থেকে SaaS-এ গেলে OS বা patch-এর কাজ কমে, কিন্তু পরিচয়, ডেটা আর সেটিং সব মডেলেই আপনার হাতে থাকে। Serverless-এ server patch নেই, তবু function-এর role, secret, dependency আর input আপনার। ভাগ provider আর সেবাভেদে আলাদা, তাই নির্দিষ্ট সেবার দলিল পড়ুন।

প্র ৩৭একটি web app-এ SSRF পাওয়া গেল, app-টি cloud VM-এ। ঝুঁকি কত দূর যেতে পারে? (কঠিন)

উত্তর: SSRF একা হয়তো মাঝারি, কিন্তু পথ দেখতে হয়। VM-এর metadata সেবা থেকে সাময়িক credential পাওয়া গেলে, আর role বড় হলে, ঝুঁকি হয়ে যায় ডেটা ফাঁস। প্রকাশিত নথি অনুযায়ী Capital One ২০১৯-এর ঘটনায় ঠিক এমন কয়েকটি দুর্বলতা জুড়ে গিয়েছিল: ভুল সাজানো WAF, SSRF-ধরনের সমস্যা, metadata credential আর বড় role (পর্ব ৬৫)। প্রতিরক্ষা প্রতিটি কড়িতে: SSRF সারানো, metadata-তে token বাধ্য, role ছোট করা, আর অস্বাভাবিক API ব্যবহারে alert. একটি কড়ি ভাঙলেই পথ বন্ধ, তাই সবচেয়ে সস্তা কড়িটি আগে।

Kubernetes-এর পরিস্থিতি

প্র ৩৮একটি Pod-কে শক্ত করবেন। কী কী দেখবেন? (মাঝারি)

উত্তর: Pod Security Standards-এর restricted-কে লক্ষ্য ধরি: non-root, allowPrivilegeEscalation: false, সব capability বাদ, seccomp RuntimeDefault. সাথে read-only root filesystem, hostPath আর Docker socket নয়, CPU ও memory limit. Image digest দিয়ে বাঁধা আর স্বাক্ষর যাচাই। দরকার না হলে automountServiceAccountToken: false. চারপাশে default-deny NetworkPolicy, যদিও এটি কাজ করে শুধু তখন, যখন network plugin সমর্থন করে।

প্র ৩৯Kubernetes Secret কি নিরাপদ? (মাঝারি)

উত্তর: নাম শুনে যতটা মনে হয়, ততটা নয়। মান শুধু base64-এ থাকে। Secret পড়ার অনুমতি যাঁর আছে, তিনি পড়তে পারেন, আর সেই namespace-এ Pod বানাতে পারলে সেটি mount করেও পড়া যায়। তাই etcd encryption চালু করা, যা অনেক cluster-এ নিজে করতে হয়, RBAC-এ get secrets ছোট রাখা, আর সম্ভব হলে বাইরের secret manager, ছোট মেয়াদের মান সহ।

প্র ৪০Production-এর একটি Pod-এ সন্দেহজনক process-এর alert এলো। কী করবেন? (কঠিন)

উত্তর: সাথে সাথে Pod মুছব না, কারণ প্রমাণ দ্রুত হারায়, আর Deployment আরেকটি বানিয়ে দেবে, যাতে একই ফাঁক থাকে। ক্রম: alert যাচাই, NetworkPolicy দিয়ে Pod আলাদা, label বদলে Service থেকে সরানো, সম্ভব হলে log আর filesystem-এর প্রমাণ নেওয়া। ঘটনার পরিধি: এই Pod-এর ServiceAccount কী করতে পারত, audit log-এ কী করেছে? সেই token আর secret বদলানো। Image কি আক্রান্ত, না runtime-এ ঢুকেছে? তারপর পরিষ্কার image-এ নতুন করে চালানো। Container-এর জন্য forensic পরিকল্পনা ঘটনার আগেই বানাতে হয়।

নিচের ব্লক এক সেবার cloud আর Kubernetes সাজ দেখে। আগে অনুমান করুন, কোন finding সবার ওপরে উঠবে। কোনো আসল API ডাকা হয় না।

// Review in-memory cloud and Kubernetes objects. Toy rules, no real API.
const pod = { name: 'files-api', image: 'files:latest', privileged: false,
  runAsNonRoot: false, hostPath: false, automountToken: true, role: 'files-sa' };
const roles = { 'files-sa': { verbs: ['*'], resources: ['secrets', 'pods'] } };
const net = { name: 'files-lb', internet: true, backend: 'files-api' };
const bucket = { name: 'shares', public: false, encrypted: true };

const findings = [];
const add = (sev, msg) => findings.push({ sev, msg });
if (!/@sha256:/.test(pod.image)) add(2, 'image not pinned by digest');
if (pod.privileged) add(4, 'privileged container');
if (!pod.runAsNonRoot) add(2, 'may run as root');
if (pod.hostPath) add(3, 'hostPath mount');
if (pod.automountToken) add(1, 'service account token mounted');
if (roles[pod.role].verbs.includes('*')) add(3, 'wildcard verbs on role ' + pod.role);
if (bucket.public) add(4, 'public bucket ' + bucket.name);

// One path can matter more than each finding alone.
const reachable = net.internet && net.backend === pod.name;
const wild = roles[pod.role].verbs.includes('*');
if (reachable && wild && pod.automountToken) {
  add(4, 'PATH: internet -> ' + pod.name + ' -> token -> wildcard role');
}
findings.sort((a, b) => b.sev - a.sev);
const names = { 4: 'CRITICAL', 3: 'HIGH', 2: 'MEDIUM', 1: 'LOW' };
for (const f of findings) console.log(names[f.sev].padEnd(9) + f.msg);
console.log(findings.length + ' findings');
CRITICAL PATH: internet -> files-api -> token -> wildcard role
HIGH     wildcard verbs on role files-sa
MEDIUM   image not pinned by digest
MEDIUM   may run as root
LOW      service account token mounted
5 findings

শীর্ষে কোনো একক সেটিং নেই, আছে একটি পথ। LOW মাপের mounted token একা নিরীহ, কিন্তু internet-এ খোলা সেবা আর wildcard role-এর সাথে মিলে সে পথের অংশ। পর্ব ৭২-এ একেই toxic combination বলা হয়েছে। ইন্টারভিউতে এই বাক্যটি শক্তিশালী: “আমি finding-এর তালিকা নয়, হামলার সম্ভাব্য পথ দেখি, আর পথের সবচেয়ে সস্তা কড়িটি আগে ভাঙি।” এখানে automountToken বন্ধ করলেই PATH লাইন চলে যায়। করে দেখুন।

Supply chain আর CI/CD গেট

প্র ৪১একটি জনপ্রিয় package আক্রান্ত হওয়ার খবর এলো। আপনার দল আক্রান্ত কি না কীভাবে জানবেন? (মাঝারি)

উত্তর: প্রথম প্রশ্ন: এটি আমাদের কোথায় আছে? উত্তর দেয় SBOM আর lockfile, পরোক্ষ dependency সহ। Log4Shell ২০২১-এ অনেক দল এই প্রশ্নেই আটকেছিল। তারপর: আক্রান্ত version চলছে কি না, কোড সেই অংশ ডাকে কি না, internet থেকে পৌঁছায় কি না, KEV-এ আছে কি না। ক্ষতিকর package হলে শুধু update নয়: build যন্ত্রে কী চলেছে, CI-র secret বদলানো, আর আগের artifact বাতিল।

প্র ৪২CI/CD pipeline নিজে কীভাবে লক্ষ্য হয়? কীভাবে শক্ত করবেন? (কঠিন)

উত্তর: Pipeline-এর হাতে secret আর production-এ যাওয়ার ক্ষমতা থাকে, তাই সে দামি লক্ষ্য। Control: long-lived key নয়, OIDC-র ছোট মেয়াদের পরিচয়। বাইরের action পূর্ণ commit hash-এ বাঁধা। Fork থেকে আসা pull request-এ secret নয়। প্রতি build-এ নতুন runner ব্যবহার। Main branch-এ review বাধ্য। Build আর deploy-এর অনুমতি আলাদা। Provenance তৈরি আর স্বাক্ষর (Sigstore), যাতে deploy-এর সময়ে যাচাই করা যায় artifact প্রত্যাশিত পথে এসেছে। SLSA এই পথের ধাপ দেখায়, তবে SLSA কোড নিরাপদ বলে দাবি করে না।

ফলো-আপ: “xz ২০২৪ থেকে কী শিখলেন?” — প্রকাশিত তথ্য অনুযায়ী দীর্ঘ সময় ধরে বিশ্বাস গড়ে release-এ ক্ষতিকর অংশ ঢোকানো হয়, আর একজন ডেভেলপার অস্বাভাবিক ধীরগতি দেখে ধরেন। শিক্ষা: scan-এর বাইরে maintainer-এর ওপর চাপ, build-এর পুনরুৎপাদন আর অস্বাভাবিকতা দেখার অভ্যাসও লাগে।

প্র ৪৩নতুন security scan pipeline-এ বসাবেন। প্রথম দিনেই সব ব্যর্থ করলে কী হবে? কীভাবে চালু করবেন? (মাঝারি)

উত্তর: শত শত পুরোনো finding-এ সব build থামলে দল গেটটি বন্ধ করে দেবে, আর বিশ্বাস হারাবে। ধাপে ধাপে: (১) প্রথমে শুধু রিপোর্ট, ফল মেপে। (২) False positive কমানো। (৩) অল্প কিছু নিশ্চিত নিয়মে থামানো: secret, KEV, নিশ্চিত critical. (৪) শুধু নতুন কোডে কড়া, পুরোনোটি আলাদা backlog-এ। (৫) ব্যতিক্রমে মালিক আর মেয়াদ। মাপুন: pipeline-এ কত সময় বাড়ল, কত finding সত্যি ছিল।

নিচের গেটে পাঁচটি finding আছে। SCA-র দুটি একই রকম critical, তবু ফল আলাদা। কেন? চালানোর আগে বলুন।

// A toy release gate. The date is fixed, and every rule is ours to change.
const TODAY = '2026-11-01';
const POLICY = {
  sca:      f => f.kev || (f.sev === 'critical' && f.fix) ? 'BLOCK' : f.sev === 'high' ? 'WARN' : 'INFO',
  sast:     f => f.sev === 'high' && f.confirmed ? 'BLOCK' : 'WARN',
  sbom:     f => 'BLOCK', // missing SBOM; a found secret or no signature would also block
};
const exceptions = [{ id: 'F2', expires: '2026-12-01', owner: 'pay-team' },
  { id: 'F4', expires: '2026-10-01', owner: 'web-team' }];
const findings = [
  { id: 'F1', type: 'sca', sev: 'medium', fix: true },
  { id: 'F2', type: 'sca', sev: 'critical', fix: true },
  { id: 'F3', type: 'sast', sev: 'high', confirmed: false },
  { id: 'F4', type: 'sca', sev: 'critical', fix: true },
  { id: 'F5', type: 'sbom' },
];
let blocked = 0;
for (const f of findings) {
  let verdict = POLICY[f.type](f);
  const ex = exceptions.find(e => e.id === f.id);
  let note = '';
  if (verdict === 'BLOCK' && ex) {
    if (ex.expires >= TODAY) { verdict = 'WARN'; note = ' (exception, ' + ex.owner + ')'; }
    else note = ' (exception expired ' + ex.expires + ')';
  }
  if (verdict === 'BLOCK') blocked++;
  console.log(f.id, f.type.padEnd(5), verdict.padEnd(6) + note);
}
console.log(blocked ? 'Release stopped: ' + blocked + ' blocker(s)' : 'Release may go');
F1 sca   INFO  
F2 sca   WARN   (exception, pay-team)
F3 sast  WARN  
F4 sca   BLOCK  (exception expired 2026-10-01)
F5 sbom  BLOCK 
Release stopped: 2 blocker(s)

F2 আর F4 দুটিই critical, আর দুটিরই fix আছে। F2-র ব্যতিক্রম ১ ডিসেম্বর পর্যন্ত বৈধ, তাই সতর্কতা। F4-এর ব্যতিক্রম ১ অক্টোবরে ফুরিয়েছে, তাই আবার blocker. মেয়াদ ছাড়া ব্যতিক্রম চিরস্থায়ী ঝুঁকি হয়ে যায়। F3 অনিশ্চিত, তাই সতর্কতা: নিশ্চিত না হয়ে থামালে দলের আস্থা যায়। F5-এ SBOM নেই: কোড নয়, প্রমাণ অনুপস্থিত, তবু থামে।

৭ · AI নিরাপত্তার প্রশ্ন

রিভিশন: পর্ব ৫১ · AI নিরাপত্তা, পর্ব ০৩, পর্ব ৭০

নতুন প্রশ্ন, পুরোনো নীতি: trust boundary, least privilege, defense in depth. নতুন একটি তথ্যই মনে রাখুন: model একটি প্রভাবিত হওয়ার মতো উপাদান। তাই তাকে নিয়ম রক্ষাকারী দারোয়ান বানানো যায় না। নম্বরগুলো OWASP LLM Top 10 (২০২৬) অনুসারে, যেমনটি পর্ব ৫১-এ আছে।

প্র ৪৪Prompt injection কী? কেন এর পূর্ণ সমাধান নেই? (মাঝারি)

উত্তর: Prompt injection (LLM01): পড়া লেখা model-এর আচরণ বদলে দেয়। সরাসরি হয় ব্যবহারকারীর কথায়, পরোক্ষ হয় নথি, email বা web পাতার ভেতরের লেখায়। SQL-এ parameter আদেশ আর ডেটাকে আলাদা করে, কিন্তু model-এর ভেতরে এমন পাকা দেয়াল নেই। তাই ধরে নিই model একদিন বিভ্রান্ত হবেই, আর ক্ষতি সীমিত রাখি: কম tool, কাজ ধরে মানুষের অনুমোদন, allowlist, sandbox, আর model-এর বাইরে সাধারণ কোডের permission gate.

প্র ৪৫কোম্পানির নথির ওপর একটি RAG chatbot নিরাপদে বানাবেন কীভাবে? (কঠিন)

উত্তর: মূল ঝুঁকি: ব্যবহারকারী যা পড়ার অধিকার রাখেন না, chatbot তা বলে দেয়। তাই অনুমতি যাচাই নথি খোঁজার আগেই, ব্যবহারকারীর নিজের পরিচয়ে, model-কে বলে নয়। Multi-tenant হলে প্রতি tenant-এর সূচি আলাদা। নথি মুছলে সূচি থেকেও মুছুন, উত্তরে উৎস দেখান, আর ঢোকানোর সময়েই গোপন তথ্য ছেঁকে নিন। নথির লেখা অবিশ্বস্ত ডেটা, কারণ পরোক্ষ injection সেখান থেকেই আসে। Log-এ প্রশ্ন আর উত্তরও সংবেদনশীল ডেটা।

প্র ৪৬একটি AI agent গ্রাহকসেবায় refund দিতে পারবে। আপনার review কী? (কঠিন)

উত্তর: এটি Excessive Agency-র (LLM03) জায়গা। আমি প্রশ্ন করব: সত্যিই agent-কে দিতে হবে, না সে প্রস্তাব দেবে আর মানুষ চাপবেন? দিলে: টাকার ওপরের সীমা, দিনে সীমা, শুধু সেই গ্রাহকের অর্ডারে, ছোট মেয়াদের নিজস্ব পরিচয়, প্রতিটি কাজের audit log, আর অবিশ্বস্ত লেখা পড়ার পরে টাকার কাজে মানুষের অনুমোদন। এই নিয়ম model-এর prompt-এ নয়, tool-এর কোডে। Prompt পরামর্শ, কোড বাধ্যবাধকতা।

প্র ৪৭দলের ডেভেলপাররা AI দিয়ে কোড লিখছেন। Security engineer হিসেবে আপনার নীতি কী? (মাঝারি)

উত্তর: নিষেধ নয়, পথ করে দেওয়া। অনুমোদিত টুল, যেখানে ডেটা-ব্যবহারের চুক্তি পরিষ্কার। Prompt-এ secret বা গ্রাহকের ডেটা নয়। AI-র লেখা কোডও সাধারণ review আর গেট পার হবে, কারণ এতে injection বা অনুমতির ফাঁক থাকতে পারে। নতুন dependency যাচাই, কারণ AI অস্তিত্বহীন package-এর নামও বলে, যা typosquatting-এর ঝুঁকি আনে। Model-এর output-কে অবিশ্বস্ত input ধরুন (LLM10, Improper Output Handling).

নিচের gate-টি সরল কোড, model-এর বাইরে। পর্ব ৫১-এর নীতির ছোট রূপ। Model কোনোটিই চালায় না, পরিকল্পনাটি হাতে লেখা।

// A permission gate in plain code, outside the model. No real model runs.
const TOOLS = { search_docs: 'read', read_ticket: 'read', send_email: 'external',
  refund_order: 'money', delete_record: 'destroy' };
const MAX_CALLS = 6;
function gate(call, state) {
  const effect = TOOLS[call.name];
  if (!effect) return 'DENY  tool not on the list';
  if (state.calls >= MAX_CALLS) return 'DENY  call budget used up';
  state.calls++;
  if (effect === 'destroy') return 'DENY  never allowed for this agent';
  if (effect === 'read') {
    if (call.tainted) state.tainted = true;
    return 'ALLOW read only' + (call.tainted ? ', context now untrusted' : '');
  }
  if (state.tainted) return 'ASK   person must approve, untrusted text in context';
  return effect === 'money' ? 'ASK   person must approve money' : 'ALLOW';
}
const state = { calls: 0, tainted: false };
const plan = [
  { name: 'read_ticket' },
  { name: 'search_docs', tainted: true },   // holds <untrusted-doc-text>
  { name: 'send_email' },
  { name: 'refund_order' },
  { name: 'delete_record' },
  { name: 'run_shell' },
  { name: 'read_ticket' },
  { name: 'read_ticket' },
];
for (const c of plan) console.log(c.name.padEnd(14) + gate(c, state));
read_ticket   ALLOW read only
search_docs   ALLOW read only, context now untrusted
send_email    ASK   person must approve, untrusted text in context
refund_order  ASK   person must approve, untrusted text in context
delete_record DENY  never allowed for this agent
run_shell     DENY  tool not on the list
read_ticket   ALLOW read only
read_ticket   DENY  call budget used up

send_email সাধারণত ALLOW হতো। কিন্তু আগের ধাপে অবিশ্বস্ত নথি পড়া হয়েছে, তাই এখন মানুষের অনুমোদন লাগছে। run_shell তালিকায় নেই, আর delete_record এই agent-এর জন্য কখনোই নয়। শেষ লাইনে ৬ কলের সীমা ফুরিয়েছে: এটি লুপ আর সীমাহীন খরচ থামায় (LLM06). লক্ষ করুন, run_shell সীমায় গোনা হয়নি, কারণ সে আগেই থেমেছে।

৮ · Incident, postmortem আর অগ্রাধিকার

রিভিশন: পর্ব ৩২, পর্ব ৬১, পর্ব ৬২, পর্ব ৬৫, পর্ব ৬৬, পর্ব ৬৮

একটি incident-এর গল্প বলা

ইন্টারভিউতে “একটি incident-এর কথা বলুন” এলে সময়রেখা ধরে বলুন। নিচের ঘটনা কাল্পনিক। একটি CI key ভুলে public repository-তে গিয়েছিল। ধাপে ধাপে দেখুন, প্রতিটি ফাঁক কোন প্রশ্ন তোলে।

ঘড়ি · এক দিনের স্থানীয় সময়
সময়
ঘটনা
ফাঁসের পরে
  1. ফাঁস। ঘটনা শুরু এখান থেকে, যদিও তখন কেউ জানে না। প্রতিরোধের প্রথম সুযোগ: push-এর আগে secret scanning.
  2. প্রথম ব্যবহার। মাত্র ২৯ মিনিট। Public repository-র secret মিনিটের মধ্যেও ব্যবহার হতে পারে, তাই “কেউ দেখেনি” ধরে নেওয়া যায় না।
  3. Alert. ব্যবহারের ২৬ মিনিট পরে। মাঝে ০৯:৪৪-এ bucket listing হয়েছে। Detection দেরিতে এলো, এটি postmortem-এর একটি বিষয়।
  4. Containment. Triage ১০:১৯-এ নিশ্চিত, key বন্ধ ১০:২৬-এ। Alert থেকে ১৯ মিনিট। প্রমাণ নষ্ট হয়নি, কারণ audit log আলাদা জায়গায় থাকে।
  5. Session বাতিল। Key বন্ধ করা আর চলমান session শেষ করা এক কাজ নয়। এই পাঁচ মিনিটের ফাঁকটি জানা থাকা চাই।
  6. পরিষ্কার অবস্থা। ১১৩ মিনিটে নতুন short-lived পরিচয়। Incident বন্ধ হবে তখনই, যখন প্রভাব জানা। Bucket listing-এর পরে কী পড়া হলো, তা audit log-এ দেখতে হবে।

উপরের সংখ্যাগুলো হাতে বানানো নয়। তিনটি ভিন্ন উৎসের log মিলিয়ে সময়রেখা বানালে এগুলো বেরিয়ে আসে। এই block নিজের বানানো নমুনা ফাইলেই কাজ করে।

export LC_ALL=C
cd "$(mktemp -d)"
# Fictional incident. Times are one local day, source names are made up.
cat > repo.log <<'EOF'
09:12 repo  commit adds file with key ci-deploy-example to a public repository
EOF
cat > cloud.log <<'EOF'
09:41 cloud login with key ci-deploy-example from 198.51.100.23
09:44 cloud bucket listing by ci-deploy-example
10:26 cloud key ci-deploy-example disabled
10:31 cloud active sessions revoked
EOF
cat > soc.log <<'EOF'
10:07 soc   alert: unusual location for ci-deploy-example
10:19 soc   triage confirms incident
11:05 soc   new key issued through short-lived CI identity
EOF
sort -k1,1 repo.log cloud.log soc.log > timeline.txt
echo "== merged timeline =="; cat timeline.txt
mins() { awk -v t="$1" 'BEGIN { split(t, a, ":"); print a[1] * 60 + a[2] }'; }
at() { mins "$(grep -m1 "$1" timeline.txt | cut -d' ' -f1)"; }
leak=$(at 'commit adds'); abuse=$(at 'login with key')
alert=$(at 'alert:'); stop=$(at 'disabled'); clean=$(at 'new key issued')
echo "== durations in minutes =="
echo "leak to first misuse : $((abuse - leak))"
echo "misuse to alert      : $((alert - abuse))"
echo "alert to key disabled: $((stop - alert))"
echo "leak to key disabled : $((stop - leak))"
echo "leak to clean state  : $((clean - leak))"
== merged timeline ==
09:12 repo  commit adds file with key ci-deploy-example to a public repository
09:41 cloud login with key ci-deploy-example from 198.51.100.23
09:44 cloud bucket listing by ci-deploy-example
10:07 soc   alert: unusual location for ci-deploy-example
10:19 soc   triage confirms incident
10:26 cloud key ci-deploy-example disabled
10:31 cloud active sessions revoked
11:05 soc   new key issued through short-lived CI identity
== durations in minutes ==
leak to first misuse : 29
misuse to alert      : 26
alert to key disabled: 19
leak to key disabled : 74
leak to clean state  : 113

sort -k1,1 তিন উৎসকে এক সময়রেখায় আনে। আসল কাজে আগে সব ঘড়ি একই সময় অঞ্চলে আনতে হয়, নইলে ক্রম মিথ্যা বলে। ৭৪ মিনিটের ভাঙন লক্ষ করুন: ২৯ (প্রতিরোধ না থাকায়), ২৬ (detection), ১৯ (সাড়া)। প্রতিটি অংশের সমাধান আলাদা, তাই শুধু মোট সময় বললে কিছুই শেখা হয় না।

প্র ৪৮“আগে থামাবেন, না আগে প্রমাণ রাখবেন?” Incident-এ এই টানাপোড়েন কীভাবে সামলান? (মাঝারি)

উত্তর: সাধারণ সেবা-বিভ্রাটে আগে ক্ষতি থামানো। Security incident-এ server মুছে ফেললে প্রমাণ হারায়, তাই সাধারণত মুছে নয়, আলাদা করে থামাই: network থেকে সরানো, key বন্ধ করা। আগে volatile প্রমাণের যা দ্রুত নেওয়া যায় নিই। ডেটা সক্রিয়ভাবে বেরিয়ে গেলে থামানোই আগে, আর সেই সিদ্ধান্তটি লিখে রাখি। আইনি বা তদন্তের প্রয়োজন থাকলে পর্ব ৬৩-এর chain of custody মাথায় রাখি।

প্র ৪৯ভালো postmortem কেমন? (মাঝারি)

উত্তর: Blameless postmortem-এ প্রশ্ন “কে ভুল করল” নয়, “ব্যবস্থা কেন ভুলটি সহজ করে দিল, আর কেন থামাল না”. কাঠামো: সময়রেখা, প্রভাব, মূল ও সহায়ক কারণ, কী ভালো গেল, আর মালিক ও তারিখসহ কাজের তালিকা। উপরের ঘটনায় “ডেভেলপার ভুলে key commit করলেন” মূল কারণ নয়। কারণ: long-lived key ছিল, scanner ছিল না। দোষ দিলে পরের বার মানুষ ভুল লুকোবেন, আর ঘটনা দেরিতে জানা যাবে।

ফলো-আপ: “Blameless মানে কি দায়হীন?” — না। ব্যবস্থার দায় থাকে, আর ইচ্ছাকৃত অসদাচরণ আলাদা বিষয়।

প্র ৫০একটি প্রকাশিত breach থেকে শেখা একটি শিক্ষা বলুন। (মাঝারি)

উত্তর: কাঠামো: কী প্রকাশিত, কোন প্রতিরক্ষা ব্যর্থ, আর কী থাকলে সাহায্য হতো। যেমন Equifax ২০১৭: প্রকাশিত সরকারি রিপোর্ট অনুযায়ী জানা একটি ত্রুটির patch সময়মতো পৌঁছায়নি, আর মেয়াদোত্তীর্ণ certificate ট্রাফিক দেখার যন্ত্রকে অন্ধ করে রেখেছিল। শিক্ষা: একটি কারণ প্রায় কখনো থাকে না। asset inventory, patch যাচাই আর “control নিজে চলছে কি না” দেখার ব্যবস্থা লাগে। উৎসের নাম বলুন, আর নিশ্চিত না হলে “প্রকাশিত রিপোর্ট অনুযায়ী” বলুন (পর্ব ৬৫)।

অগ্রাধিকারের অনুশীলন

প্র ৫১CVSS 9.8-এর একটি ত্রুটি পরীক্ষাগারের ভেতরের server-এ, আর CVSS 7.5-এর একটি internet-এ খোলা payment gateway-তে, KEV-এ তালিকাভুক্ত। কোনটি আগে? (সহজ)

উত্তর: Gateway. CVSS তীব্রতা মাপে, ঝুঁকি নয়। KEV মানে হামলা হচ্ছে, আর সেবাটি internet-এ খোলা ও জরুরি। ভেতরের যন্ত্র পরে, তবে ভুলে যাব না। পর্ব ৩২-এর ক্রম: হামলা হচ্ছে কি (KEV), হওয়ার সম্ভাবনা কত (EPSS), পৌঁছানো যায় কি, asset কতটা জরুরি।

প্র ৫২Release আগামীকাল। Review-তে একটি উঁচু ঝুঁকির finding পেলেন। সারাতে তিন দিন। কী করবেন? (কঠিন)

উত্তর: “থামান” বা “যেতে দিন” দুটি ছাড়াও পথ আছে। আমি সিদ্ধান্তের বিকল্প দেব: (১) ত্রুটিপূর্ণ feature-টি flag দিয়ে বন্ধ রেখে বাকি release যাক। (২) Compensating control: rate limit, WAF নিয়ম বা অতিরিক্ত monitoring, সীমিত সময়ের জন্য। (৩) তিন দিন পিছিয়ে দেওয়া। (৪) Risk acceptance: ব্যবসার মালিক লিখে ঝুঁকি নেন, মেয়াদসহ। ঝুঁকি মেনে নেওয়ার সিদ্ধান্ত আমার একার নয়। আমার কাজ পরিষ্কার ছবি দেওয়া আর একটি সুপারিশ করা।

এবার একটি আসল অনুশীলন। আপনার হাতে ১০ জন-দিন, আর সাতটি কাজ (L × I স্কোর, কাজের দিনসহ)। কাগজে নিজের তালিকা আগে বানান। KEV-এর কাজ বাধ্য। তারপর চালান।

// Ten engineer-days, seven jobs. Scores are L x I; the method is a teaching toy.
const BUDGET = 10;
const jobs = [
  { id: 'A share link owner check', L: 4, I: 5, days: 3 },
  { id: 'B short-lived CI identity', L: 3, I: 5, days: 1 },
  { id: 'C KEV library on public API', L: 5, I: 4, days: 2, kev: true },
  { id: 'D old TLS on internal admin', L: 2, I: 3, days: 2 },
  { id: 'E MFA on admin panel', L: 4, I: 5, days: 4 },
  { id: 'F verbose error pages', L: 3, I: 2, days: 1 },
  { id: 'G full log centralisation', L: 2, I: 4, days: 6 },
].map(j => ({ ...j, score: j.L * j.I }));

function greedy(order) {
  let left = BUDGET, sum = 0; const take = [];
  for (const j of order) if (j.days <= left) { left -= j.days; sum += j.score; take.push(j.id[0]); }
  return take.join(' ') + '  score ' + sum + '  days left ' + left;
}
const kevFirst = (a, b) => (b.kev ? 1 : 0) - (a.kev ? 1 : 0);
const byScore = [...jobs].sort((a, b) => kevFirst(a, b) || b.score - a.score);
const byRatio = [...jobs].sort((a, b) => kevFirst(a, b) || b.score / b.days - a.score / a.days);
let best = { sum: -1 };
for (let m = 0; m < 1 << jobs.length; m++) {
  const set = jobs.filter((_, i) => m >> i & 1);
  const days = set.reduce((s, j) => s + j.days, 0);
  const sum = set.reduce((s, j) => s + j.score, 0);
  if (days <= BUDGET && set.some(j => j.kev) && sum > best.sum) best = { sum, set, days };
}
console.log('Highest score first:', greedy(byScore));
console.log('Score per day first:', greedy(byRatio));
console.log('Best of all ' + (1 << jobs.length) + ' sets:', best.set.map(j => j.id[0]).join(' '), ' score', best.sum, ' days', best.days);
Highest score first: C A E B  score 75  days left 0
Score per day first: C B A F D  score 67  days left 1
Best of all 128 sets: A B C E  score 75  days 10

“প্রতি দিনে সবচেয়ে বেশি” শুনতে বুদ্ধিমানের, কিন্তু এখানে সে ছোট কাজে দিন খরচ করে E (admin-এ MFA) বাদ দিল, আর ১ দিন ফেলে রাখল: ৬৭. স্কোর ধরে সাজানো পথটি C, A, E, B নিল: ৭৫, যা ১২৮টি সম্ভাব্য সেটের সেরা ফলের সমান। এখানে দুটি মিলে গেছে, তবে এটি কাকতাল: অন্য সংখ্যায় স্কোর-ক্রমও হারতে পারে, কারণ এটি knapsack ধরনের সমস্যা। আর একটি সৎ সতর্কতা: L × I ক্রমসূচক স্কোর, তাই এগুলো যোগ করা মোটা হিসাব মাত্র (পর্ব ০৪)। ইন্টারভিউতে ফলটি নয়, যুক্তি বলুন: “G বাদ গেল, তাই বলে রাখি detection-এর ঝুঁকি পরের ধাপে যাচ্ছে।”

প্র ৫৩ডেভেলপার দল বলছে এই finding সারানোর সময় নেই। কীভাবে এগোবেন? (মাঝারি)

উত্তর: আগে বুঝব, আসল বাধা কী: সময়, না finding-টি বাস্তব মনে হচ্ছে না, না সমাধান অস্পষ্ট। তারপর কাজ ছোট করব: নির্দিষ্ট patch বা pull request নিজে দেব, test সহ। SLA আর ঝুঁকির কথা ব্যবসার ভাষায় বলব। মত না মিললে ঝুঁকি লিখে যথাযথ মালিকের কাছে নিয়ে যাব, লড়াই নয়, সিদ্ধান্তের জন্য। লম্বা মেয়াদে পুরো শ্রেণির ত্রুটি মুছে দেওয়া secure default বেশি কাজের।

৯ · নকল ইন্টারভিউ, ঝুঁকির ভাষা আর আচরণগত প্রশ্ন

রিভিশন: পর্ব ৫৪, পর্ব ৬৭, পর্ব ৬৮, Software engineering ইন্টারভিউ

একটি নকল কথোপকথন

পড়ার সময় প্রতি ধাপে থামুন, আর উত্তরটি আগে নিজে দিন। লক্ষ করুন, প্রার্থী কোথায় প্রশ্ন করছেন, কোথায় সংখ্যা দিচ্ছেন, আর কোথায় সিদ্ধান্ত অন্যের হাতে রাখছেন।

কথোপকথন · কাল্পনিক
বক্তা
গুণ
  1. প্রশ্ন। ইচ্ছা করেই ছোট। বেশিরভাগ তথ্য আপনাকে চেয়ে নিতে হবে।
  2. পরিধি। সরাসরি উত্তরে ঝাঁপ না দিয়ে তিনটি কাজের প্রশ্ন। প্রতিটিই ঝুঁকি বদলাতে পারে।
  3. তথ্য। ঠিকানা আর ফোন মানে ব্যক্তিগত ডেটা। ক্রমিক নম্বর মানে পাশের নম্বর অনুমান করা সহজ।
  4. ঝুঁকি। নাম, প্রভাব, সংখ্যা আর পরের ধাপ, চার বাক্যে। “হতে পারে” নয়, “আগে যাচাই করব”: অনুমানকে অনুমানই বলা হলো।
  5. চাপ। একটি প্রচলিত ভুল প্রস্তাব। পরীক্ষা হচ্ছে, আপনি মূল কারণ ধরতে পারেন কি না, আর সম্মান রেখে “না” বলতে পারেন কি না।
  6. মূল কারণ। প্রস্তাবের ভালো দিক স্বীকার করে আসল সীমা বলা হলো। শেষে একটি test: সমাধানটি যেন ফিরে না যায়।
  7. ব্যবসা। এখন আর কারিগরি প্রশ্ন নয়। দেখা হচ্ছে সিদ্ধান্ত নিতে পারেন কি না।
  8. শেষ। বিকল্প, ঝুঁকি-গ্রহণের মালিক, অতীতে ঘটেছে কি না, আর ভবিষ্যতের alert. ডেটা ফাঁসের আলামত পেলে incident response শুরু হবে।

ঝুঁকি কীভাবে বোঝাবেন

একই finding তিনজনকে তিনভাবে বলতে হয়। শ্রোতা যে সিদ্ধান্ত নেবেন, সেই ভাষায় বলুন। নিচের সংখ্যাগুলো কাল্পনিক ধরে নেওয়া।

শ্রোতাতিনি কী জানতে চানএকই finding, তাঁর ভাষায়
ডেভেলপারকোথায়, কীভাবে সারাব“receipt()-তে মালিকের যাচাই নেই। Query-তে user_id যোগ করুন, আর এই test-টি চালান।”
Engineering managerকত কাজ, কী ঝুঁকি, কবে“উঁচু ঝুঁকি। আজ এক দিনের কাজ। না সারলে release থামানোর সুপারিশ, কারণ গ্রাহকের ঠিকানা যাচ্ছে।”
নেতৃত্বব্যবসার ক্ষতি, কী সিদ্ধান্ত“একজন গ্রাহক অন্যের ঠিকানা দেখতে পারেন। এতে আস্থা আর উপাত্ত-আইনের ঝুঁকি আছে। কাল release বা এক দিন পেছানো, এর মধ্যে আমার সুপারিশ এক দিন।”

তিনটি অভ্যাস কাজে আসে। ভয় দেখাবেন না: “সব শেষ হয়ে যেতে পারে” বলে সিদ্ধান্ত ভালো হয় না। সম্ভব হলে সংখ্যা নয়, range দিন, আর অনুমান বলুন (পর্ব ৬৮)। আর সিদ্ধান্তের বিকল্প দিন, শুধু সমস্যা নয়।

প্র ৫৪নেতৃত্ব জিজ্ঞেস করলেন, “আমরা কি নিরাপদ?” কী বলবেন? (মাঝারি)

উত্তর: “হ্যাঁ” বা “না” কোনোটিই সৎ নয়, কারণ নিরাপত্তা একটি অবস্থান, শেষ বিন্দু নয়। বলব: “আমাদের সবচেয়ে বড় তিনটি ঝুঁকি এই। গত ত্রৈমাসিকে এই দুটি কমেছে। একটি বাকি, এর জন্য এই সিদ্ধান্ত দরকার। ঘটনা হলে এত সময়ে ধরতে পারব বলে আমরা মেপেছি।” কত “সবুজ” নয়, কী জানি আর কী জানি না, সেটিই সৎ রিপোর্ট।

প্র ৫৫নিরাপত্তা metric হিসেবে কী রিপোর্ট করবেন? (মাঝারি)

উত্তর: যা সিদ্ধান্ত বদলায়। KEV-তালিকার ত্রুটি সারাতে সময়, উঁচু ঝুঁকির কত অংশ SLA-র ভেতরে, phishing-প্রতিরোধী MFA-র আওতা, MTTD আর সাড়ার সময়, ব্যতিক্রমের সংখ্যা ও বয়স। “মোট finding” বা “ঠেকানো হামলার সংখ্যা” একা দেখালে ভুল ধারণা হয়, কারণ scan বাড়লে সংখ্যা বাড়ে। কোনো মাপকে লক্ষ্য বানালে মানুষ সেটিকে সাজাতে শুরু করে, এটিও মনে রাখুন।

আচরণগত প্রশ্ন আর STAR

আচরণগত প্রশ্নে STAR কাঠামো কাজে দেয়: Situation (পরিস্থিতি), Task (আপনার দায়িত্ব), Action (আপনি নিজে কী করলেন), Result (ফল, সম্ভব হলে সংখ্যায়)। সাথে একটি শিক্ষা। নিচের গল্পগুলো কাল্পনিক, শুধু কাঠামো দেখাতে। ইন্টারভিউতে নিজের সত্যি ঘটনা বলুন। আগের প্রতিষ্ঠানের গোপন তথ্য, গ্রাহকের নাম বা খোলা ত্রুটির বিবরণ বলবেন না। নতুন হলে কলেজ-প্রজেক্ট, ক্লাবের সাইট বা নিজের lab থেকে ঘটনা নিন।

প্র ৫৬“আপনি একটি নিরাপত্তা ঝুঁকি ধরেছিলেন, কিন্তু দল মানতে চায়নি।” (কাল্পনিক উত্তর) (মাঝারি)

উত্তর: S: “আমাদের ছোট প্রজেক্টে admin পাতা শুধু গোপন URL দিয়ে সুরক্ষিত ছিল।” T: “আমি review করছিলাম, আর দল বলল সময় নেই।” A: “আমি নিজের staging-এ, দলকে জানিয়ে, দেখালাম যে login ছাড়াই পাতা খোলে। তারপর এক ঘণ্টার একটি pull request দিলাম, role যাচাইসহ।” R: “একই দিনে merge হলো। পরে আমরা সব admin route-এ একটি common middleware বসালাম, আর ৫টি route-এর test যোগ হলো।”

লক্ষ করুন: নিজের পরিবেশে, অনুমতিসহ, আর সমাধান সহ।

প্র ৫৭“আপনার একটি ভুলের কথা বলুন।” (কাল্পনিক উত্তর) (মাঝারি)

উত্তর: S: “আমি একটি WAF নিয়ম সরাসরি blocking mode-এ চালু করেছিলাম।” T: “ভুয়া login চেষ্টা কমানো ছিল আমার কাজ।” A: “কিছু আসল গ্রাহক আটকে গেলেন। আমি নিজে জানালাম, নিয়মটি শুধু-log mode-এ ফেরালাম, আর log দেখে সীমা ঠিক করলাম।” R: “২০ মিনিটে সমস্যা থামল। এখন সব নিয়ম আগে report mode-এ চলে।”

দোষ অন্যের ঘাড়ে নেই, নিজের কাজ স্পষ্ট, আর শেষে ব্যবস্থার বদল।

প্র ৫৮“কেউ আপনাকে একটি ত্রুটির রিপোর্ট চেপে রাখতে বললেন।” কী করবেন? (কঠিন)

উত্তর: আগে বুঝব কেন বলছেন, হয়তো ভয়, হয়তো সঠিক কারণে গোপন রাখা। ত্রুটি রেকর্ড করা আর প্রকাশ করা এক নয়: সীমিত মানুষের মধ্যে নথিভুক্ত হওয়া জরুরি। গ্রাহকের ডেটা বা আইনি দায় থাকলে প্রতিষ্ঠানের নির্ধারিত পথে, ম্যানেজার, security lead বা legal-এর কাছে নিয়ে যাব। নিজের মতে বাইরে প্রকাশ করব না। নৈতিকতা আর দায়িত্বশীল প্রকাশের নীতি পর্ব ০৬-এ।

প্র ৫৯“নিরাপত্তায় আসতে চান কেন? অভিজ্ঞতা কম, তবু আপনাকে কেন নেব?” (সহজ)

উত্তর: মুখস্থ না, প্রমাণ দিন: “আমি সিস্টেম কীভাবে ভাঙে বুঝতে ভালোবাসি, আর এই কোর্সের ক্যাপস্টোনে একটি কাল্পনিক দোকানের threat model থেকে incident মহড়া পর্যন্ত নিজে করেছি। এই লিংকে আমার নমুনা রিপোর্ট আছে।” যা করেছেন, শুধু তা বলুন। নিজের public কাজে কোনো আসল প্রতিষ্ঠানের তথ্য রাখবেন না।

ইন্টারভিউয়ারকে আপনার প্রশ্ন

  • নিরাপত্তা দল আর ডেভেলপার দলের সম্পর্ক কেমন? Design review কখন হয়?
  • ঝুঁকি মেনে নেওয়ার সিদ্ধান্ত কে নেন, আর ব্যতিক্রমের মেয়াদ থাকে কি?
  • শেষ বড় incident-এর পরে কী বদলেছে?
  • এই ভূমিকায় on-call আছে? কীভাবে ভাগ হয়?
  • প্রথম ৯০ দিনে এই পদে ভালো কাজ কেমন দেখাবে?

১০ · ৩০ দিনের রিভিশন, অভিনন্দন আর পরের পথ

পুরো কোর্সের মানচিত্র: কোর্স হোম, শব্দের জন্য কোর্সের শব্দকোষ

দিনে ঘণ্টাখানেক ধরে সাজানো। আপনার সময় ও ভূমিকা অনুযায়ী বদলে নিন। Cloud ভূমিকা হলে ২৮ নম্বর দিন বাড়ান, application ভূমিকা হলে ১৬ থেকে ২১. প্রতিদিন শেষে একটি প্রশ্নের উত্তর জোরে বলুন, শুধু পড়বেন না।

দিনমডিউলমূল পর্বশেষে যা পারবেন
১–৩ভিত্তি২, ৩, ৪, ৬যেকোনো সেবার threat model ১৫ মিনিটে
৪–৭Cryptography৮, ৯, ১২, ১৩, ১৪অংশ ৫-এর টেবিল না দেখে বলা
৮–১০Identity১৭, ১৮, ১৯, ২০Login আর session-এর নকশা
১১–১৩Network২২, ২৩, ২৫, ২৬Zone আর নিয়মের নকশা
১৪–১৫System ও endpoint৩০, ৩২, ৩৪অগ্রাধিকারের যুক্তি
১৬–১৮Web৩৭, ৩৮, ৩৯, ৪০, ৪২, ৪৩অংশ ৩-এর ১২টি ড্রিল
১৯–২১নিরাপদ software৪৬, ৪৮, ৪৯, ৫১CI/CD গেট আর AI-র উত্তর
২২মানুষ৫৩, ৫৪দোষারোপহীন সংস্কৃতি বোঝানো
২৩–২৪Detection৫৫, ৫৬, ৬০একটি detection rule ব্যাখ্যা
২৫–২৬Incident৬১, ৬২, ৬৫অংশ ৮-এর সময়রেখা মুখে
২৭GRC৬৮, ৬৯, ৭০ঝুঁকিকে range-এ বলা
২৮Cloud৭২, ৭৩, ৭৪অংশ ৬-এর পরিস্থিতি
২৯অনুশীলন৭৫, ৭৬, ৭৭, ৭৮, ৭৯দুর্বল প্রশ্নগুলো আবার
৩০নকল ইন্টারভিউএই পর্ব, অংশ ৯৪৫ মিনিটের কথোপকথন, দুটি STAR গল্প

আগের দিন সন্ধ্যায় নতুন কিছু শিখবেন না। Internet আর screen share পরীক্ষা করুন, আর ঘুমান। আপনি কোনো vendor বা সংস্থার certificate-এর পথে থাকলে তার নিজের syllabus আলাদা, আর এই কোর্স একা তার পূর্ণ প্রস্তুতির দাবি করে না।

অভিনন্দন

আপনি ৮০টি পর্ব পেরিয়ে এসেছেন। CIA triad থেকে threat model, AES-এর ভেতর থেকে Kubernetes, phishing থেকে incident মহড়া: এখন আপনি বাড়ির তালাও বোঝেন, পুরো মহল্লার পাহারাও। সবচেয়ে বড় অর্জন কোনো সংজ্ঞা নয়। অর্জন হলো একটি অভ্যাস: কিছু দেখলেই জিজ্ঞেস করা, কী ভুল হতে পারে, আর আমরা কীভাবে জানব।

এরপর কী করবেন

  • নিজের একটি প্রমাণ বানান: ক্যাপস্টোনের threat model আর ঝুঁকির খাতা গুছিয়ে একটি নমুনা রিপোর্ট করুন, কাল্পনিক প্রতিষ্ঠানের নামে।
  • একটি ছোট lab রাখুন: নিজের যন্ত্রে দুটি VM বা container, একটি log সংগ্রাহক, আর একটি detection rule. প্রতি সপ্তাহে একটি ঘটনা মহড়া।
  • Primary source পড়ার অভ্যাস করুন: OWASP ASVS, NIST-এর দলিল, প্রকাশিত postmortem.
  • লেখা ও আলোচনায় অংশ নিন: open source প্রকল্পের নিরাপত্তা-নথি উন্নত করুন, স্থানীয় community-তে শিখুন।
  • Bug bounty করলে: শুধু প্রোগ্রামের লেখা scope-এর ভেতরে, পর্ব ৫০ মেনে।
  • ক্ষেত্র বাড়ান: System design, cloud আর একটি programming ভাষার গভীরতা এই পেশায় সবসময় কাজে দেয়।

শেষ কথা, আর সবচেয়ে জরুরি কথা: এই কোর্সে যা শিখলেন, তা দিয়ে পরীক্ষা করবেন শুধু নিজের system-এ, অথবা লিখিত অনুমতি আছে এমন system-এ। কৌতূহল, ভালো উদ্দেশ্য বা “শুধু দেখছিলাম” অনুমতির বিকল্প নয়। অনুমতি ছাড়া প্রবেশ অপরাধ, আর আপনার পুরো পেশা বিশ্বাসের ওপর দাঁড়িয়ে। আইনের বিবরণ পর্ব ০৬-এ আছে। এই পাতা আইনি পরামর্শ নয়।

AI-এর যুগে ইন্টারভিউর প্রস্তুতি

AI একজন ধৈর্যশীল নকল ইন্টারভিউয়ার হতে পারে। কিন্তু নিরাপত্তায় তার ভুলগুলো দামি। সে প্রায়ই CVE নম্বর আর standard বানায়। পুরোনো পরামর্শ দেয়: MD5, ECB, salt ছাড়া hash. Error সারাতে নিরাপত্তা বন্ধ করতে বলে: verify=False, chmod 777, খোলা CORS. তার লেখা কোডে injection বা অনুমতির ফাঁক থাকতে পারে। Triage-এ সে অতিরিক্ত আত্মবিশ্বাস দেখায়। আর prompt-এ দেওয়া secret ফাঁসের ঝুঁকিতে পড়ে। Live ইন্টারভিউতে AI ব্যবহারের নিয়ম আগে জেনে নিন, আর নিয়ম ভাঙবেন না।

AI-কে উত্তর লিখতে না বলে আপনাকে চেপে ধরতে বলুন। আসল প্রতিষ্ঠানের তথ্য, log, key বা গ্রাহকের ডেটা কখনো দেবেন না।

তুমি একজন কড়া কিন্তু ভদ্র security engineer ইন্টারভিউয়ার। শুধু প্রতিরক্ষার দিক থেকে প্রশ্ন করবে। আমার স্তর: [শুরু/মাঝারি/উন্নত]। আমার লক্ষ্য: [application/cloud/সাধারণ]। ১. আমাকে একটি কাল্পনিক সেবার secure design প্রশ্ন দাও। শুধু পরিধি বলো, উত্তর বলো না। ২. আমি পরিধি, সম্পদ, DFD, threat-এর ক্রম, control আর trade-off বলব। কোনোটি বাদ গেলে প্রশ্ন করো, নিজে বলে দিও না। ৩. ৩টি ফলো-আপ করো। একটি ব্যবসার চাপের, একটি ডেভেলপারের আপত্তির। ৪. শেষে পাঁচটি ক্ষেত্রে ১ থেকে ৫ নম্বর দাও: পদ্ধতি, গভীরতা, অগ্রাধিকার, যোগাযোগ, সততা। ৫. কোনো CVE, standard বা সংখ্যা নিয়ে নিশ্চিত না হলে "নিশ্চিত নই" লেখো, আর কোন প্রাথমিক উৎস দেখব বলো। কোনো হামলার ধাপ বা কোড লিখবে না।

নিজেকে যাচাই করুন

ভুল হলে কারণসহ ব্যাখ্যা পাবেন, আবার চেষ্টাও করতে পারবেন।

ক্রমSecure design ইন্টারভিউয়ে উত্তরের ধাপগুলো সঠিক ক্রমে সাজান (▲▼ চেপে সরান)

  1. পরিধি নিয়ে প্রশ্ন করা
  2. সম্পদের তালিকা আর ক্রম
  3. DFD আর trust boundary আঁকা
  4. Threat খুঁজে likelihood × impact দিয়ে সাজানো
  5. Control, trade-off আর detection বলা

(সহজ) একটি login করা সেবায় GET /invoices/1042 লগইন করা যেকোনো ব্যবহারকারীর জন্য যেকোনো invoice ফেরত দেয়। ত্রুটির সবচেয়ে ঠিক নাম কোনটি?

  • Authentication একেবারে নেই
  • IDOR বা broken object level authorization
  • Stored XSS
  • Session fixation

(মাঝারি) একজন ডেভেলপার বললেন, ক্রমিক রসিদ নম্বরকে UUID করলেই অন্যের রসিদ দেখার ঝুঁকি শেষ। কোন উত্তরটি সবচেয়ে সঠিক?

  • ঠিক, UUID অনুমতি যাচাইয়ের সম্পূর্ণ বিকল্প
  • UUID ডেটাকে encrypt করে, তাই ঠিক
  • UUID-র কোনো মূল্যই নেই, কখনো ব্যবহার করা যাবে না
  • UUID বাড়তি স্তর, মূল সমাধান server-এ মালিকের যাচাই

(সহজ) Python কোডে requests.get(url, verify=False) কী বন্ধ করে?

  • সার্ভারের certificate যাচাই
  • পুরো TLS encryption
  • URL-এর allowlist যাচাই
  • Response-এর schema যাচাই

(মাঝারি) ওয়ালেটের কোডে প্রথমে balance পড়া হয়, তারপর আলাদা ধাপে bal - amount লেখা হয়। একই সময়ে দুটি request এলে কী ঝুঁকি, আর সেরা সমাধান কী?

  • XSS; output encoding
  • Replay; response-এ HMAC যোগ করা
  • Race condition; শর্তসহ atomic UPDATE
  • Slow query; cache যোগ করা

(মাঝারি) Multi-tenant SaaS-এ tenant_id কোথা থেকে নেওয়া সবচেয়ে নিরাপদ?

  • URL-এর query থেকে
  • Request body থেকে
  • যাচাই করা session বা token-এর পরিচয় থেকে
  • Client-এর পাঠানো একটি custom header থেকে

(কঠিন) AES-GCM-এ একই key-তে একই nonce দুইবার ব্যবহার হলো। কোন বক্তব্যটি সঠিক?

  • গোপনীয়তা আর অখণ্ডতা দুটিই ক্ষতিগ্রস্ত হতে পারে
  • কিছুই হয় না, nonce গোপন নয়
  • শুধু nonce-টি ফাঁস হয়, ডেটা নিরাপদ থাকে
  • Library সবসময় নিজে থেকে ধরে থামিয়ে দেয়

(মাঝারি) একটি cloud access key public repository-তে পাওয়া গেল। প্রথম কাজ কোনটি হওয়া উচিত?

  • Git history থেকে commit মোছা
  • পরের সপ্তাহের সভায় বিষয়টি তোলা
  • কে commit করেছেন তা খুঁজে বের করা
  • Key বন্ধ বা বদলানো, তারপর ব্যবহার যাচাই

(মাঝারি) একটি Pod-এর পরিষেবা internet-এ খোলা, তার ServiceAccount token mount করা, আর সেই account-এর role-এ wildcard verb আছে। এই পরিস্থিতি বর্ণনায় সবচেয়ে ভালো ভাবনা কোনটি?

  • তিনটি আলাদা ছোট finding, কোনোটিই জরুরি নয়
  • মিলিত একটি পথ, একটি কড়ি ভাঙলেই পথ বন্ধ
  • Internet-এ খোলা থাকাটাই একমাত্র সমস্যা
  • Kubernetes-এর ত্রুটি, আপনার করার কিছু নেই

(মাঝারি) RAG chatbot-এ ব্যবহারকারীর অনুমতি যাচাই কখন হওয়া উচিত?

  • নথি খোঁজার আগে, ব্যবহারকারীর নিজের পরিচয়ে
  • Model উত্তর বানানোর পরে, উত্তর থেকে কেটে
  • System prompt-এ বলে দিলেই model নিজে মেনে চলবে
  • শুধু নথি index করার সময় একবার

(মাঝারি) ঝুঁকির ক্রমে “দিনপ্রতি স্কোর” ধরে সাজালে ৪ দিনের একটি বড় কাজ (স্কোর ২০) বাদ পড়ল, আর কয়েকটি ছোট কাজ ঢুকল। হাতে মোট ১০ দিন। সবচেয়ে ভালো শিক্ষা কোনটি?

  • দিনপ্রতি স্কোর সবসময় সেরা ফল দেয়
  • সংখ্যা অকেজো, শুধু অনুমানে চলুন
  • সরল নিয়ম সেরা ফল নিশ্চিত করে না, মোট ফল আর যুক্তি যাচাই করুন
  • সবসময় সবচেয়ে বড় কাজ আগে করুন

(সহজ) Blameless postmortem-এর মূল উদ্দেশ্য কী?

  • দোষী কর্মীকে চিহ্নিত করা
  • ব্যবস্থার দুর্বলতা বুঝে কাজের তালিকা বানানো
  • ঘটনাটি প্রতিষ্ঠানের বাইরে যেতে না দেওয়া
  • সব দায় থেকে সবাইকে মুক্তি দেওয়া

(সহজ) ইন্টারভিউতে আচরণগত প্রশ্নে কোন উত্তরটি সবচেয়ে ভালো?

  • ভুলটি সহকর্মীর ছিল বলে দেখানো
  • ইন্টারনেটের একটি নিখুঁত গল্প নিজের বলে বলা
  • আগের প্রতিষ্ঠানের খোলা ত্রুটির পূর্ণ বিবরণ দেওয়া
  • নিজের সত্যি ঘটনা STAR-এ, ফল আর শিক্ষাসহ

শব্দকোষ

লেখার মধ্যে ডটেড দাগ দেওয়া শব্দে মাউস রাখুন বা চাপুন — অর্থ দেখাবে। এই পর্বের সব নতুন শব্দ এখানে একসাথে:

মনে রাখুন

  1. নকশার উত্তরে ক্রম ধরুন: পরিধি, সম্পদ, DFD, ঝুঁকির ক্রম, control আর trade-off.
  2. Code পড়ুন source থেকে sink, আর finding-এ প্রভাব, সমাধান ও test বলুন।
  3. Crypto-তে নাম নয়, ব্যবহার দেখুন: nonce, key-এর জায়গা, যাচাই।
  4. Finding-এর তালিকা নয়, পথ দেখুন, আর সবচেয়ে সস্তা কড়িটি আগে ভাঙুন।
  5. ঝুঁকি মেনে নেওয়ার সিদ্ধান্ত মালিকের। আপনার কাজ পরিষ্কার ছবি, বিকল্প আর সুপারিশ.

পথের শেষ: এটিই এই কোর্সের শেষ পর্ব। ৮০টি পর্ব পেরিয়ে আসার জন্য অভিনন্দন। ইন্টারভিউর জন্য শুভকামনা। আর মনে রাখবেন: পরীক্ষা শুধু নিজের system-এ, অথবা লিখিত অনুমতিতে।

আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ

এই পর্বটি শেয়ার করুন:
এই পর্বে ভুল পেয়েছেন? জানান