یک فایل مدل ۶۵ بایتی می‌تواند موتور استنتاج محبوب Llama CPP را ناگهان متوقف کند. این محتوای بسیار کوچک باعث بروز خطای تقسیم بر صفر در داخل پارسر (parser) شده و منجر به کرش SIGFPE می‌شود.

چرا این کرش اهمیت دارد

چه مشکلی پیش آمد

پارسر، متادیتای مدل را در ساختارهای C++ می‌خواند و بررسی می‌کند که هر بُعد تنسور (tensor dimension) «غیرمنفی» باشد. عدد صفر این شرط را برآورده می‌کند، بنابراین بررسی با موفقیت انجام می‌شود. خط بعدی کد، از این بُعد به عنوان مقسوم‌علیه در محاسباتی استفاده می‌کند که فرض را بر مثبت بودن مقدار می‌گذارد. وقتی بُعد صفر باشد، عملیات تقسیم یک استثنای ممیز شناور (SIGFPE) ایجاد کرده و برنامه را متوقف می‌کند.

این اعتبارسنجی تنها نیمی از ویژگی ثابت (invariant) مورد نیاز را پوشش می‌داد: مقادیر منفی را مسدود می‌کرد اما صفر را نادیده می‌گرفت، در حالی که صفر نیز برای محاسبات بعدی به همان اندازه ناامن است.

توسعه‌دهندگان باید چه کار کنند

  • با فایل‌های مدل مانند باینری‌ها برخورد کنید. بارگذاری یک مدل، بایت‌های خام را در ساختارهای حافظه تجزیه (parse) می‌کند؛ این یک مرز کلاسیک است که در آن داده‌های بررسی‌نشده می‌توانند باعث کرش فرآیند یا حتی اتفاقات بدتر شوند.
  • از بررسی‌های ناقص خودداری کنید. شرطی که تنها بخشی از ویژگی ثابت مورد نیاز را پوشش می‌دهد، حس امنیت کاذبی ایجاد می‌کند. در اینجا، «غیرمنفی» بودن کافی نبود؛ کد به شرط «مثبت» بودن نیاز داشت.
  • فرض‌ها را پس از هر بررسی زیر سوال ببرید. وقتی یک تست محدوده (bounds test) انجام می‌شود، بررسی کنید که کد بعدی به ویژگی سخت‌گیرانه‌تری تکیه نکند.
  • از ابزارهای fuzzing استفاده کنید. نویسنده با اجرای libFuzzer به همراه AddressSanitizer، این باگ را کشف کرد؛ این ابزار ورودی‌ها را تغییر می‌دهد (mutate) و عملیات غیرقانونی مانند تقسیم بر صفر را شناسایی می‌کند.

نحوه اعمال اصلاحیه

این اصلاحیه یک محافظ (guard) اضافه می‌کند که در صورت صفر بودن یک بُعد، از محاسبه سرریز (overflow) صرف‌نظر می‌کند. این شرط کوچک، ضمن حذف مسیر کرش، از پشتیبانی از تنسورهای با اندازه صفرِ مجاز (که در برخی از انواع مدل‌ها برای ویژگی‌های اختیاری استفاده می‌شوند) نیز محافظت می‌کند.

نتیجه‌گیری: یک فایل تک‌بایتی ۶۵ بایتی می‌تواند یک موتور استنتاج گسترده را از کار بیندازد؛ اعتبارسنجی دقیق و fuzzing سیستماتیک، بارگذارهای مدل (model loaders) را ایمن نگه می‌دارد.

منبع: https://dev.to/harrisonsec/your-model-file-is-untrusted-input-1eap