آسیب پذیری Race Condition چیست و چه خطری دارد؟

0 78
۵/۵ - (۴ امتیاز)

فهرست

در این مقاله از سری مقالات امنیت نرم افزار آکادمی ترجنس یک آسیب پذیری را بررسی می کنیم که در بر اثر وجود Race Condition در نرم افزار حادث می شود. واقعیت این است که Race Condition به خودی خود آسیب پذیری نیست اما می تواند باعث آسیب پذیری خطرناکی شود که آن را آسیب پذیری Race Condition می نامند.

شرایط مسابقه یا Race Condition چیست و چگونه پدید می آید؟

اساسا Race Condition به شرایطی اطلاق می شود که خروجی یک برنامه وابسته به تداخل یا شرایط زمانی رویدادهای مختلف شود. Race Condition در برنامه هایی پیش می آید که دو یا چند مولفه مثل نخ (Thread) یا فرآیند یا پردازه (Process) بر سر یک منبع مشترک با یکدیگر رقابت کنند. برای روشن شدن موضوع یک مثال در پایتون می آوریم. مثالی که ارائه می دهیم یک شبیه سازی ساده از عمل خواندن بروزرسانی در پایگاه داده است: مقدار یک داده در پایگاه داده به روز می شود. طبیعی است که برای این کار لازم است یک عمل خواندن و یک عمل نوشتن انجام شود. پر واضح است که در هر زنجیره رویدادی که عمل خواندن وجود داشته باشد، در صورت استفاده از همروندی (Concurrency) یا موازی سازی (Parallelism) می تواند Race Condition پدید آید. و اما مثال:

class Database:
    def __init__(self):
        self.data = 1

    def update(self):
        l_data = self.value
        l_data += 1
        time.sleep(0.2)
        self.data = l_data

کلاس معرفی شده یک پایگاه داده را شبیه سازی می کند (!!!) و تابع update یک مقدار در آن را بروز می کند.
استفاده از کلاس:

if __name__ == "__main__":
    db = Database()
    print("Data Value Before Update Is: %d", db.data)

    with concurrent.futures.ThreadPoolExecutor(max_workers = 2) as executor:
        for index in range(2):
            executor.submit(db.update, index)
    print("data Value After Update Is: %d", db.data)

دو نخ داریم که هر کدام تابع update ار فراخوانی می کنند. طبیعی است که پس از اجرای کامل برنامه مقدار data باید برابر۳ باشد اما مقدار گاهی برابر ۲ می شود (احتمالا در همان اجرای ابتدایی این اتفاق می افتد ولی اگر نشد چندبار اجرا کنید).
به زبان ساده می توان توضیح داد که نخی که یک واحد به مقدار data اضافه می کند هنوز به طور کامل نتیجه را ذخیره نکرده که نخ دوم مقدار را می خواند (که ۱ باشد) و در نهایت مقدار ۲ برای data ذخیره می شود.
اما موضوع این پست این مورد نیست! موضوع آسیب پذیری ای است که در این شرایط رخ می دهد.

آسیب پذیری Race Condition

درست مدیریت نکردن Race Condition توسط برنامه نویس در برنامه هایی که به صورت چند نخی (Multithread) یا چند پردازنده (Multiprocess) نوشته می شوند می تواند علاوه بر تاثیراتی که روی درستی برنامه می گذارد برنامه را به یک برنامه آسیب پذیر خطرناک تبدیل کند. قبلا چند مورد از آسیب پذیری هایی که ناشی از عدم دانش یا توجه برنامه نویس و طراح نرم افزار به مسائل امنیتی بوجود آمدند را در مقالاتی چون این و این و این مقاله بیان کردیم. همچنین در مورد DevSecOps مقاله ای دیدیم و تاثیر آن روی کاهش آسیب پذیری های این چنینی را بررسی کردیم.
آسیب پذیری Race Condition انواع مختلفی دارد. ما در این مقاله در مورد Time-of-check-Time-of-use صحبت می کنیم. این آسیب پذیری نوع خاص و البته رایجی از Race Condition است که در زمانی رخ می دهد که یک شرط قبل از استفاده از یک منبع چک می شود (مثل چیزی که در مثال دیدیم). آسیب پذیری امنیتی حاصل از این مورد را TOCTTOU می نامند.
تکه کد زیر را در نظر بگیرید:

