پرش به محتوای اصلی

Firecracker VM Escape: PwnEscape قسمت 2

هکرنیوز۱۴۰۵ آبان ۱۵, جمعه، ساعت ۲۳:۰۳حدود 10 دقیقه مطالعه

آدرس مقاله: https://pwn.ai/blog/firecracker-escape آدرس نظرات: https://news.ycombinator.com/item?id=50397219 امتیاز: 258 # نظرات: 110

Firecracker قرار است کدهای غیرقابل اعتماد را در داخل microVM نگه دارد. ما از آن فرار کردیم و به اجرای کد به عنوان root در هاست دست یافتیم.

ما متوجه شدیم که چگونه رجیسترها را ذخیره می‌کند، جایی که از سر گرفته می‌شود را تغییر می‌دهد، و زمانی که از KVM برمی‌گردد، آن را وادار به اجرای فراخوانی دلخواه ما کردیم. سپس مهمان تغییرات موقت پشته را بازیابی کرد. Firecracker به کار خود ادامه داد و VM از طریق SSH در دسترس باقی ماند.

PwnEscape Part 1 ابتدا حافظه میزبان را در پشت این کار معرفی کرد. در اینجا قسمت بعدی زنجیره را دنبال می کنیم: استفاده از آن دسترسی برای یافتن Firecracker در حافظه و گرفتن یک رشته زنده از داخل مهمان. این ادامه نمایش CVE-2026-99999 در راه اندازی Firecracker است.

یک MicroVM Firecracker دارای یک فرآیند روی میزبان است که آن را مدیریت می کند. هر CPU مجازی یا vCPU یک رشته در آن فرآیند دارد. این موضوع برای اجرای مهمان وارد KVM می شود و زمانی که رویدادی نیاز به مدیریت در فضای کاربر داشت به Firecracker برمی گردد. Firecracker این ترتیب را در نمای کلی معماری خود مستند می کند.

فراخوانی که CPU مجازی را اجرا می کند به صورت زیر است:

در حالی که thread در آن فراخوانی سیستم است، هسته میزبان رجیسترهای فضای کاربری ذخیره شده خود را در ساختاری به نام pt_regs نگه می دارد. این رجیسترها رشته Firecracker را توصیف می‌کنند: نشانگر دستورالعمل آن می‌گوید که اجرا باید کجا از سر گرفته شود، و نشانگر پشته آن می‌گوید از کدام پشته فضای کاربر باید استفاده کند.

که بازگشت از KVM_RUN را به یک هدف جذاب تبدیل کرد. اگر می‌توانستیم قاب ذخیره‌شده را پیدا کرده و آن را تغییر دهیم، می‌توانیم کد Firecracker را که هنگام بازگشت رشته به فضای کاربر اجرا می‌شود، انتخاب کنیم. یک عملیات مهمان که باعث چنین بازگشتی می شود، ماشه را فراهم می کند.

ما قبلا از طریق نقشه برداری مهمان به حافظه فیزیکی میزبان انتخاب شده دسترسی داشتیم. برای استفاده از آن، باید فرآیند Firecracker را شناسایی کنیم، کدی را که می‌توانیم در آن فرآیند فراخوانی کنیم، پیدا کرده و فریم ثبت متعلق به رشته vCPU فعال آن را پیدا کنیم. نقطه شروع یک صفحه خاطره بود که در داخل مهمان کنترل می کردیم.

شکل 1. مهمان فرآیند Firecracker خود را شناسایی می کند، رجیسترهای ذخیره شده برای یک رشته vCPU را پیدا می کند، و زمانی که رشته از KVM برمی گردد، آن را تغییر مسیر می دهد.

مهمان و میزبان از فضاهای آدرس فیزیکی متفاوتی استفاده می کنند. یک صفحه دارای یک آدرس فیزیکی مهمان یا GPA در داخل ماشین مجازی و یک آدرس فیزیکی میزبان یا HPA در دستگاه پشتیبان آن است. در مورد هدف، جداول صفحه گسترده (EPT) ترجمه بین آنها را فراهم می کند.

ما یک الگوی بایت قابل تشخیص، یک nonce، در یک صفحه مهمان قرار دادیم. اولین تحلیلگر معدل شناخته شده آن صفحه و محتویات آن را به عنوان ورودی در نظر گرفت. آنها با هم آدرسی برای ترجمه و راهی برای بررسی اینکه آیا ترجمه به صفحه ما رسیده است به ما دادند.

حل‌کننده محدوده فیزیکی میزبان تحت پوشش حافظه اولیه را برای ریشه‌های EPT کاندید جستجو کرد. ریشه EPT نقطه شروع جداول ترجمه است. برای هر نامزد، حل‌کننده ورودی‌های انتخاب‌شده توسط آدرس مهمان را تا زمانی که به یک صفحه فیزیکی رسید، دنبال کرد، سپس آن صفحه را برای nonce بررسی کرد.

