Berputar tanpa henti: Bug kecil yang bisa

Wanita muda terlihat kontemplatif saat dia bekerja di komputer di malam hari.

Bug kecil yang bisa: CVE-2024-30089 adalah kerentanan kernel halus yang saya gunakan untuk mengeksploitasi mesin Windows 11 yang diperbarui sepenuhnya (dengan semua Keamanan Berbasis Virtualisasi dan mitigasi keamanan perangkat keras diaktifkan) dan mencetak kemenangan pertama saya di Pwn2Own tahun ini.

Dalam artikel ini, saya menguraikan pendekatan sederhana saya dalam berburu bug: memilih titik awal dan secara intuitif mengikuti suatu jalur hingga sesuatu menarik perhatian saya. Bug ini menarik karena dapat dipicu dengan andal karena kesalahan logika. Kesalahan terjadi pada kondisi tertentu dalam sistem komunikasi antar-proses, yang kemudian menyebabkan bebas-penggunaan. Menemukan bug diperlukan membandingkan jalur kode program di berbagai kemungkinan statusnya, sebuah proses yang saya jelaskan secara rinci. Yang sama menariknya adalah asal bug dan pendekatan Microsoft untuk menambalnya. Topik-topik ini juga dibahas dalam posting ini.

Berburu selama 0 hari: Mulai dari mana?

Pertanyaan umum yang saya terima tentang riset kerentanan adalah bagaimana memulai. Bahkan, memilih target dan ber pegang teguh pada itu mungkin merupakan salah satu langkah paling sulit dari proses riset. Kerentanan yang dibahas di sini ada di Microsoft Kernel Streaming Service (mskssrv.sys). Lihat postingan blog ini untuk mendapatkan gambaran umum mengenai subsistem. Dalam posting itu, saya menunjukkan beberapa karakteristik subsistem MSKSSRV yang mungkin menjadikannya permukaan serangan yang baik, khususnya mekanisme komunikasi antar-proses (IPC).

Basis kode MSKSSRV cukup kecil, dan kerentanan terakhir dalam subsistem ini yang saya temukan juga dieksploitasi secara independen di alam liar sebagai 0-hari. Saya juga mendengar tentang upaya tambahan dari peneliti dan perusahaan lain untuk mengaudit driver ini. Karena itu, saya awalnya jatuh ke dalam perangkap umum dengan mengasumsikan tidak ada lagi bug yang tersisa untuk ditemukan di permukaan serangan ini. Tapi, karena saya telah menyarankannya di postingan blog saya sebelumnya, saya memilih untuk mempercayai naluri saya dan terus mencari.

Kunci kunci: Siapa itu?

Cara yang bagus untuk mendapatkan ide-ide riset baru adalah dengan tetap mendapat informasi tentang riset saat ini. Saya membaca sebuah postingan blog yang luar biasa dari k0shl yang memicu inspirasi untuk berburu jenis serangga tertentu. Dalam kerentanan yang ditemukan oleh k0shl, jumlah referensi objek diinisialisasi dan ditingkatkan tanpa penguncian yang tepat, menciptakan use after free window. Meskipun bug k0shl adalah bug userland dan bukan di kernel, pengodean perpustakaan yang rentan mengingatkan saya ketika saya sebelumnya mengaudit driver MSKSSRV.

MS KS Server (MSKSSRV) berinteraksi dengan proses userland melaluiFSStreamReg dan benda FSContextReg . FSStreamReg dan FSContextReg keduanya berasal dari kelas dasarFSRegObject . Saya perhatikan bahwa FSContextReg tidak mengimplementasikan fungsi penguncian vtable, dan implementasi kelas dasar (FSRegObject ) diimplementasikan dengan sebuah instruksi nop. Ini berarti tidak ada mekanisme penguncian yang benar-benar diterapkan untuk objek FSContextReg . Sebaliknya,FSStreamReg mengimplementasikan fungsi penguncian yang menggunakan mutex. Mekanisme penguncian digunakan saat mengakses objek untuk pembersihan, dalam fungsiFSRendezvousServer::Close :

Tangkapan layar fungsi FSRendezvousServer::Close

