InvoiceShelf یک وصله (patch) برای CVE-2026-55610 منتشر کرد؛ یک نقص امنیتی بحرانی که به هر مالک در یک شرکت اجازه میداد حسابهای کاربری در شرکت دیگری را تسخیر کند. این آسیبپذیری که در مقیاس CVSS امتیاز ۸.۷ را دریافت کرده است، ناشی از نبودِ بررسی محدوده مستأجر (tenant-scope check) در کدهای Laravel اپلیکیشن بود.
نحوه عملکرد نقص امنیتی
InvoiceShelf یک ابزار SaaS است که بر پایه Laravel ساخته شده و به شرکتها اجازه میدهد کاربران، فاکتورها و تنظیمات را از طریق یک داشبورد واحد مدیریت کنند. این پلتفرم برای شناسایی یک مستأجر (tenant)، یک هدر سفارشی را میخواند. زمانی که یک مالک (Owner) درخواست رکورد یک کاربر را میدهد، کد فقط این را بررسی میکند که: «آیا درخواستکننده، مالک شرکت خودش هست؟»
این کد هرگز تأیید نمیکند که آیا کاربر هدف متعلق به همان مستأجر هست یا خیر. قابلیت route-model binding ضمنی در Laravel، شناسه کاربر (user ID) را به ردیفی در جدول جهانی کاربران (global users table) متصل میکند و سیاستهای مجوزدهی (authorization policy) نیز درخواست را صرفاً بر اساس نقش درخواستکننده تأیید میکنند.
یک مهاجم میتوانست:
- هر شناسه عددی کاربر را در URL درخواست ارسال کند.
- رکورد کامل کاربر، از جمله ایمیل را دریافت کند.
- یک عملیات بهروزرسانی انجام دهد که ایمیل و رمز عبور قربانی را بازنویسی کرده و حتی حساب را به عنوان یک super-admin به شرکت مهاجم اختصاص دهد.
در عمل، یک مالک مخرب، یک ابزار مدیریت شرکت را به یک سلاح همهجانبه برای تسخیر حسابها (account-takeover) تبدیل کرد. برای این کار به هیچ سطح دسترسی فراتر از «Owner» نیاز نبود.
چه کسانی تحت تأثیر قرار میگیرند
تمام مشتریان InvoiceShelf که از نسخههای قبل از 2.4.1 استفاده میکردند، در معرض خطر بودند. از آنجایی که این نقص در مسیر اصلی مدیریت درخواستها قرار دارد، هر مستأجری میتواند بدون توجه به اندازه یا وضعیت امنیتی، توسط مالکِ هر مستأجر دیگری هدف قرار گیرد. پیامدهای این نقص شامل از دست رفتن محرمانگی (آدرسهای ایمیل) و از دست رفتن یکپارچگی (تغییرات غیرمجاز رمز عبور، ارتقا به super-admin) است.
وصله (Patch)
توسعهدهندگان نسخه 2.4.1 را منتشر کردند که یک بررسی صریح برای مستأجر (explicit tenant check) را پیش از هرگونه عملیات خواندن یا نوشتن روی رکورد کاربر اضافه میکند. این اصلاحیه، پرسوجو (query) را به شناسه شرکت فعال محدود میکند و Laravel را مجبور میکند که فقط ردیفهایی را برگرداند که متعلق به مستأجرِ درخواستکننده هستند.
آنچه توسعهدهندگان باید بیاموزند
- هرگز در اپلیکیشنهای چندمستأجره (multi-tenant) به کلیدهای اصلی جهانی (global primary keys) اتکا نکنید.
- یک فیلتر مستأجر (tenant filter) را برای هر جستجوی پایگاه داده اعمال کنید، نه فقط برای عملیات حذف یا ایجاد.
- سیاستهای مجوزدهی را طوری تنظیم کنید که هم نقش عامل (actor) و هم وابستگی مستأجر (tenancy) شیء هدف را تأیید کنند.
- با ویژگیهای ضمنی فریمورک مانند route-model binding به عنوان ابزارهای تسهیلکننده برخورد کنید که میتوانند شکافهای امنیتی را پنهان کنند، مگر اینکه محدودسازی صریح (explicit scoping) را اضافه کنید.
نگاهی به آینده
این حادثه نشاندهنده ریسک گستردهتری برای هر SaaS است که از جداول مشترک استفاده میکند. ممیزیهای امنیتی باید تمام نقاط انتهایی (endpoints) را که شناسهها را میپذیرند بررسی کرده و تأیید کنند که محدودسازی مستأجر (tenant scoping) به طور یکنواخت اعمال شده است.
نکته کلیدی: نبودِ تنها یک بررسیِ مربوط به مستأجر میتواند یک نقش کاربری دارای امتیاز را به یک درِ پشتی همهجانبه تبدیل کند. محدودسازی صحیح (Proper scoping) یک انتخاب نیست؛ بلکه زیربنای جداسازی دادهها در هر سیستم چندمستأجره است.
