InvoiceShelf তাদের CVE-2026-55610-এর জন্য একটি প্যাচ রিলিজ করেছে, যা একটি অত্যন্ত গুরুতর ত্রুটি (critical flaw)। এই ত্রুটির মাধ্যমে একটি কোম্পানির যেকোনো মালিক অন্য একটি কোম্পানির ইউজার অ্যাকাউন্ট হাইজ্যাক করতে পারতেন। CVSS স্কেলে ৮.৭ রেটিং প্রাপ্ত এই দুর্বলতাটি অ্যাপের Laravel কোডে একটি 'tenant-scope check' না থাকার কারণে তৈরি হয়েছিল।
ত্রুটিটি যেভাবে কাজ করত
InvoiceShelf হলো Laravel-এর ওপর ভিত্তি করে তৈরি একটি SaaS টুল, যা কোম্পানিগুলোকে একটি সিঙ্গেল ড্যাশবোর্ড থেকে ইউজার, ইনভয়েস এবং সেটিংস ম্যানেজ করতে সাহায্য করে। প্ল্যাটফর্মটি একজন 'tenant'-কে শনাক্ত করতে একটি কাস্টম হেডার (custom header) ব্যবহার করে। যখন একজন Owner কোনো ইউজার রেকর্ডের জন্য রিকোয়েস্ট করেন, তখন কোডটি কেবল এটি যাচাই করে যে, “রিকোয়েস্টকারী কি তার নিজস্ব কোম্পানির একজন Owner?”
এটি কখনোই যাচাই করে না যে টার্গেট করা ইউজারটি একই 'tenant'-এর অন্তর্ভুক্ত কি না। Laravel-এর 'implicit route-model binding' ইউজার আইডি-টিকে গ্লোবাল ইউজার টেবিলের একটি রো (row)-এর সাথে মিলিয়ে ফেলে, এবং অথরাইজেশন পলিসি শুধুমাত্র রিকোয়েস্টকারীর রোলের (role) ওপর ভিত্তি করে রিকোয়েস্টটি অনুমোদন করে দেয়।
ফলে একজন আক্রমণকারী যা করতে পারতেন:
- রিকোয়েস্ট URL-এ যেকোনো নিউমেরিক ইউজার আইডি প্রদান করতে পারতেন।
- ইমেলসহ সম্পূর্ণ ইউজার রেকর্ড प्राप्त করতে পারতেন।
- একটি আপডেট রিকোয়েস্ট পাঠিয়ে ভিকটিমের ইমেল, পাসওয়ার্ড পরিবর্তন করতে পারতেন এবং এমনকি অ্যাকাউন্টটিকে সুপার-অ্যাডমিন (super-admin) হিসেবে আক্রমণকারীর কোম্পানির অধীনে পুনরায় বরাদ্দ করতে পারতেন।
বাস্তবে, একজন ক্ষতিকারক Owner একটি কোম্পানি-ম্যানেজমেন্ট টুলকে একটি সার্বজনীন অ্যাকাউন্ট-টেকওভার অস্ত্রে পরিণত করেছিলেন। এর জন্য “Owner” রোলের বাইরে অন্য কোনো বিশেষ প্রিভিলেজ বা ক্ষমতার প্রয়োজন ছিল না।
কারা আক্রান্ত হয়েছেন
২.৪.১ ভার্সনের আগের যেকোনো ভার্সন ব্যবহারকারী সকল InvoiceShelf গ্রাহক এই ঝুঁকির মুখে ছিলেন। যেহেতু ত্রুটিটি রিকোয়েস্ট হ্যান্ডলিং-এর মূল পথে (core request-handling path) ছিল, তাই কোম্পানির আকার বা নিরাপত্তা ব্যবস্থা যাই হোক না কেন, যেকোনো tenant-কে অন্য কোনো tenant-এর Owner টার্গেট করতে পারতেন। এর প্রভাবের মধ্যে রয়েছে গোপনীয়তা রক্ষা করতে না পারা (ইমেল অ্যাড্রেস ফাঁস হওয়া) এবং তথ্যের অখণ্ডতা নষ্ট হওয়া (অননুমোদিত পাসওয়ার্ড পরিবর্তন, সুপার-অ্যাডমিন হিসেবে পদোন্নতি)।
প্যাচ (The Patch)
ডেভেলপাররা ২.৪.১ ভার্সন রিলিজ করেছেন, যেখানে ইউজার রেকর্ডের যেকোনো রিড (read) বা রাইট (write) অপারেশনের আগে একটি সুনির্দিষ্ট 'tenant check' যুক্ত করা হয়েছে। এই ফিক্সটি কুয়েরিকে (query) সক্রিয় কোম্পানির আইডেন্টিফায়ারের মধ্যে সীমাবদ্ধ করে দেয়, যা Laravel-কে শুধুমাত্র রিকোয়েস্টকারীর tenant-এর অন্তর্ভুক্ত রো-গুলো রিটার্ন করতে বাধ্য করে।
ডেভেলপারদের যা শেখা উচিত
- মাল্টি-টেন্যান্ট অ্যাপ্লিকেশনগুলোতে কখনোই গ্লোবাল প্রাইমারি কী (global primary keys)-এর ওপর নির্ভর করবেন না।
- শুধুমাত্র ডিলিট বা ক্রিয়েট অ্যাকশনের ক্ষেত্রে নয়, বরং প্রতিটি ডাটাবেস লুকআপের ক্ষেত্রে একটি 'tenant filter' প্রয়োগ করুন।
- অথরাইজেশন পলিসিগুলো যেন অ্যাক্টরের রোল এবং টার্গেট অবজেক্টের tenancy উভয়ই যাচাই করে তা নিশ্চিত করুন।
- রুট-মডেল বাইন্ডিংয়ের মতো ফ্রেমওয়ার্কের ইমপ্লিসিট ফিচারগুলোকে কেবল সুবিধার মাধ্যম হিসেবে দেখুন, কারণ এগুলো সিকিউরিটি গ্যাপ লুকিয়ে রাখতে পারে যদি না আপনি সুনির্দিষ্ট স্কোপিং (explicit scoping) যোগ করেন।
ভবিষ্যৎ ভাবনা
এই ঘটনাটি এমন যেকোনো SaaS-এর জন্য একটি বৃহত্তর ঝুঁকির ইঙ্গিত দেয় যা একই টেবিল শেয়ার করে। সিকিউরিটি অডিটে এমন সমস্ত এন্ডপয়েন্ট (endpoints) পর্যালোচনা করা উচিত যা আইডেন্টিফায়ার গ্রহণ করে এবং নিশ্চিত করা উচিত যে tenant scoping একইভাবে কার্যকর করা হয়েছে।
সারকথা: একটি মাত্র মিসিং 'tenant check' একজন প্রিভিলেজড ইউজার রোলকে একটি সার্বজনীন ব্যাকডোর (backdoor)-এ পরিণত করতে পারে। সঠিক স্কোপিং কোনো ঐচ্ছিক বিষয় নয়; এটি যেকোনো মাল্টি-টেন্যান্ট সিস্টেমের ডেটা আইসোলেশনের (data isolation) ভিত্তি।