Blok Kode 1: FSRendezvousServer::Close, mengunci dan membuka jalur untuk FSRegObjects

Ada dua objek yang berasal dari kelas dasar FSRegObject  , tetapi satu tipe objek mengimplementasikan mekanisme penguncian yang tepat dan yang lainnya tidak. Ini mencurigakan bagi saya. Untuk menguji teori saya, saya mencoba memicu perilaku tidak terdefinisi menggunakan referensi ke objek FSContextReg yang tidak terlindungi. Namun, karena perlindungan penguncian pada FSRendezvousServer  global objek, yang menyimpan pointer ke daftar FSRegObjects , saya tidak bisa memicu sesuatu yang menarik, meskipun kurangnya perlindungan kunci pada benda FSContextReg  . Namun, saya bisa merasakan ada sesuatu yang “mencurigakan” tentang sistem penghitungan referensi untuk FSRegObjects  .Aku hanya belum tahu apa.

IPC di server MS KS

Seperti yang saya sebutkan di posting blog terakhir saya, aspek berbagi objek antar-proses dari MSKSSRV adalah jalan yang menarik untuk kerentanan, jadi saya memutuskan untuk fokus lebih lanjut. Mekanisme IPC dari subsistem diilustrasikan dalam diagram berikut:

Diagram mekanisme IPC subsistem

Diagram 1: Komunikasi Antar Proses di MS KS Server

Membuka handle file ke perangkat MSKSSRV, melalui CreateFile, akan membuat FILE_OBJECT yang sesuai dengan handle tersebut. Dengan menggunakan handle tersebut, sebuah proses dapat menginisialisasi stream baru atau objek konteks dengan mengirimkan IOCTL ke perangkat menggunakan fungsi DeviceIoControl . Proses inisialisasi menentukan proses jarak jauh mana yang dapat mendaftarkan objek dengan menentukan ID proses melalui argumenlpInBuffer . Proses jarak jauh, menggunakan pegangan file baru ke perangkat MSKSSRV, sekarang dapat mendaftarkan objek melalui perangkat IOCTL. Penunjuk untuk FSRegObject disimpan di

Irp->CurrentStackLocation->FileObject->FsContext2.

Penunjuk yang sama ke objek FSRegObject disimpan dua kali di FsContext2, sekali di FILE_OBJECT yang digunakan oleh proses inisialisasi dan sekali di FILE_OBJECT digunakan oleh proses pendaftaran. Dengan cara ini, referensi ke objek FSRegObject dapat dibagikan di seluruh proses. Misalnya, menggunakan objek FSStreamReg, beberapa proses dapat memiliki akses ke buffer bingkai aliran, seperti yang ditunjukkan pada Diagram 1. Jumlah referensi pada FSRegObject awalnya diset ke 1 lalu bertambah sekali lagi setelah tahap inisialisasi selesai. Mendaftarkan FSRegObject meningkatkan jumlah referensi lagi, untuk total tiga referensi per objek.

Diagram Inisialisasi dan Mendaftarkan Objek FSContextReg

Diagram 2: Menginisialisasi dan Mendaftarkan Objek FSContextReg

Menemukan bug

Saya memutuskan untuk melihat lagi di mana saya sebelumnya mengaudit mencoba mencari kerentanan penguncian. Saya perhatikan fungsi FSRendezvousClose, yang memanggil FSRendezvousServer::Close , dipanggil dalam rutinitas fungsi pembersihan dan penutupan pengiriman driver:

Tangkapan layar CodeBlock dengan rutinitas DispatchCleanup dan DIPatchCleanup untuk MS KS Server Driver

Blok Kode 2: Rutinitas DispatchCleanup dan DIPatchCleanup untuk Driver Server MS KS

Sebuah rutinitas dispatch menangani satu atau lebih jenis IRP, yaitu permintaan I/O yang telah dikemas. Di Windows, ketika semua referensi handle ke file telah ditutup, driver sistem file yang sesuai untuk file tersebut menerima IRP_MJ_CLEANUP  dan permintaan IRP_MJ_CLOSE  , yang ditangani oleh rutinitas fungsi DispatchCleanup dan DispatchClose driver.