if (!access("/tmp/file", W_OK)) {
    f = open("/tmp/file", O_WRITE);
    write_to(file);
}
else {
    fprintf("Permission Denied");
}

فرض کنید برنامه ای که کد بالا در آن وجود دارد یک برنامه Set-UID است و بنابراین هنگامی که برنامه توسط کاربر عادی اجرا شود euid برنامه برابر صفر یا root است. برنامه قصد دارد در یک file در دایرکتوری tmp بنویسد منتها برای جلوگیری از نوشتن غیر مجاز برنامه چک می کند که کاربر مجوز نوشتن روی فایل را داشته باشد. تابع access این عمل را انجام می دهد. دقت کنید که تابع access مقدار uid را چک می کند نه euid و این خوب است! وقتی این موضوع چک شد و در صورتی که کاربر مجوز نوشتن را داشت فایل برای نوشتن باز می شود اما تابع open برخلاف تابع access بجای uid مقدار euid را چک می کند و این بد است! پس در مورد این برنامه تابع open‌ همیشه موفق است چرا که برنامه Set-UID است و euid آن برابر صفر یا root است. اصلا برای همین است که از تابع access استفاده می شود اما بین چک کردن فایل و باز کردن آن یک پنجره زمانی است و این جذاب است.
فکر کنید بتوان در این پنجره بتوان فایل file را به یک Symbolic Link تغییر داد. خیلی جذاب می شود! در این صورت می توان در یک فایل حساس نوشت و یک کاربر با دسترسی root تعریف کرد و این یعنی Privilege Escalation! اما قرار گرفتن در این پنجره زیاد کار راحتی نیست چرا که در هر لحظه در کامپیوتر میلیون یا حتی میلیاردها رخداد اجرا می شوند. اگر این تغییر زود رخ دهد نتیجه access خطا می شود و اگر این تغییر دیر انجام شود برنامه از فایل استفاده می کند و کارش (در این قسمت) تمام می شود. واقعیت این است که احتمال قرار گرفتن در این پنجره کم است اما اگر به اندازه کافی (تعداد قابل قبول) تلاش کنیم حتما موفق می شویم.

برنده شدن در Race Condition

فرض کنید برنامه قبلی را داریم. نیاز به یک برنامه هم داریم که سمت مهاجم اجرا می شود. برنامه مهاجم دو عمل را به صورت تکراری انجام می دهد:

  • فایل file را به یک فایل که توسط ما قابل نوشتن است تبدیل می کند. (عمل AA)
  • کاری می کند که فایل file به etc/passwd/ اشاره کند (Symbolic Link). (عمل AB)

برنامه اصلی نیز مجوز کاربر اصلی (uid) را برای نوشتن در tmp/file/ چک کرده (VA) و فایل را باز می کند (VB).
طبیعی است که برنامه مهاجم به صورت …, AA, AB, AA, AB و برنامه اصلی به صورت …, VA, VB, VA, VB اجرا می شود. اما دنباله واقعی به این تمیزی نیست! اگر دو برنامه روی کامپیوتر چند پردازنده اجرا شوند به دلیل وجود چند پراسس دنباله های بالا تلفیق می شوند (روی تک پردازنده هم به دلیل Context Switch) چنین اتفاقی رخ می دهد. واقعیت این است که دنباله های متفاوتی قابل پیدایش هستند اما همانطور که واضح است دنباله مورد نظر ما (مهاجم) AA, VA, AB, VB می باشد. اگر موفق شویم به این دنباله دست یابیم فایل etc/passwd/ باز می شود و می توان در آن نوشت! این یک رخنه امنیتی است.

سخن پایانی

در این مقاله از سری مقالات امنیت نرم افزار آکادمی ترجنس راجع به Race Condition و یکی از انواع آسیب پذیری های Race Condition به نام TOCTTOU صحبت کردیم. همانطور که گفتیم آسیب پذیری های متعددی در قالب Race Condition وجود دارند که در مقاله های بعدی آن ها را نیز بررسی می کنیم و همچنین سناریو کامل اکسپلویت این مقاله و مقالات بعدی را به صورت کد قرار می دهیم.

درباره ما

ترجنس | thregence.ir
آکادمی ترجنس | edu.thregence.ir
دوره‌های آکادمی ترجنس | courses.thregence.ir
اینستاگرام | instagram.com/thregence
تلگرام | t.me/thregence
یوتوب | https://bit.ly/30mGowo
آپارات | aparat.com/thregence

ارسال یک پاسخ