این یک نوع بسیار خاص از سوء استفاده است که انواع نرم افزارها را آزار می دهد.
Use-After-Free (UAF) یک آسیب پذیری بدوی تخریب حافظه است که همچنان تهدیدی قابل توجه برای انواع نرم افزارها از سیستم عامل گرفته تا نرم افزار کاربردی است. این نقص امنیتی حیاتی زمانی رخ میدهد که یک جزء برنامه سعی میکند به دادههای موجود در آدرس حافظهای که قبلاً آزاد شده است، دسترسی پیدا کند، از این رو نام آن استفاده پس از آزاد شدن است.
آسیب پذیری های UAF می تواند منجر به بهره برداری بالقوه از نرم افزار یا حتی به خطر افتادن سیستم شود. در اینجا آسیب پذیری UAF چیست، چرا اتفاق می افتد، و چگونه می توانید نرم افزار خود را از آسیب پذیری UAF ایمن کنید.
آسیب پذیری Use-After-Free (UAF) چیست؟
قبل از پرداختن به آسیبپذیری Use-After-Free، اجازه دهید یک قدم به عقب برگردیم و برخی از اصول مدیریت حافظه را درک کنیم. هنگامی که یک برنامه اجرا می شود، داده ها و کد آن در حافظه بارگذاری می شود.
مدیریت حافظه فرآیند مدیریت نحوه ذخیره (به نام تخصیص حافظه) و حذف (به نام تخصیص حافظه) داده ها و کد در حافظه به روشی بهینه است. دو بخش اصلی حافظه که در آن داده های برنامه ذخیره می شود، پشته و پشته هستند.
برنامه ها را می توان به صورت ایستا در پشته و به صورت پویا در پشته اختصاص داد. یک آسیبپذیری استفاده پس از آزادسازی زمانی رخ میدهد که برنامهنویسان تخصیص و تخصیص حافظه پویا را به درستی در برنامههای خود مدیریت نمیکنند. این بدان معناست که آسیبپذیریهای کلاس UAF نوعی بهرهبرداری از پشته است. برای درک بهتر این آسیب پذیری، درک قوی از نحوه عملکرد اشاره گرها در برنامه نویسی کمک می کند.
همانطور که از نام آن پیداست استفاده پس از آزاد شدن (UAF)، نوعی آسیبپذیری بدوی تخریب حافظه است که زمانی رخ میدهد که به یک شی که قبلاً از حافظه اختصاص داده شده است، دوباره دسترسی پیدا کند که منجر به خرابی یا پیامدهای ناخواسته مانند نشت حافظه، تشدید امتیاز (EOP) یا اجرای کد دلخواه. بیایید یاد بگیریم که این شرایط در وهله اول چگونه رخ می دهد و چگونه از آن بهره برداری می شود.
چگونه از استفاده پس از آزاد شدن (UAF) بهره برداری می شود؟
استفاده پس از آزاد شدن (UAF)، همانطور که از نامش پیداست، یک آسیبپذیری بدوی تخریب حافظه است که زمانی رخ میدهد که یک برنامه همچنان به مکانهای حافظهای که آزاد کرده است دسترسی پیدا کند. بیایید نگاهی به یک کد مثال بیندازیم:
#include <stdio.h>
#include <stdlib.h>
int main() {
int *MUO = malloc(sizeof(int));
*MUO = 69420;
printf("Value: %d\n", *MUO);
free(MUO);
printf("Value?: %d\n", *MUO);
return 0;
}
آیا می تواند آسیب پذیری را تشخیص دهد؟ همانطور که می بینید، در این کد، اشاره گر MUO با استفاده از تابع ()free از حافظه جدا می شود، اما در خط بعدی با استفاده از تابع ()printf دوباره فراخوانی می شود. این منجر به رفتار غیرمنتظره برنامه می شود و بسته به جایی که آسیب پذیری در نرم افزار وجود دارد، ممکن است برای افزایش امتیاز و نشت حافظه مورد استفاده قرار گیرد.
چگونه مصرف را پس از رایگان کاهش دهیم؟
UAF به دلیل اشتباهات در برنامه نویسی یک برنامه رخ می دهد. چند احتیاط وجود دارد که می توانید برای جلوگیری از آسیب پذیری های Use-After-Free در نرم افزار خود انجام دهید.
در اینجا چند بهترین روش وجود دارد که می توانید برای به حداقل رساندن آسیب پذیری های خراب حافظه در نرم افزار خود اتخاذ کنید:
- استفاده از زبان های برنامه نویسی ایمن مانند Rust با مکانیزم های داخلی برای جلوگیری از آسیب پذیری های بدوی تخریب حافظه مانند UAF، Buffer Overflow و غیره. اگر از زبان های برنامه نویسی مانند C/C++ استفاده می کنید، به احتمال زیاد باگ های حافظه را در کد خود معرفی می کنید. به همین دلیل، حتی سیستم عامل هایی مانند ویندوز و لینوکس به آرامی به سمت Rust مهاجرت می کنند. همچنین اگر برنامه های سطح پایین ایجاد می کنید، باید در مورد Rust یاد بگیرید.
- علاوه بر استفاده از یک زبان ایمن برای حافظه، توصیه میشود بهترین روشها مانند تنظیم یک اشارهگر روی مقدار NULL پس از آزاد شدن آن را دنبال کنید تا از هر گونه آسیبپذیری Use-After-Free جلوگیری کنید.
- همچنین میتوانید تکنیکهایی مانند تخصیص یکموقع (OTA) را پیادهسازی کنید که از دسترسی مهاجمان به اشیاء حافظه آزاد شده و یک خطمشی چرخه حیات شیء سختگیرانه جلوگیری میکند، که به پیگیری هر شی حافظهای که تخصیص داده شده و تخصیص داده میشود کمک میکند. البته به خاطر داشته باشید که این پیاده سازی ها ممکن است باعث افزایش سربار حافظه و عملکرد شود.
نمونه های واقعی آسیب پذیری استفاده پس از آزادسازی (UAF).
آسیبپذیری Use-After-Free (UAF) در سناریوهای مختلف دنیای واقعی از مرورگرهای وب گرفته تا هسته اندروید و برنامههای روزمره کشف و مورد سوء استفاده قرار گرفته است. این نیاز به اقدامات امنیتی پیشگیرانه را نشان می دهد. برخی از نمونه های واقعی UAF عبارتند از:
- مرورگرهای اینترنتی: آسیبپذیریهای UAF در مرورگرهای وب برای اجرای کد دلخواه، به خطر انداختن حریم خصوصی کاربر و اجرای حملات اجرای کد از راه دور مورد سوء استفاده قرار گرفتهاند. یک مثال اخیر میتواند CVE-2021-38008 باشد که از یک آسیبپذیری UAF در Google Chrome سوء استفاده میکند و به عوامل تهدید اجازه میدهد کد دلخواه را از راه دور بر روی ماشین قربانی اجرا کنند.
- سیستمعاملها: آسیبپذیریهای UAF که در هستههای ویندوز/لینوکس/اندروید یافت میشوند به مهاجمان این امکان را میدهند که امتیازات بالاتری کسب کنند، مکانیسمهای امنیتی را دور بزنند و پایداری را به دست آورند. تعداد زیادی آسیب پذیری UAF وجود دارد که تا به امروز در هسته های سیستم عامل پیدا شده اند و هنوز هم یافت می شوند. در زمان نگارش این مقاله، CVE-2023-3269، یک آسیبپذیری UAF دیگر در هسته لینوکس که منجر به افزایش امتیاز میشود، بهطور عمومی منتشر شد. CVE-2022-23270 نمونه ای از آسیب پذیری UAF در هسته ویندوز است.
- برنامه های کاربردی نرم افزار: آسیب پذیری های UAF در برنامه های نرم افزاری برای دستکاری رفتار برنامه مورد سوء استفاده قرار گرفته اند که منجر به افشای اطلاعات، اجرای کد دلخواه، خرابی برنامه و در بدترین حالت، افزایش امتیازات می شود. چندین برنامه نرم افزاری در معرض حملات UAF بوده و هستند. این نرم افزارها بیشتر برنامه های C/C++ هستند که با رویکردهای مدیریت حافظه ناکارآمد و ناایمن توسعه یافته اند.
برای کسب اطلاعات بیشتر در مورد آسیبپذیریهای Use-After-Free در برنامههای کاربردی دنیای واقعی، میتوانید صفحه فهرست رسمی MITER CVE را بررسی کرده و بر اساس کلمه کلیدی Use-After-Free مرتب کنید.
تخصیص کارآمد حافظه به ایمن کردن نرم افزار کمک می کند
تخصیص حافظه بهینه و اندیشیده شده تا حد زیادی از برنامه های شما در برابر آسیب پذیری های رایج تخریب حافظه بدوی محافظت می کند.
UAF همراه با زمان بررسی زمان استفاده (TOCTOU)، شرایط مسابقه، و سرریزهای بافر (BOF) برخی از آسیب پذیری های حافظه هستند که معمولا مورد سوء استفاده قرار می گیرند. با یادگیری نحوه مدیریت حافظه برنامه شما توسط پلتفرمی که روی آن اجرا می شود، می توان از همه این موارد اجتناب کرد. این به شما وضوح نحوه تخصیص برنامه شما توسط سیستم عامل را در حافظه می دهد و شما را با ابزارهایی برای طراحی نرم افزار برای عملکرد و امنیت بهینه مجهز می کند.
اگر قبلا این کار را نکرده اید، می توانید با درک نحوه انجام مدیریت حافظه در لینوکس، پرکاربردترین سیستم عامل سرور جهان، شروع کنید.