Dalam MSKSSRV, FSRendezvousClose  dipanggil dalam rutinitas fungsi DispatchCleanup dan DispatchClose driver, jika pointer disimpan di Irp->CurrentStackLocation->FileObject->FsContext2  bukan NULL. Sesuatu yang menonjol bagi saya di FSRendezvousServer::Close , yang telah saya analisis sebelumnya, adalah berbagai pemeriksaan pada ID proses penelepon. Konteks proses menjadi penting karena seluruh kode mode kernel berjalan dalam satu ruang alamat kernel yang bersifat tunggal, yang terpisah dari ruang alamat mode pengguna. Setiap proses memiliki konteks memori mode pengguna masing-masing, dan konteks proses tempat sebuah thread kernel dijalankan menentukan ruang alamat mode pengguna proses mana yang akan diakses ketika thread tersebut mengakses alamat pengguna. Kode berikut memeriksa apakah proses pemanggil merupakan proses yang melakukan inisialisasi atau pendaftaran:

Tangkapan layar fungsi FSRendezvousServer::Close

Blok Kode 3: FSRendezVousServer: :Close, Proses pemeriksaan pada FSRegObjects

Informasi spesifik proses disimpan dalam FSRegObject  yang disimpan di

 Irp->CurrentStackLocation->FileObject->FsContext2

 
pada saat inisialisasi atau pendaftaran. Driver menentukan mana yang memproses sumber daya tertentu (

EPROCESS

 objek, objek acara, dan hal-hal lain) perlu dilepaskan dengan memeriksa ID proses pemanggil. Jika prosesnya adalah proses inisialisasi atau pendaftaran, beberapa pembersihan tambahan dilakukan untuk sumber daya spesifik proses tersebut.

Hal ini menarik perhatian saya karena pada umumnya semua rutinitas Dispatch dijalankan dalam konteks proses arbitrary, dengan beberapa pengecualian. Dengan kata lain, sistem memilih utas untuk melakukan pekerjaan Dispatch ; utas apa yang dipilihnya secara acak. Saya menemukan bahwa DispatchCleanup  dipanggil dalam konteks proses yang menutup handle akhir. Jadi, dalam hal ini, pemeriksaan ID proses masuk akal. Artinya, jika, DispatchClose  dipanggil sebagai akibat dari permintaan  konteksproses yang berubah-ubah. Itu berarti bahwa jika FSRendezvousServer::Close  disebut sebagai hasil dari permintaan IRP_MJ_CLOSE  , itu akan berasal dari konteks proses yang sewenang-wenang, mengalahkan tujuan pemeriksaan ID proses. Ini adalah petunjuk besar bahwa ada sesuatu yang salah di sini.

Selain itu, sebagai fitur dari OS Windows, handle dapat dibagikan dengan proses lain (dengan pewarisan proses anak atau menggunakan fungsi API DuplicateHandle ). Melalui pegangan file bersama, proses lain juga dapat berinteraksi dengan FILE_OBJECT yang sama .

Diagram Berbagi Handle Perangkat Server MS KS

 Diagram 3: Berbagi Handle Perangkat Server MS KS

Karena ini, mungkin juga konteks proses selama  DispatchCleanup  bukan proses inisialisasi maupun proses pendaftaran. Jika salah satu dari handle tersebut diduplikasi dan dibagikan ke proses lain, dan proses itu adalah yang terakhir untuk menutup pegangan, DispatchCleanup  akan dipanggil dalam konteks proses asing itu (yang bukan proses inisialisasi atau pendaftaran).

Diagram Proses Asing Menutup Handle Terakhir ke FILE_OBJECT

Diagram 4: Proses Asing Menutup Handle Terakhir ke FILE_OBJECT

