یه آسیب پذیری به شناسه CVE-2023-43641 در کتابخونه libcue کشف و گزارش شده، که امکان اجرای کد در سیستم های لینوکسی که از GNOME استفاده میکنن رو، میده.
libcue یه کتابخونه هستش که برای تجزیه ی cue sheetها مورد استفاده قرار میگیره. خود cue sheet یسری متادیتا هستن که برای طرح بندی ترک های روی CD مورد استفاده قرار میگیره و معمولا در فرمت فایل صوتی FLAC استفاده میشه. در حقیقت میشه گفت که کتابخونه libcue یکی از dependency های برنامه های پخش موزیک مانند Audacious هستش.
اما دلیلی که باعث شده محقق، این کتابخونه رو مورد ارزیابی قرار بده، استفاده اون توسط tracker-miners هستش. برنامه ای که همراه با GNOME ارائه میشه و همونطور که میدونید، GNOME محیط پیش فرض دسکتاپهای گرافیکی در اغلب سیستم عاملهای متن باز هستش.
هدف استفاده از tracker-miners در GNOME اینه که، فایلهارو در دایرکتوری HOME ایندکس میکنه تا راحتتر قابل جستجو باشن. مثلا این اندکس کردن در نوار جستجوی زیر قابل استفاده هستش :
وقتی فایلی رو در زیرشاخه های دایرکتوری Home اضافه یا دستکاری میکنید، از جمله Downloads، این ایندکس بطور خودکار بروزمیشه.
بطور خلاصه این آسیب پذیری همونطور که در ویدیوی زیر هم قابل مشاهده هستش، اینجوریه که شما یه فایل cue sheet که فرمت cue داره رو از اینترنت دانلود میکنید و این فایل در فولدر Downloads قرار میگیره. قرار گرفتن در این فولدر باعث میشه که tracker-miners بصورت خودکار، شروع به اسکن کنه. چون فرمت فایل cue هستش، بنابراین tracker-miners ، از کتابخونه libcue برای تجزیه فایل استفاده میکنه. چون این کتابخونه هم دارای آسیب پذیری memory corruption هستش، امکان اجرای کد دلخواه رو میده که در این ویدیو، ماشین حساب رو اجرا میکنه. در حقیقت مهاجم با فریب کاربر برای دانلود یه فایل و اجرای اون توسط قربانی میتونه کد دلخواه در سیستم قربانی اجرا کنه، برای همین بهش One-Click RCE میگن.
نکته ای که وجود داره ، Cue sheetها یکی از فرمتهای فایلی هستن که توسط tracker-miners پشتیبانی میشه و فرمتهایی مانند HTML ، JPEG و PDF هم پشتیبانی میشن.
محقق فعلا PoC رو منتشر نکرده تا کاربران بتونن زمان کافی برای بروزرسانی رو داشته باشن، اما یه PoC ساده منتشر کرده که اجرای اون منجر به کرش سیستم میشه و باهاش میتونید متوجه بشید که تحت تاثیر هستید یا نه.
برای استفاده از PoC اصلی نیاز به دستکاری آفست ها داریم. محقق PoC رو روی Ubuntu 23.04 و Fedora 38 توسعه و تست کرده و جواب گرفته. اگه PoC روی توزیع مناسب اجرا بشه، جواب میده و اگه نه، SIGSEGV میده. محقق گفته به غیر از این دو مورد ، روی توزیع دیگه ای ، PoC رو توسعه نداده، اما معتقده که سیستم هایی که از گنوم استفاده میکنن، میتونن تحت تاثیر آسیب پذیری قرار بگیرن.
باگ کتابخونه libcue :
کتابخونه libcue ، یه پروژه کوچیکه که ، در درجه اول یه گرامر bison برای cue sheet ها ، بهمراه چند ساختار داده ای برای ذخیره ی داده های تجزیه شده هستش. یه نمونه از cue sheet رو در زیر مشاهده میکنید :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
REM GENRE "Pop, dance pop" REM DATE 1987 PERFORMER "Rick Astley" TITLE "Whenever You Need Somebody" FILE "Whenever You Need Somebody.mp3" MP3 TRACK 01 AUDIO TITLE "Never Gonna Give You Up" PERFORMER "Rick Astley" SONGWRITER "Mike Stock, Matt Aitken, Pete Waterman" INDEX 01 00:00:00 TRACK 02 AUDIO TITLE "Whenever You Need Somebody" PERFORMER "Rick Astley" SONGWRITER "Mike Stock, Matt Aitken, Pete Waterman" INDEX 01 03:35:00 |
باگ در سینتکس INDEX هستش. اگه عبارت زیر رو در INDEX استفاده کنیم، باگ فعال میشه :
1 |
INDEX 4294567296 0 |
مشکل از دو بخش تشکیل شده. یکی اینکه اسکنر cue ، از atoi برای اسکن integerها استفاده میکنه :
1 |
[[:digit:]]+ { yylval.ival = atoi(yytext); return NUMBER; } |
atoi آسیب پذیری integer overflow رو بررسی نمیکنه و در نتیجه میشه یه index منفی ایجاد کرد، مثلا 4294567296 توسط atoi ، به -400000 تبدیل میشه.
مشکل دوم که در حقیقت قسمت اصلی آسیب پذیری هستش، اینه که track_set_index بررسی نمیکنه که i ≥ 0 باشه :
1 2 3 4 5 6 7 8 9 |
void track_set_index(Track *track, int i, long ind) { if (i > MAXINDEX) { fprintf(stderr, "too many indexes\n"); return; } track->index[i] = ind; } |
اگه مقدار i منفی باشه، کد میتونه خارج از محدوده آرایه بنویسه. با توجه به اینکه ind هم تحت کنترل مهاجم هستش، بنابراین آسیب پذیری میتونه قدرتمند باشه.
اصلاح آسیب پذیری هم با اضافه کردن یه if ، میتونه به شکل زیر انجام بشه :
1 2 3 4 5 6 7 8 9 10 11 12 13 |
diff --git a/cd.c b/cd.c index cf77a18..4bbea19 100644 --- a/cd.c +++ b/cd.c @@ -339,7 +339,7 @@ track_get_rem(const Track* track) void track_set_index(Track *track, int i, long ind) { - if (i > MAXINDEX) { + if (i < 0 || i > MAXINDEX) { fprintf(stderr, "too many indexes\n"); return; } |
آشنایی بیشتر با tracker-miners :
محقق اعلام کرده که این آسیب پذیری در حقیقت روی tracker-miners نیست. اما روی tracker-miners کار کرده چون بطور خودکار فولدر Downloads رو اسکن میکنه و این میتونه تاثیر آسیب پذیری رو بیشتر کنه.
tracker-miners از دو پروسس تشکیل شده :
- tracker-miner-fs
- tracker-extract
tracker-miner-fs همیشه در بکگراند، در حال اجراست و tracker-extract وقتی درخواستی برای اسکن باشه، اجرا میشه. tracker-miner-fs از inotify برای مونیتورینگ فولدرهای خاصی مانند Downloads ، Music و Videos استفاده میکنه. وقتی یه فایل جدید ایجاد میشه اون، tracker-extract رو برای اسکن اجرا میکنه. بعد از اسکن ، tracker-extract نتایج رو به tracker-miner-fs ارسال میکنه و بعد از چند ثانیه، اجراش متوقف میشه.
آسیب پذیری همونطور که حدس زدید، روی tracker-extract تاثیر میزاره، چون در اون ، libcue اجرا میشه. با توجه به اینکه هر دو پروسس با امتیاز کاربر جاری اجرا میشن، بنابراین باید با یه آسیب پذیری افزایش امتیاز زنجیر بشن تا امکان اجرای کد با امتیاز بالا رو داشته باشه.
اگه tracker-miners اجرا نشه، آسیب پذیری فعال نمیشه. برای اینکه بررسی کنید، در حال اجراست یا نه از دستور زیر استفاده کنید :
1 |
ps aux | grep track |
خروجی دستور معمولا نشون دهنده ی اجرای tracker-miner-fs هستش و نه tracker-extract . اگه در خروجی هیچکدوم در حال اجرا نبودن که البته نادره، در نوار جستجو عبارتی رو تایپ کنید، تا tracker-miner-fs بصورت خودکار راه اندازی بشه. محقق گفته که tracker-miners با گنوم ادغام شده و بنابراین راهی برای متوقف کردنش وجود نداره. البته اینجا روشی رو برای توقف اون با دستکاری systemd ارائه داده.
معماری دو پروسسی tracker-miners برای اکسپلویت آسیب پذیری مفیده:
- اولا بررسی حافظه برای پروسسی که تازه شروع به اجرا کرده، نسبت به پروسسی که ساعتها در حال اجراست ساده تره. بنابراین با توجه به اینکه tracker-extract براساس تقاضا اجرا میشه، میتونه بررسی رو ساده تر کنه. جالبتر اینکه ، tracker-extract همیشه برای اسکن فایلهای دانلود شده، یه thread جدید میسازه که قالب بندی heapاش در malloc این thread ، همیشه یکسانه. البته برای توزیعهای مختلف متفاوته. مثلا این قالب بندی هیپ، در Ubuntu 23.04 و Fedora 38 یکمی متفاوت هستش اما در هر توزیع یکسانه.
- دوما ، با توجه به اینکه tracker-extract در صورت نیاز اجرا میشه، بنابراین مهاجم میتونه اونو چندین بار اجرا کنه تا در نهایت اکسپلویتش کنه. البته با توجه به اینکه فرمت هیپ یکسانه ، اکسپلویت از قابلیت اعتماد بالایی برخوداره اما مهاجم میتونه چندین فایل مخرب حاوی اکسپلویت رو در یه فایل فشرده قرار بده، تا شانس اجراش رو بالا ببره.
استفاده tracker-extract از سندباکس seccomp :
سختترین بخش اکسپلویت این آسیب پذیری، دور زدن ASLR هستش. اما محقق وقتی داشته PoC رو توسعه میداده، متوجه شده که tracker-extract از سندباکس seccomp استفاده میکنه که از اجرای این اکسپلویت جلوگیری میکنه.
محقق وقتی داشته روی PoC کار میکرده، خطای Disallowed syscall “close_range” caught in sandbox رو دریافت میکنه بنابراین رفته یه مسیر دیگه ای رو انتخاب کرده تا درگیر تابع close_range نشه در نتیجه بدون اینکه بدونه تونسته این سندباکس رو هم دور بزنه. دور زدن رو هم وقتی فهمیده که توسعه دهندگان گنوم ازش پرسیدن که چطوری سندباکس دور زدی؟ متوجه شده. بنابراین کلا دور زدن سندباکس رو بصورت تصادفی کشف کرده.
این آسیب پذیری منجر به اصلاح سندباکس توسط Carlos Garnacho هم شده که این مسیر اکسپلویت رو اصلاح کرده تا در آینده قابل سوء استفاده نباشه.