قطعه‌های زیر کد شبه توضیحی با نام‌های کمکی توصیفی هستند. آنها داده های ارسال شده بین مراحل و بررسی های مورد استفاده برای اتصال آنها را نشان می دهند.

بررسی nonce یک ترجمه پیشنهادی را به حافظه ای که کنترل می کردیم متصل کرد. جست و جوی گسترده تر دو نامزد ایجاد کرد. اعتبار سنجی جداول صفحه تو در تو آنها را به یک ریشه EPT کاهش داد. با قدم زدن در این ریشه، آدرس فیزیکی میزبان صفحه مهمان به ما داده شد.

ما این نتیجه را guest_page_hpa نامیدیم و آن را به حل کننده بعدی ارسال کردیم. ما اکنون یک شی قابل تشخیص در حافظه میزبان داشتیم. وظیفه بعدی یافتن فرآیند میزبانی بود که آن را ترسیم کرد.

Firecracker حافظه استفاده شده توسط مهمان را در فضای آدرس خود نقشه می‌کشد. این نگاشت راهی را به ما داد تا از صفحه مهمان تا فرآیند به عقب کار کنیم.

فرآیندهای میزبان از جداول صفحه برای ترجمه آدرس های مجازی خود به حافظه فیزیکی استفاده می کنند. سطح بالا فهرست جهانی صفحه یا PGD نامیده می شود. بازیابی PGD مناسب به ما این امکان را می دهد که آدرس های داخل Firecracker را ترجمه کرده و کد آن را بخوانیم و در حافظه اولیه ذخیره کنیم.

نگاشت معکوس ما جداول صفحه میزبان بومی را برای نگاشت guest_page_hpa جستجو کرد. یک پیاده روی معمولی در جدول صفحه با یک آدرس مجازی شروع می شود و یک آدرس فیزیکی تولید می کند. در اینجا، ما به دنبال نگاشت یک صفحه فیزیکی که قبلا می‌شناختیم، گشتیم، سپس آدرس مجازی و ریشه جدول صفحه مرتبط با آن را بازیابی کردیم.

این نگاشت مجازی فرآیند میزبان را به صفحه فیزیکی یافت شده از طریق EPT متصل کرد. نگاشت معکوس یک فضای آدرس معتبر را برگرداند. ما ریشه آن را به عنوان host_pgd حفظ کردیم و از آن برای بررسی فرآیند استفاده کردیم.

حل‌کننده بعدی به دنبال فایل اجرایی Firecracker در آن نقشه‌برداری‌ها بود. یک تصویر ELF را شناسایی کرد و یک توالی بایت شناخته شده را در Wrapper Write(2) Firecracker بررسی کرد. که فضای آدرس بازیابی شده را به باینری مورد نظر ما متصل می کند.

ASLR در جایی که یک فایل اجرایی بارگذاری می شود تغییر می کند. تفاوت بین یک آدرس در تصویر ELF و آدرس زمان اجرا متناظر آن، بایاس بار است. هنگامی که نقشه‌بردار تصویر را شناسایی کرد، می‌توانست آن سوگیری را بازیابی کند و از آن برای مکان‌یابی کد مورد نیاز اکسپلویت استفاده کند:

نقشه‌بردار بایاس بار را به عنوان firecracker_base برگرداند. با این مقدار و host_pgd، می‌توانیم کد را در فرآیند در حال اجرا پیدا کنیم، آدرس مجازی آن را به حافظه فیزیکی میزبان ترجمه کنیم و بایت‌های موجود در آنجا را با دودویی مورد انتظار مقایسه کنیم.

ما سه مکان را بررسی کردیم: wrapper write(2) که اثبات ما را ایجاد می‌کند، ادامه بعد از KVM ioctl، و یک xor eax,eax کوتاه. دنباله ret مورد نیاز برای بازگشت تمیز است. اهداف آنها زمانی مرتبط می شود که مسیر بازگشت را در زیر بسازیم.

در این مرحله، مهمان می‌تواند تصویر Firecracker و نقشه‌های خصوصی آن را بررسی کند. ما هنوز به رجیسترهای ذخیره شده موضوعی که در حال حاضر VM ما را اجرا می کند نیاز داریم.

شکل 2. nonce صفحه مهمان را در حافظه میزبان مشخص می کند. نگاشت آن به ریشه جدول صفحه میزبان منتهی می شود، که به حل کننده بعدی اجازه می دهد تصویر Firecracker را بیابد و اعتبار سنجی کند.

فریم یاب host_pgd و firecracker_base را از مراحل قبل گرفت. از آنها برای تشخیص وضعیت ذخیره شده رشته میزبان استفاده می کرد.