Saya perhatikan bahwa fungsi FSRendezvousServer::Close  dapat dipanggil dua kali ketika file handle ditutup (sekali untuk permintaan IRP_MJ_CLEANUP  dan sekali untuk permintaan IRP_MJ_CLOSE  , Blok Kode 2). Dalam fungsi itu ada dua kemungkinan panggilan ke FSRegObject::Release  (Blok Kode 4), yang menurunkan referensi objek dan membebaskan memorinya jika jumlah referensi turun menjadi 0. Itu berarti FSRegObject::Release  bisa dipanggil hingga empat kali untuk handle. Selain itu, ada dua handle file yang FILE_OBJECT  menunjuk ke FSRegObject yang sama melalui penunjuk FSContext2  . Itu berarti kemungkinan memanggil FSRegObject::Release  hingga delapan kali pada objek yang sama, empat untuk setiap handle. Jika jumlah referensi awal objek hanya tiga, maka terlalu banyak dereferensi dapat memicu kemungkinan terjadinya use-after-free. Lagipula, itulah cara berpikir saya. Saya tahu struktur program mungkin akan mencegah mencapai jumlah maksimum dereferensi teoretis, tetapi mungkin tidak cukup. Pada titik ini saya merasa saya sedang melakukan sesuatu dan memutuskan untuk menyelidiki hal ini lebih lanjut.

Tangkapan layar dari FSRegObject::Release dapat dipanggil dua kali dari FSRendezvousServer::Close

Blok Kode 4: FSRegObject: :Release dapat dipanggil dua kali dari fsRendezVousServer: :Close

Secara umum, lebih banyak dereferensi daripada referensi pada suatu objek bukanlah satu-satunya cara penggunaan setelah bebas dapat terjadi. Namun dalam hal ini, kita dapat yakin bahwa jika FSRegObject telah dibebaskan, jumlah referensi telah turun menjadi nol. Terakhir kali sebuah FSRegObject yang valid diakses selama IRP_MJ_CLEANUP/CLOSE Permintaan IRP adalah dalam panggilan ke FSRegObject::Release . Jadi, jika use-after-free dimungkinkan, panggilan ke FSRegObject::Release akan selalu terjadi setelah objek dibebaskan. Selama panggilan, objek akan sekali lagi didereferensikan. Untuk alasan itu, menghitung jumlah dereferensi adalah heuristik yang baik untuk menemukan penggunaan setelah bebas untuk kasus khusus ini.

Satu-satunya hal yang tersisa untuk dilakukan adalah melacak kemungkinan status program, mencatat kapan objek dibebaskan dan diakses. Saya melakukan ini dengan meniru logika program secara mental selama permintaan IRP_MJ_CLEANUP/CLOSE , masing-masing dimulai dengan fungsi Dispatch yang sesuai (Blok Kode 2), untuk setiap kasus yang mungkin terjadi.

Berikut ini adalah status-status berdasarkan proses mana yang menutup referensi terakhir ke sebuah handle. Setiap entri mewakili jumlah dereferensi objek FSContextReg yang terjadi jika proses yang sesuai menutup handle akhir. Catatan: tidak ada perbedaan fungsional antara HANDLE #1 (inisialisasi pegangan) dan HANDLE #2 (pendaftaran handle), karena bidang FileObject->FSContext2 menunjuk ke memori yang sama di kedua FILE_OBJECT diwakili ole handle yang sesuai.

Tangkapan layar dereferensi FSContextReg untuk setiap kemungkinan status IPC MSKSSRV

Dereferensi FSContextReg untuk masing-masing kenungkinan status IPC MSKSSRV

Berhasil! Keadaan terakhir menghasilkan empat kali dereferensi: dua oleh proses asing dan dua oleh proses yang melakukan inisialisasi (sekaligus registrasi), sementara pada awalnya hanya ada tiga referensi, yang berarti use-after-free dapat terjadi! Saya juga mengulangi latihan yang sama dengan objek FSStreamReg , tetapi karena bug kebocoran memori dalam kode, sebenarnya tidak mungkin untuk membebaskan objek FSStreamReg  setelah didaftarkan.

Kerentanan

Saat melakukan latihan otak mesin virtual yang diuraikan di atas, saya menemukan masalahnya. Jika prosesnya adalah proses inisialisasi atau proses pendaftaran, pembersihan yang sesuai terjadi, dan pointer toko di Irp->CurrentStackLocation->FileObject->FsContext2  diatur ke NULL . Blok kode di bawah ini menunjukkan di mana ini terjadi jika penelepon adalah proses inisialisasi:

Tangkapan layar FSRegObject: :CloseInitProcess menetapkan penunjuk fsContext ke NULL

Blok Kode 5: fsRegObject: :CloseInitProcess menyetel penunjuk fsContext ke NULL

Ini berarti FSRendezvousClose  tidak akan dipanggil lagi selama penyelesaian IRP_MJ_CLOSE  permintaan di DispatchClose  (SrvDispatchClose , Blok Kode 2).

Namun, jika proses panggilan adalah proses asing, tidak ada pembersihan yang terjadi dan FSRegObject::Release  dipanggil sekali di dekat akhir fungsi. Sejak FileObject->FsContext2  bukan NULL, FSRendezvousServer::Close  dipanggil lagi selama IRP_MJ_CLOSE berikutnya  permintaan dan panggilan lain ke FSRegObject: :Release terjadi.

Sekarang, jika handle kedua ditutup oleh proses yang menginisialisasi dan mendaftarkan objek FSContextReg, objek akan membersihkan semua sumber daya yang tersimpan, membuatnya kosong. Hal ini menyebabkan FSRegObject::Release  untuk dipanggil dua kali dalam FSRendezvousServer: :Close (Blok Kode 4). Dereferensi ekstra berfungsi untuk memperhitungkan referensi inisialisasi tambahan setelah objek kosong.

Hal ini menghasilkan total empat dereferensi pada satu objek FSContextReg  , menunjukkan bahwa penggunaan setelah bebas terjadi.

Diagram CVE-2024-30089 digambarkan

Diagram 5: CVE-2024-30089 digambarkan

Pembaca mungkin bertanya-tanya mengapa proses lain tidak bisa menjadi yang terakhir menutup kedua handle tersebut, karena secara tampak hal itu juga akan menghasilkan empat kali dereferensi. Sebelum objek dihancurkan dan dibebaskan, objek tersebut dilepaskan dari daftar yang disimpan dalam objek globalFSRendezvousServer . Pada awal FSRendezvousServer::Close , penunjuk di dalam FSContext2 diperiksa sebagai anggota yang valid dari daftar. Dalam hal ini, objek dibebaskan dalam panggilan kedua ke FSRegObject::Release pada akhir fungsi. Selama panggilan keempat ke FSRendezvousServer::Close , objek telah dibatalkan tautan dari daftar, menjadikannya objek yang tidak valid, sehingga tidak dapat digunakan. Untuk memicu use-after-free, hal itu harus terjadi setelah objek diambil dan divalidasi di FSRendezvousServer::Close . Cuplikan kode di bawah ini menunjukkan primitif use-after-free yang dapat diperoleh dengan kerentanan:

Tangkapan layar dari jalur primitif kode UAF

Blok Kode 6: Jalur primitif UAF

Kompleksitas serangan

Dalam panduanpembaruan keamanan untuk kerentanan ini, skor CVSS menunjukkan bahwa “Eksploitasi [adalah] Lebih Mungkin“ dan kompleksitas serangan untuk kerentanan ini adalah “Rendah“. Meskipun Microsoft tidak memberikan penjelasan terperinci untuk penilaian mereka, saya telah mencatat beberapa pola saat menambal membedakan kerentanan lainnya. Kerentanan ini kemungkinan mendapat skor tersebut karena berasal dari kesalahan logika, sehingga mudah dipicu. Dengan mengikuti langkah-langkah yang diuraikan dalam Diagram 5, penyerang dapat secara konsisten memicu skenario penggunaan setelah bebas yang digambarkan dalam Blok Kode 6. Namun, ini tidak berarti bahwa mengeksploitasi dalam praktik itu mudah. Panduan terperinci dari langkah-langkah eksploitasi akan dibahas di bagian selanjutnya dari seri ini.

Retrospektif

Memahami bagaimana bug terjadi penting untuk mengembangkan pendekatan proaktif untuk mengamankan praktik pengembangan. Untuk mengetahui bagaimana kerentanan itu muncul, saya menganalisis versi driver sebelumnya yang diperoleh dari Winbindex dan mencari perbedaan logika dalam fungsi FSRendezvousServer::Close  .

