Jailbreak 0day Terakhir: Tachy0n
(blog.siguza.net)- tachy0n adalah exploit eskalasi hak akses kernel yang berjalan di iOS 13.0–13.5; pada 23 Mei 2020, exploit ini disertakan sebagai 0day dalam unc0ver v5.0.0 dan saat itu menargetkan langsung iOS terbaru
- Intinya adalah kondisi race Lightspeed pada
lio_listio, yang memungkinkan objekkalloc.16dibebaskan dua kali sehingga dua objek berbeda dapat menunjuk ke memori yang sama - Bug dari keluarga yang sama sebelumnya juga dipakai dalam jailbreak/untether Spice untuk iOS 11, tetapi lingkungan sandbox aplikasi dan
racoonmemiliki batasan yang sangat berbeda dalam hal hak akses, sandbox, dan teknik spray - Exploit untuk unc0ver secara berulang mengamankan overlap
OSData, lalu menggunakanIOBufferMemoryDescriptordanIOAcceleratorFamily2untuk menyusun fake task dan fake mach port - Sejak iOS 14, Apple beralih ke pendekatan yang memblokir strategi exploit itu sendiri melalui pemisahan allocator, sequestering, PAC, dan hardening per objek; pengetahuan publik tentang exploit kernel iOS kini jauh tertinggal dibanding era iOS 13
Mengapa publikasi tachy0n tidak biasa
- tachy0n adalah exploit lama yang memengaruhi iOS 13.0 hingga 13.5, dan dipublikasikan pada 23 Mei 2020 dengan disertakan dalam unc0ver v5.0.0
- Menurut standar saat itu, ini adalah eskalasi hak akses lokal kernel (kernel LPE) yang biasa, tetapi jarang terjadi karena dipublikasikan sebagai 0day jailbreak yang memengaruhi versi iOS terbaru
- Apple merilis patch khusus untuk bug tersebut sekitar satu minggu setelah exploit dipublikasikan
- Bug ini adalah 0day di iOS 13.5, tetapi sebelumnya sudah pernah dimanfaatkan dalam bentuk 1day
- Pwn20wnd mencari 0day yang dapat dijangkau dari sandbox aplikasi, dan titik awalnya adalah pengujian regresi terhadap 1day yang sudah dikenal
- SockPuppet di iOS 12 dipatch pada iOS 12.3, tetapi muncul kembali di iOS 12.4
- Kasus ini memperlihatkan tidak adanya pengujian regresi Apple untuk jenis bug tersebut, dan Pwn20wnd mengimplementasikan beberapa pengujian regresi 1day yang dikenal lalu mendapatkan hit
Lightspeed: kondisi race lio_listio
- Bug inti tachy0n adalah bug Lightspeed dari Synacktiv, dan terkait dengan kemungkinan CVE-2020-9859 serta CVE-2018-4344
- Kerentanan ini berada pada syscall
lio_listio, yang menjalankan I/O file secara asinkron atau batch - Kernel mengalokasikan struktur
aio_lio_contextuntuk melacak pekerjaan I/O yang diajukan- Struktur ini memiliki field
io_waiter,io_issued, danio_completed
- Struktur ini memiliki field
- Pekerjaan sebenarnya dijalankan di thread terpisah, dan ketika semua I/O selesai,
do_aio_completionmembebaskan konteks tersebut - Jika tidak ada pekerjaan yang dijadwalkan, thread saat ini dari
lio_listioharus membebaskan konteks tersebut - Masalahnya, pemeriksaan ini memiliki kondisi race
- Pekerjaan bisa saja sudah diajukan ke thread lain, tetapi selesai dan konteksnya sudah dibebaskan sebelum waktu pemeriksaan
- Pada saat itu,
lio_listiokembali memeriksalio_contextyang sudah menjadi dangling pointer
Alur dari double free menuju exploit
- Urutan yang diperlukan untuk exploit adalah sebagai berikut
lio_listiomengalokasikanlio_context- Pekerjaan selesai dan
do_aio_completionmembebaskanlio_context - Memori yang sudah dibebaskan dialokasikan ulang sebagai objek yang dikendalikan penyerang dan dibuat seolah-olah
lio_context->io_issued == 0 lio_listiomelihatnya dan kembali membebaskan objek penyerang tersebut- Memori yang sama dialokasikan ulang sebagai objek lain, sehingga dua alokasi berbeda menunjuk ke memori yang sama
- Pada perangkat 64-bit,
lio_contextmasuk ke zone terkecil, yaitukalloc.16 - Sebelum iOS 14, allocation site yang sama dibagi berdasarkan ukuran, terlepas dari jenis objek
- Objek C++, array pointer, dan buffer data yang disediakan pengguna dapat saling menggunakan ulang memori dalam bucket berukuran sama
- Double free ini berperilaku berbeda dari double free umum yang mudah berujung pada kondisi fatal jika tidak ada realokasi perantara
lio_context->io_issuedtidak bernilai 0 saat masih dialokasikan- Setelah dibebaskan, allocator menimpa 8 byte pertama dengan nilai canary dan freelist pointer atau nilai XOR alamat objek
- Karena itu, free kedua hanya terjadi jika ada realokasi di antaranya dan byte ke-4 sampai ke-7 bernilai 0
- Exploit nyata dapat mencoba ulang race ini berkali-kali, dan di praktiknya jarang ada objek sistem lain yang secara kebetulan membuat byte yang diperlukan menjadi 0 hingga memicu double free
Pemanfaatan sebelumnya di Spice
- Bug yang sama digunakan juga dalam jailbreak/untether Spice yang menargetkan iOS 11.x
- Spice dikerjakan oleh tim Jake Blair bersama Sparkey dan littlelailo, dan versi terbaru saat itu adalah iOS 13.x
- Tujuannya adalah membuat mach port forgery baik di lingkungan aplikasi maupun lingkungan
racoon- Pada exploit kernel sebelum iOS 14, jika nilai yang disediakan pengguna dapat ditafsirkan sebagai pointer mach port, tahap berikutnya menjadi jauh lebih mudah
- Alur dasar untuk membuat mach port forgery dengan Lightspeed adalah sebagai berikut
- Memicu free pertama pada
lio_context - Melakukan spray mach message yang memiliki OOL mach ports descriptor berukuran 1 atau 2
- Membiarkan entry pertama sebagai
MACH_PORT_NULLagar masuk kekalloc.16dan tampak sepertiio_issuedbernilai 0 - Dengan free kedua, membebaskan array OOL mach ports
- Melakukan spray data terkendali ke
kalloc.16untuk mengganti array mach ports dengan fake pointer
- Memicu free pertama pada
Perbedaan batasan sandbox aplikasi dan racoon
- Pada A7–A9(X), tidak ada PAN, sehingga alamat userland dapat didereferensi seperti pointer kernel hanya dengan
mmapdanmlock - A10 dan A11 juga hendak didukung, tetapi di sandbox aplikasi, dukungan itu tidak selesai karena tidak ditemukan kebocoran alamat kernel yang sesuai dan target untuk menempatkan data kendali
- 1day yang hendak dimanfaatkan mencakup kebocoran informasi kernel stack dari Ian Beer serta escape sandbox backboardd
- Rencananya adalah membocorkan pointer shared memory atau menempatkan data di segmen
__DATAkernel - Karena target yang sesuai tidak ditemukan, dukungan A10/A11 melalui jalur aplikasi tidak terwujud
- Rencananya adalah membocorkan pointer shared memory atau menempatkan data di segmen
- Jalur
racoonmemiliki kondisi berbeda- Berjalan sebagai root, tetapi memiliki sandbox yang lebih ketat daripada aplikasi biasa
- Tidak memiliki akses IOSurface, sehingga tidak bisa memakai spray
OSUnserializeXMLumum melaluiIOSurface::setValue - Sebagai gantinya, pemanggilan
OSUnserializeXMLdi dalamRootDomainUserClient::secureSleepSystemOptionsdapat digunakan untuk melakukan spray sebagian objek dalam bentuk leak
racoonmemiliki profil sandbox yang mengizinkan semua pembacaan dan penulisan sysctl, serta memiliki hak root- Jika kernel slide diketahui, sysctl global di
__DATAkernel dapat digunakan seperti penyimpanan data pada alamat yang diketahui - Di Spice, yang dipilih adalah
vm.swapfileprefix
- Jika kernel slide diketahui, sysctl global di
- Untuk memperoleh kernel slide, digunakan CVE-2018-4413 dari panicall
- Kebocoran informasi
sysctl_procargsxdapat membocorkan hampir satu halaman memori kernel yang belum diinisialisasi darikernel_map - Dengan ini, pointer kode kernel dan heap dapat diperoleh, sehingga A7–A11 dapat ditangani
- Di sandbox aplikasi,
sysctl_procargsxdiblokir sehingga metode yang sama tidak mungkin dilakukan
- Kebocoran informasi
Struktur exploit tachy0n untuk unc0ver
- Target unc0ver adalah A8–A13, sehingga A10+ tidak bisa diabaikan atau bergantung pada dereferensi userland
- Exploit ini dirancang dalam struktur dua lapis dengan mempertimbangkan tahap memory corruption yang bisa gagal
- Lapisan bawah menjalankan thread freerer yang memanggil
lio_listiodan thread racer yang melakukan unserializeOSDatamelalui IOSurface - Nilai defaultnya adalah 4 freerer dan 16 racer, dan dapat disesuaikan
- Lapisan bawah menjalankan thread freerer yang memanggil
- Data yang di-unserialize melalui IOSurface adalah
OSDictionarydengan beberapa entryOSData- Posisi yang sesuai dengan
io_issuedharus bernilai 0 - Magic value seperti
0x41414141,0x69696969, serta nilai keykdigunakan untuk mendeteksi overlap
- Posisi yang sesuai dengan
- Setelah race, semua nilai
OSDatadiperiksa- Objek yang magic value-nya berubah dianggap telah diambil oleh objek sistem lain dan ditandai sebagai target cleanup nanti
- Jika key dan nilai
kdi dalam buffer berbeda, itu dinilai sebagai overlap ketika objekOSDatalain menunjuk ke backing buffer yang sama
- Fungsi
maybe_reyoinkdanoverlapdalam kode menyusun informasi overlap tersebut dan meneruskannya ke lapisan atas - Lapisan atas menggunakan objek
OSDatayang overlap untuk menyusun fake mach port- Membebaskan satu
OSData - Melakukan spray mach message dengan OOL port descriptor
- Membebaskan
OSDatalainnya - Mengalokasikan ulang sebagai
OSDatabaru yang berisi pointer fake task port
- Membebaskan satu
Menempatkan data terkendali pada alamat kernel yang diketahui
- Exploit dapat membocorkan raw kernel pointer dari mach port dengan membaca isi yang telah dialokasikan ulang sebagai array OOL ports descriptor melalui
OSData - Pada tahap berikutnya, ini digunakan untuk membocorkan alamat task port dan service port
IOSurfaceRoot, tetapi masalah utamanya adalah memperoleh alamat kernel dari buffer yang dapat dikendalikan secara stabil - Kandidat yang ditemukan di source XNU adalah
IOMemoryDescriptor- Field
_rangesadalah arrayIOVirtualRange, dan satuIOVirtualRangetepat masuk kekalloc.16 - Namun,
IOMemoryDescriptorbiasa menggunakan_singleRangealih-alih heap allocation jika rangenya hanya satu
- Field
IOBufferMemoryDescriptormenjadi pengecualian karena memanggilIONew(IOAddressRange, 1)untuk satu range sehingga melakukan heap allocation- Tempat yang praktis untuk mengalokasikannya secara arbitrer dan memetakannya ke ruang alamat pengguna adalah antarmuka AGX dari
IOAcceleratorFamily2- Jika userclient type 0 dibuka dari
IOGraphicsAccelerator2, akan diperolehIOAccelContext2 - Tiga memory descriptor dapat di-map melalui
::clientMemoryForType() - Type 0 berukuran 0x8000 byte sehingga digunakan untuk mengidentifikasi victim descriptor
- Jika userclient type 0 dibuka dari
- Exploit menggunakan loop berikut
- Membuka
IOAccelContext2dan memperoleh duaOSDatayang overlap - Membebaskan salah satu
OSData - Menghubungkan
IOAccelSharedUserClient2yang sudah dibuka sebelumnya denganIOConnectAddClient() - Membaca
OSDatayang tersisa untuk memastikan 8 byte pertama adalah kernel pointer yang page-aligned dan 8 byte berikutnya adalah0x8000 - Jika kondisi tidak cocok, menutup
IOAccelContext2dan mengulang
- Membuka
Pageable memory, fake port, zone_require
- Setelah memory descriptor di-map ke process dan alamat kernelnya diketahui, masih ada masalah bahwa memori dibuat sebagai
kIOMemoryPageable - Karena fake mach port dan objek fake task dapat diakses saat preemption dimatikan, page tersebut perlu di-fault-in di sisi kernel
- Ini ditangani dengan memanggil dua kali external method 2
IOAccelContext2::submit_data_buffers, yang secara tidak langsung memanggilIOAccelContext2::processSidebandBuffer- Membaca struktur pada offset 0x10 byte dari awal shared memory
- Struktur pertama memiliki
tok == 0x100dan dibuat menutupi seluruh page agar proses berlanjut hingga page kedua - Page kedua kemudian dapat digunakan untuk meletakkan data fake object
- Tahap berikutnya berlanjut ke penyusunan fake task, fake port, switcheroo OOL descriptor, dan primitive pembacaan arbitrer
- Bypass
zone_requirejuga diperlukan- Saat itu,
zone_requiremengizinkan page di luarzone_mapdan menafsirkan0x20byte pertama page seperti metadata - Dengan memasukkan zone index yang benar, ini dapat digunakan seperti tiket lolos untuk zone yang diinginkan
- Karena itu diperlukan dua page: satu page untuk task dan satu page untuk mach port
- Saat itu,
- Exploit ini sekarang dipublikasikan di GitHub
Analisis dan patch setelah publikasi
- Publikasi exploit 0day lengkap untuk versi terbaru yang masih ditandatangani menarik perhatian scene jailbreak iOS
- Brandon Azad, yang saat itu bekerja di Project Zero, mengidentifikasi kerentanannya dalam waktu kurang dari 4 jam setelah exploit dipublikasikan dan memberi tahu Apple
- Analisis tersebut dirangkum dalam How to unc0ver a 0-day in 4 hours or less
- Enam hari setelah exploit dipublikasikan, Synacktiv melalui artikel baru membahas kemungkinan bahwa fix asli di iOS 12 membuat memory leak, dan upaya memperbaiki memory leak itu justru menghidupkan kembali bug semula
- Sembilan hari setelah exploit dipublikasikan, Apple merilis patch
- Setelah itu, pengujian regresi untuk bug tersebut ditambahkan ke XNU
- Lima puluh empat hari setelah publikasi, versi reverse-engineered bernama “tardy0n” disertakan dalam jailbreak Odyssey, dengan target yang juga iOS 13.0–13.5
Lingkungan exploit yang berubah sejak iOS 14
- iOS 14 menunjukkan perubahan strategi keamanan kernel Apple
- Sebelum iOS 14, apa pun primitive awalnya—heap overflow, over-release objek C++, type confusion, dan sebagainya—target berikutnya umumnya adalah mach port
- Salah satu perubahan terbesar di iOS 14 adalah allocator
kallocdanzalloc- Zone map dibagi menjadi beberapa rentang “kheap”
- Data yang dikendalikan pengguna dan objek kernel dipisahkan agar masuk ke heap berbeda
- Sequestering diterapkan pada objek kernel, sehingga page virtual address yang dialokasikan pada zone tertentu tidak digunakan ulang oleh zone lain sampai reboot
- Physical memory dapat dibebaskan, tetapi rentang virtual memory tidak digunakan ulang untuk objek lain, sehingga type confusion pada objek kernel secara praktis terblokir
- Guard page, posisi awal zone allocation yang berubah tiap boot, serta penyempurnaan berikutnya membuat keandalan serangan cross-zone jauh lebih rendah
- Apple bergeser dari sekadar memblokir bug individual menjadi memblokir strategi exploit
- Jika exploit memakai struct kmsg sebagai target corruption, struktur tersebut ditandatangani
- Jika pipe buffer dipakai sebagai antarmuka baca/tulis kernel yang stabil, pointer terkait menjadi target penerapan PAC
- Jika muncul teknik yang memakai objek tidak terkait sebagai victim, tipe objek tersebut di-hardening
- Akibatnya, dalam pengembangan exploit, exploit strategy menjadi lebih bernilai daripada 0day memory corruption awal
Terputusnya pengetahuan publik
- Sebelum iOS 14, pengetahuan riset keamanan iOS yang publik dinilai hampir setara dengan pengetahuan privat
- Setelah iOS 14, kecuali beberapa pengecualian, berbagi informasi pada dasarnya terhenti
- Bahkan ketika iOS 19 beta tinggal beberapa minggu lagi, dirangkum bahwa tidak ada exploit kernel publik untuk iOS 18 atau iOS 17
- Catatan keamanan Apple sesekali memuat kerentanan yang dieksploitasi di dunia nyata, tetapi informasi publik tidak mampu mengikuti riset privat
- Fakta bahwa baru 5 tahun berlalu sejak tachy0n dipublikasikan menunjukkan betapa cepatnya bidang exploit kernel iOS berubah
2 komentar
Perangkat keras Apple memang hebat, tetapi perangkat lunaknya penuh dengan niat untuk mengekang pengguna.
Bahkan jika Anda hanya ingin menjalankan aplikasi yang Anda buat dan build sendiri di perangkat milik Anda, tetap perlu berlangganan seharga $100.
Kalau Anda adalah pengembang yang memakai aplikasi open source skala kecil hingga menengah dan membangunnya sendiri untuk dipakai,
daripada harus melakukan sideload dengan memanfaatkan celah di perangkat Apple sampai perlu jailbreak, lebih mudah pakai Android saja.
Komentar Hacker News
Yang mengesankan adalah cara mengalahkan perusahaan bernilai 1 triliun dolar ternyata lewat pekerjaan sederhana dan membosankan yang menjadi kelemahan khusus Apple, yaitu regression testing
SockPuppet, salah satu kerentanan besar yang dipakai untuk jailbreak di iOS 12, ditemukan dan dilaporkan ke Apple oleh Ned Williamson dari Project Zero, dipatch di iOS 12.3, lalu kemudian dipublikasikan di bug tracker Project Zero
Namun di iOS 12.4 kerentanan itu muncul lagi seolah-olah belum pernah dipatch, mungkin karena Apple melakukan fork XNU ke branch terpisah untuk versi tersebut dan gagal menerapkan patch-nya
Ini adalah sinyal kuat bahwa tidak ada regression test untuk kerentanan semacam ini, dan hanya dengan mengotomatiskan beberapa 1-day yang sudah dikenal, Pwn bisa langsung mengenai sasaran
Saya penasaran ada berapa pihak yang menjalankan CI farm untuk terus menguji kerentanan lama pada versi baru proyek seperti Linux, FreeBSD, OpenWRT, dan OpenSSH
Saat kuliah 20 tahun lalu, saya menjadi relawan QA di Mozilla, dan saat itu ada kumpulan regression test yang terus bertambah, terutama untuk bug rendering/layout dan JavaScript engine
Karena kami membuat test case minimal untuk reproduksi dan verifikasi perbaikan, test itu juga mudah dimasukkan ke build pipeline
Bug memang tidak bisa dihindari, tetapi bug yang sudah diperbaiki dengan waktu dan uang lalu hidup kembali adalah skenario terburuk
Organisasi yang peduli pada kualitas jelas berinvestasi pada regression testing, tetapi banyak organisasi tidak menghargai QA dan entah tidak melakukannya sama sekali atau menyerahkannya ke outsourcing termurah
Benar-benar aneh bahwa Apple tidak memiliki regression test untuk jailbreak, kategori bug yang secara historis paling menarik perhatian
Mozilla sekarang mungkin bisa dikritik dari banyak sisi, tetapi bahkan pada awal 2000-an mereka menjalankan QA dan CI/CD yang cukup solid dengan alat seperti Tinderbox dan Bugzilla
Ketika DevOps menjadi tren dan memopulerkan cara kerja seperti ini, saya sempat mengira semua orang sudah melakukannya, tetapi ternyata itu salah paham saya
Ini seperti situasi ala Hukum Conway yang tercipta dari pemisahan keamanan dan pengembangan fitur
Meskipun ada prosedur build/release dan kumpulan regression test yang matang, karena struktur organisasi internal, besar kemungkinan isu keamanan semacam ini tidak masuk ke dalamnya
Jumlahnya mudah saja ribuan, dan mungkin itu SQLite
Ini pendekatan yang layak ditiru
Jika perbaikan tidak di-backport, kemungkinan besar test-nya juga tidak akan di-backport
Saat melihat istilah seperti kheap separation, mitigasi task port, SSV, dan SPTM, rasanya seperti sedang lancar berbicara dengan teman dalam bahasa asing lalu tiba-tiba beralih ke penjelasan bedah otak atau fisika nuklir, dan pemahaman saya jatuh dari tebing
Rasanya mirip ketika saya pernah mencoba menerjemahkan percakapan tentang renovasi tungku peleburan
Sayang jailbreak sekarang tidak seramai dulu
Hampir tidak ada hal praktis yang saya lakukan dengan iPad yang di-jailbreak, tetapi itu menyenangkan, dan kalau sekarang saya ingin memasang aplikasi tethering, UTM, serta solusi JIT
SideStore juga terlihat menjanjikan, tetapi akun saya dulu sempat menjadi akun Apple Developer berbayar, sehingga masih ada 10 app ID yang tidak kedaluwarsa, dan karena itu saya tidak bisa memasang aplikasi seperti UTM kecuali membuat akun baru atau membayar lagi
Setelah kehilangan itu, saya kembali ke Android, dan pada saat itu Android sudah cukup mengejar dari sisi fitur bawaan
Saya dengar Apple sekarang membayar 1 juta dolar untuk jailbreak, dan itu kemungkinan adalah batas bawah harga pasar bebas
Entah harus lewat broker, atau ada email publik yang tidak akan tenggelam jika bertanya melalui dukungan pelanggan lini pertama
Kalau ini benar, berarti Apple memakai strategi yang luar biasa
Dengan menutup semua jalan untuk mendapatkan root di perangkat, Apple bisa mempatch kerentanan yang ditemukan gratis oleh developer jailbreak
Menurut tulisan itu, komunitas privat masih memiliki exploit dan Apple mempatch exploit tersebut
Hanya komunitas publik atau developer ini yang tampaknya, entah karena alasan apa, tidak lagi seperti itu
Kalimat favorit saya dari seluruh tulisan adalah: “Saya juga ingin berterima kasih kepada seseorang yang meng-unpatch bug itu di iOS 13.0. Itu juga tindakan yang sangat keren.”
Katanya “saya tidak bisa membayangkan kita akan berada di mana 5 tahun lagi”, tetapi saya bisa membayangkannya
iMessage masih memungkinkan pengambilalihan perangkat, akun, dan data
Tidak disebutkan dalam tulisan apakah ini tethered atau untethered
Setahu saya, unc0ver, jailbreak yang menyertakan ini dalam distribusinya, mungkin termasuk “semi-untethered”