مفیدترین سرنخ آدرس برگشت بود. یک رشته vCPU در KVM_RUN باید یک نشانگر دستورالعمل ذخیره شده در ادامه ioctl مربوطه در Firecracker داشته باشد. ما می‌توانیم آن آدرس را از روی باینری معتبر و بایاس بار آن محاسبه کنیم.

سپس حافظه میزبان را برای یک قاب pt_regs که با آن فراخوانی سازگار است جستجو کردیم. یک تطابق آدرس به تنهایی محتویات پشته قدیمی را نیز انتخاب می کند، بنابراین نامزد باید چندین بررسی مرتبط را انجام می دهد:

چک پشته قاب را به همان فضای آدرسی که از صفحه مهمان بازیابی کرده بودیم گره زد. دستورالعمل و آدرس تماس گیرنده آن را به تصویر Firecracker گره زدند. فیلدهای syscall آن را به عملیات اجرای vCPU گره زدند.

جست و جو یک نامزد باقی گذاشت. مکان آن به‌عنوان frame_hpa، آدرس فیزیکی میزبان قاب ثبت‌شده ذخیره‌شده، ذخیره شد. ما آن را، PGD، و بایاس بار را به کمک کننده نهایی منتقل کردیم.

قبل از تغییر حافظه، کمک کننده چک امضای کد، قاب و پشته را تکرار کرد. این اطمینان حاصل کرد که مرحله فعال از همان حالت فرآیندی استفاده می کند که حل کننده ها شناسایی کرده بودند. بررسی‌های اجرا و بازیابی بعدی نشان می‌دهد که فریم انتخابی فعال است.

شکل 3. قاب ثبت نامزد باید با KVM ioctl، جداول صفحه فرآیند بازیابی شده و کد Firecracker معتبر مطابقت داشته باشد.

ما یک بار ساده انتخاب کردیم: فرآیند Firecracker را بنویسید که یک رشته قابل تشخیص در stderr خودش بنویسد. این به دونده میزبان نتیجه قابل مشاهده ای از فرآیندی که ما در پیش گرفته بودیم می دهد.

رشته N8V23M2\n بود، هفت کاراکتر و یک خط جدید به دنبال آن. هشت بایت را اشغال می کند و در یک کلمه پشته قرار می گیرد. تماسی که می‌خواستیم Firecracker اجرا کند این بود:

در اینجا 2 توصیفگر فایل stderr Firecracker است. نشانگر بافر باید به رشته در فضای آدرس Firecracker اشاره کند، بنابراین ما رشته را در پشته فضای کاربر خصوصی آن ذخیره کردیم.

ما سه کلمه پشته را قبل از اصلاح آنها ذخیره کردیم. یکی ریسمان را نگه داشت. دو نفر دیگر آدرس های برگشتی را برای توالی تماس موقت نگه داشتند. سپس قاب رجیستر ذخیره شده را تغییر دادیم تا آدرس wrapper، آرگومان های آن و یک اشاره گر پشته برای آن دنباله را ارائه کنیم:

بازگشت از نوشتن نیز نیاز به مراقبت داشت. نوشتن موفقیت آمیز هشت بایت 8 را برمی گرداند، در حالی که یک فراخوان موفق KVM_RUN صفر را برمی گرداند. ما آدرس xor eax,eax را قرار دادیم. ret ابتدا در دنباله بازگشت. قبل از اینکه آدرس دوم اجرا را به ادامه ioctl اصلی Firecracker برگرداند، مقدار بازگشتی را پاک می کند.

با آماده شدن پشته و رجیسترهای ذخیره شده، مهمان یک بایت به پورت سریال خود نوشت. این عملیات باعث شد تا رشته vCPU از KVM_RUN بازگردد. هسته رجیسترهای اصلاح شده را بازیابی کرد و Firecracker با آرگومان های ما وارد wrapper نوشتن شد.

Wrapper نشانگر را ساطع کرد، دنباله بازگشت eax را پاک کرد، و نخ دوباره به مسیر اجرای اصلی خود پیوست. پس از بازگشت کنترل به مهمان، کمک کننده هر سه کلمه پشته را بازیابی کرد.

شکل 4. قاب ثبات ذخیره شده وارد wrapper نوشتن می شود. دو آدرس بازگشتی از طریق تنظیم مقدار بازگشتی و بازگشت به مسیر Firecracker اصلی منتهی می‌شوند.

دونده میزبان، stderr Firecracker را جدا از مهمان گرفت. خروجی کامل این بود:

ضبط دقیقا شامل هشت بایت، از جمله خط جدید نهایی بود. Firecracker هنوز در حال اجرا بود، SSH مهمان پاسخگو بود و کمک کننده سه کلمه پشته موقت را بازیابی کرده بود.