Di bagian kerentanan, saya menyebutkan bahwa penyebab utama bug ini bukanlah pengaturan
 

Irp->CurrentStackLocation->FileObject->FsContext2

 
ke 

NULL

 jika proses panggilan adalah proses asing. Yang mengejutkan saya, saya melihat baris kode yang tepat ini di versi awal mskssrv.sys:

Tangkapan layar kode versi awal FSRendezVousServer: :Close, fsContext2 disetel ke NULL

Blok Kode 7: Versi awal FSRendezVousServer: :Close, fsContext2 disetel ke NULL

Dalam blok kode yang ditunjukkan di atas, FileObject->FsContext2  secara eksplisit diatur ke NULL , terlepas dari hasil pemeriksaan ID proses sebelumnya. Ini mencegah FSRendezvousServer::Close  dari dipanggil lagi di IRP_MJ_CLOSE berikutnya permintaan  , sehingga dereferensi ekstra tidak dapat terjadi. Aneh — jadi mengapa baris kode ini dihapus? Mari kita lihat versi fungsi yang lebih baru, di mana bug pertama kali diperkenalkan:

Tangkapan layar FSContext disetel ke NULL dalam pemeriksaan feature flag

Blok Kode 8: FSContext disetel ke NULL dalam pemeriksaan feature flag

Yang ditunjukkan dalam blok kode di atas adalah pemeriksaan untuk feature flag

Feature_Servicing_TeamsUsingMediaFoundationCrashes

.
Feature flag adalah komponen Windows yang mengaktifkan berbagai fungsi dan eksperimen, meskipun tidak ada banyak informasi publik tentang mereka. Dalam postingan blog sebelumnya, kami membahas bagaimana fitur telah digunakan untuk patch kerentanan. Bendera fitur terkadang digunakan untuk menguji fungsionalitas sebelum diadopsi secara resmi. Dalam hal ini, jika

Feature_Servicing_TeamsUsingMediaFoundationCrashes

diaktifkan, FileObject->FsContext2 tidak diatur ke NULL, memperkenalkan kerentanan. Fitur ini diamati diaktifkan secara default pada instalasi Windows 10. Di Windows 11 dan seperti yang ditunjukkan pada Blok Kode 1, kondisional feature flag ini tidak ada dan pointer tidak disetel ke NULL sehingga membuatnya rentan juga.

 

Karena nama fiturnya, saya melihat fungsionalitas Microsoft Teams, perangkat lunak konferensi video. Saya mengonfirmasi bahwa aplikasi dapat menggunakan fungsionalitas MSKSSRV untuk berbagi aliran media lintas proses. Ada kemungkinan bahwa berbagi handle stream menyebabkan Teams mengalami crash. Topik yang menarik untuk riset lanjutan adalah menelaah bagaimana Teams membagikan handle perangkat MSKSSRV antarproses, serta alasan mengapa pembersihan pointer yang dilakukan dengan benar justru dapat menyebabkan aplikasi mengalami crash.

Tambalan itu

Bagian dari seri ini berfokus pada kerentanan itu sendiri, termasuk cara memperbaikinya. Saya sangat tertarik untuk memeriksa patch untuk bug ini, karena perbaikan yang saya usulkan tampaknya memicu crash di Microsoft Teams. Perlu dicatat bahwa hingga tahap ini saya belum meneliti bagaimana aplikasi nyata menggunakan driver MSKSSRV dalam praktiknya. Ketiadaan konteks tersebut menciptakan blind spot dalam memahami mengapa sebuah sistem memiliki desain seperti sekarang. Patch yang sepenuhnya menyelesaikan bug ini memerlukan restrukturisasi kode dasar dan dapat mengungkap lebih banyak detail mengenai bagaimana sistem IPC seharusnya berfungsi. Saya juga berharap untuk mendapatkan beberapa insight tentang praktik pengodean yang aman dari pengembang Microsoft.

Yang membuat saya kecewa, kesalahan logika yang menyebabkan kerentanan, yang ditambal dalam pembaruan Keamanan Juni 2024, tidak ditangani secara langsung. Sebagai gantinya, pemeriksaan token akses ditambahkan sebelum jalur kode yang rentan. Lihat kode di bawah ini untuk konteks inisialisasi IOCTL, ditangani oleh fungsi FSRendezvousServer::InitializeContext :

Tangkapan layar fungsi IOCTL dimulai dengan pemeriksaan feature flag dan memeriksa apakah proses pemanggilan adalah server bingkai

Blok Kode 9: Fungsi IOCTL dimulai dengan pemeriksaan feature flag dan memeriksa apakah proses pemanggilan adalah server bingkai

Fungsi di atas dimulai dengan memeriksa apakah fitur diaktifkan. Ini kemungkinan feature flag yang sesuai dengan patch. Jika fitur ini diaktifkan, KsIsCurrentProcessFrameServer  harus mengembalikan nilai TRUE, jika tidak, NTSTATUS  nilai STATUS_ACCESS_DENIED  akan dikembalikan.

Mari kita lihat KsIsCurrentProcessFrameServer :

Tangkapan layar dari KSISCurrentProcessFrameServer yang melakukan pemeriksaan SID pada token akses thread pemanggil

Code Block 10: Fungsi KsIsCurrentProcessFrameServer melakukan SID check terhadap access token milik thread yang memanggil

Fungsi ini memeriksa token thread pemanggil terhadap dua pengenal keamanan tertentu (SID). SID sesuai dengan token di grup NT SERVICE\FrameServer . Jika salah satu SID diaktifkan di token akses thread pemanggil, maka kode fungsi rentan dapat dijalankan.

Setelah melihat hal ini, saya menduga kemungkinan masih ada bug Administrator ke Kernel yang belum diperbaiki. Pada akhirnya, masalah korupsi memori tidak diatasi sama sekali. Saya mengonfirmasi hal ini dengan melakukan sedikit modifikasi pada eksploit asli saya: pengguna administrator dapat menjalankan layanan FrameServer , membuka handle ke layanan tersebut, lalu membuat proses eksploit menggunakan handle itu. Saya dapat memperoleh primitif kernel R/W penuh pada sistem yang sepenuhnya ditambal.

Meskipun Microsoft tidak menganggap jalur Administrator ke Kernel sebagai batas keamanan, bug serupa telah digunakan oleh aktor ancaman untuk memperoleh primitif R/W pada kernel dan memanfaatkannya untuk membutakan EDR serta menjalankan operasi rootkit. Jika Anda tertarik mengetahui apa saja yang dapat dilakukan dengan primitif ini, lihat presentasi BlackHat kami bersama FuzzySec.

Kesimpulan dan langkah selanjutnya

Posting ini berfokus pada bagian riset kerentanan dari upaya Pwn2Own saya, yang terdiri dari menemukan kerentanan kernel 0 hari yang dapat dieksploitasi untuk eskalasi hak istimewa. Tulisan ini menguraikan perjalanan tersebut: mulai dari terinspirasi oleh riset lain, gagal menemukan bug, mencoba pendekatan baru, menemukan hal yang mencurigakan, hingga akhirnya menentukan lokasi kerentanannya. Sekarang setelah bug berhasil diidentifikasi dan terdapat primitif use-after-free, sisanya seharusnya berjalan dengan mudah, bukan? Microsoft tampaknya berpendapat demikian; mereka memberi penilaian bug ini sebagai “Exploitation More Likely” dengan tingkat kompleksitas serangan “rendah”. Benarkah demikian? Saya akan membahas itu, strategi eksploitasi, dan mengungkap arti judul seri, di bagian selanjutnya!

Ucapan Terima Kasih

Andréa Piazza, untuk diagram yang menakjubkan

Emma Kirkpatrick, yang dengan sabar menjelaskan model keamanan Windows kepada saya

Mixture of Experts | 12 Desember, episode 85

Decoding AI: Rangkuman Berita Mingguan

Bergabunglah dengan panel insinyur, peneliti, pemimpin produk, dan sosok kelas dunia lainnya selagi mereka mengupas tuntas tentang AI untuk menghadirkan berita dan insight terbaru seputar AI.