ما ریکاوری را با یک پاس جدید بررسی کردیم که هیچ تغییری در حافظه ایجاد نکرد. آدرس فریم یکسانی به آن داده شد و پس از تریگر، رجیستر، کد و بررسی پشته را تکرار کرد. بررسی‌ها انجام شد و هیچ نشانگری کهنه در محل پشته موقت پیدا نشد.

این مشاهدات به سه سوال مختلف پاسخ داد. گزارش مهمان ماشه و بازیابی را ثبت کرد. ضبط میزبان نشان داد که Firecracker عملیات انتخاب شده را اجرا کرد. اعتبار سنجی نهایی وضعیت پس از اجرا را بررسی کرد.

شکل 5. گزارش مهمان، ضبط Firecracker stderr، و اعتبار سنجی نهایی، ماشه، اجرای میزبان و حالت بازیابی را ثبت می کند.

تا زمانی که نشانگر ظاهر شد، مهمان نشانگر دستورالعمل رشته میزبان، آرگومان های تابع، داده های پشته و مسیر بازگشت را انتخاب کرده بود. Firecracker تماس را با استفاده از امتیازات خود اجرا کرد.

هدف Firecracker نسخه 1.16.1 در x86-64، با هسته میزبان 7.0.0-1011-aws و هسته مهمان 6.18.44+ بود. ما Firecracker را مستقیما به عنوان root تحت systemd-run راه‌اندازی کردیم و آن را با مجموعه وظایف پین کردیم. در نتیجه، فراخوانی کنترل شده به صورت روت روی هاست اجرا می شود.

Wrapper Write موجود، اثبات فشرده ای از آن کنترل را به ما داد. گسترش آن به فراخوانی های دیگر مستلزم انتخاب کد و آرگومان های سازگار با نگاشت های فرآیند و خط مشی syscall است.

پیکربندی مورد استفاده در اینجا فاقد jailer بود. مهار تولید Firecracker شامل حذف امتیازات و محدود کردن فرآیند از طریق فضاهای نام و seccomp است. استقرار با استفاده از این کنترل ها مستلزم ارزیابی جداگانه امتیازات و منابع موجود پس از به خطر انداختن VMM است.

کشف آدرس چیزی است که به اکسپلویت اجازه می دهد نمونه در حال اجرا را دنبال کند. حل کننده EPT یک صفحه مهمان را به حافظه میزبان متصل می کند. نگاشت معکوس فضای آدرس میزبان را بازیابی می کند. نقشه‌بردار تصویر Firecracker را در زیر ASLR قرار می‌دهد. و فریم یاب وضعیت ذخیره شده vCPU را شناسایی می کند. تطبیق مرحله نهایی با ساخت دیگری مستلزم تأیید اعتبار امضاهای کد باینری و مسیر بازگشت است.

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

مقادیر زیر از رکورد اجرای حفظ شده می آیند. روش های فوق از نام های نمادین استفاده می کنند تا نقش هر مقدار مشخص باشد. این جدول آن نام ها را به آدرس های ضبط شده متصل می کند.

رکوردها از run ID eventpath-v23-0907self02 و Boot ID 2b3cd5ac-2311-427f-a50a-6a79ecb8daa7 استفاده می کنند. این شناسه‌ها رکوردهای حل‌کننده، ضبط میزبان و اعتبارسنجی را پس از بازیابی به هم متصل می‌کنند.

ارائه‌دهنده حافظه قبلی نیز پس از ساخت دیافراگم حافظه، اعداد قاب صفحه قناری و وظایف انتخاب شده توسط میزبان را به‌عنوان پوشش‌های اعتبارسنجی مستقل دریافت کرد. این آدرس‌ها توسط حل‌کننده EPT، نقشه‌برداری معکوس، نقشه‌بردار Firecracker، یاب قاب یا کمک‌کننده نشانگر نهایی مصرف نشده‌اند.

بسته انتشار حاوی منبع کمکی نهایی، سوابق حل‌کننده JSONL، ضبط میزبان، مانیفست بازیابی، چهار باینری حل‌کننده فقط خواندنی با منشأ، و مانیفست SHA-256 است. کمک کننده نهایی PGD، بار بایاس و فریم HPA تولید شده توسط حل کننده ها را می پذیرد. چک های آن شناسه اجرا، محدوده آدرس، امضای کد، ثبت های ذخیره شده و هندسه پشته را پوشش می دهد. حالت خشک آن بدون حافظه نوشتن اعتبار سنجی را انجام می دهد.

خواندن متن کامل در هکرنیوزبه زبان اصلی، در سایت ناشر باز می‌شود
متن اصلی (انگلیسی)

Firecracker VM Escape: PwnEscape Part 2

Article URL: https://pwn.ai/blog/firecracker-escape Comments URL: https://news.ycombinator.com/item?id=50397219 Points: 258 # Comments: 110

همه‌ی اخبار فناوری