- CVE-2024-1086 pada
nf_tableskernel Linux menyebabkan double free padask_buffakibat kegagalan validasi input verdict Netfilter, dan dalam kondisi tertentu dapat berujung pada eskalasi hak akses lokal - Alur serangan membuat skb yang sudah dibebaskan saat pemrosesan
NF_DROPtetap diproses seolah-olahNF_ACCEPT, sehingga objek yang sama dibebaskan lagi di jalur berikutnya - PoC telah diverifikasi pada KernelCTF mitigation, Debian, Ubuntu, dan kernel vanilla, dan setidaknya rentang v5.14.21~v6.6.14 terdampak tergantung
kconfig; perbaikan didistribusikan ke branch stable pada Februari 2024 - Inti tekniknya adalah Dirty Pagedirectory, yang menggandakan alokasi halaman PTE dan PMD ke halaman fisik yang sama sehingga akses baca/tulis dari ruang pengguna saja dapat dipakai untuk mengakses alamat fisik arbitrer; ini adalah varian KSMA berbasis data saja
- Digabungkan dengan pencarian physical KASLR, bypass
modprobe_path, eksekusi tanpa file, dan pengaitan file descriptor untuk keluar dari namespace, ini menjadi contoh LPE praktis yang menargetkan manajemen memori kernel dan subsistem jaringan sekaligus
Syarat kerentanan dan cakupan dampak
- Bug
nf_tablestelah didaftarkan sebagai CVE-2024-1086, dan inti masalahnya adalah kegagalan validasi input yang memungkinkan drop error bernilai positif dalam pemrosesan verdict Netfilter - Eksploitasi memerlukan syarat berikut
nf_tablesharus aktif- namespace pengguna tanpa hak istimewa harus aktif
- Pada distro utama seperti Debian dan Ubuntu, serangan mengasumsikan pengaturan ini aktif secara bawaan
- Berdasarkan pengujian, branch stable
linux-5.15.y,linux-6.1.y,linux-6.6.ytermasuk terdampak, danlinux-6.7.1juga mungkin terdampak - Perbaikan bug didistribusikan ke branch stable pada Februari 2024
- Kode sumber PoC dipublikasikan di CVE-2024-1086 PoC repository
Alur kode yang menghasilkan double free
- Verdict Netfilter adalah nilai yang menentukan apakah sebuah paket akan dibuang, diterima, dikirim ke queue, dan sebagainya
- Alur rentan dimulai dari
nft_verdict_init()yang tidak cukup membatasi nilai verdict dari input pengguna, sehingga dapat ditetapkan nilai yang tampak sepertiNF_DROPnamun memiliki drop error bernilai positif nf_hook_slow()memeriksa bit-bit bawah verdict, dan bila menilainya sebagaiNF_DROP, ia terlebih dahulu membebaskan skb dengankfree_skb_reason()- Setelah itu, jika hasil
NF_DROP_GETERR()mengembalikan nilai yang sesuai denganNF_ACCEPT, sisi pemanggil akan menganggap paket diterima dan melanjutkan pemrosesan - Akibatnya, skb yang sudah dibebaskan kembali dibebaskan di jalur berikutnya, membentuk primitive double free
Objek yang rusak dan cara pemrosesan paket
- Double free memengaruhi
struct sk_buffdiskbuff_head_cachedan objeksk_buff->head sk_buff->headmemuat isi paket yang sebenarnya, dan tergantung ukuran paket IPv4 dapat dialokasikan darikmalloc-256hingga halaman order 4 milik buddy allocator- PoC dirancang menggunakan paket IP besar agar masuk ke jalur buddy allocator, bukan slab allocator
- fragmentation queue IPv4 digunakan untuk menunda atau memicu pembebasan kedua pada waktu yang diinginkan
- Jika field skb yang rusak dipakai dalam jalur paket, kernel panic dapat terjadi; karena itu exploit menghindari stack TCP/UDP dan memakai jalur error fragmen IP tertentu
Cakupan pengujian dan tingkat keberhasilan
- Berbagai versi dan konfigurasi kernel diuji pada lingkungan kernel vanilla, KernelCTF, Debian, dan Ubuntu
- Contoh kasus berhasil mencakup lingkungan berikut
- Linux v5.14.21, v5.15.148, v5.16.20, v5.17.15, v5.18.19, v5.19.17, v6.0.19
- Linux v6.1.55 pada KernelCTF Mitigation v3
- Linux v6.1.69 pada Debian Bookworm 6.1.0-17
- Linux v6.1.72 pada KernelCTF LTS
- Ubuntu Jammy v6.2.0-37
- Linux v6.2.16, v6.3.13
- Contoh gagal mencakup v5.4.270, v5.10.209, v6.4.16, Ubuntu Jammy v6.5.0-15, v6.5.13, v6.6.14, dan v6.7.1
- Sejumlah kegagalan setelah v6.4.0 terkait dengan deteksi bad_page() akibat
CONFIG_INIT_ON_ALLOC_DEFAULT_ON=y - Pada lingkungan v6.4.16, tingkat keberhasilan mencapai 99.4%, dan dalam beberapa kasus turun hingga 93.0%, masing-masing dengan jumlah sampel n=1000
Cara perbaikan
- Perbaikan yang mula-mula diusulkan berpotensi menimbulkan breaking change di tengah stack Netfilter
- Perbaikan dari maintainer Netfilter memperketat pembatasan verdict dari input pengguna pada level API
- Patch menolak parameter verdict DROP/QUEUE dari input userland
- Menurut deskripsi CVE,
nft_verdict_init()mengizinkan nilai positif sebagai drop error di dalam hook verdict, dannf_hook_slow()dapat menimbulkan double free saatNF_DROPdanNF_ACCEPTbertumpang tindih - Patch perbaikannya dapat dilihat di [PATCH nf] netfilter: nf_tables: reject QUEUE/DROP verdict parameters.
Dirty Pagedirectory dan akses memori fisik arbitrer
- Teknik utama PoC adalah Dirty Pagedirectory, yaitu variasi dari teknik Dirty Pagetable yang sudah ada
- Gagasan intinya adalah menggandakan alokasi halaman PTE dan PMD ke halaman fisik yang sama
- Jika nilai yang tampak seperti entri PTE ditulis ke satu area alamat virtual, area alamat virtual lain akan menafsirkannya sebagai entri page table dan memetakan halaman fisik yang ditentukan
- Dengan cara ini, serangan bekerja sebagai kernel-space mirroring attack yang memungkinkan pengaturan alamat fisik arbitrer dan flag izin hanya melalui baca/tulis alamat ruang pengguna
- Teknik ini digunakan untuk melewati mitigasi seperti virtual KASLR, KPTI, SMAP, SMEP, dan
CONFIG_STATIC_USERMODEHELPER
Manipulasi page allocator
- Alokasi halaman kernel melibatkan slab allocator, buddy allocator, dan PCP allocator
- Head skb menggunakan halaman order 4 dari buddy allocator pada ukuran besar, sedangkan halaman PTE/PMD adalah halaman order 0, sehingga keduanya tidak langsung bertemu
- Untuk mengatasi ini, digunakan dua metode page conversion
- PCP list draining: memasukkan halaman order 4 ke buddy freelist, lalu mengosongkan PCP order 0 freelist agar terisi ulang sebagai halaman order 0 dari buddy allocator
- race condition: memanfaatkan perlombaan saat free kedua agar halaman order 4 masuk ke order 0 freelist
- PCP list draining adalah metode yang lebih sederhana, stabil, dan cepat
- Metode race condition dipakai pada exploit awal KernelCTF, tetapi kini dianggap usang karena bergantung pada lingkungan seperti VM QEMU dengan latensi serial TTY yang tinggi
Bypass mitigasi KernelCTF
- Pada lingkungan mitigasi KernelCTF, mitigasi yang paling aktif harus dilewati adalah pemeriksaan korupsi freelist
sk_buff - Karena
skbuff_head_cache->offset == 0x70, pointer next freelist bertumpang tindih denganskb->len - Setelah skb pertama dibebaskan,
skb->lentertimpa sebagian pointer freelist, lalu nilainya bisa berubah lagi saat parsing paket berikutnya dan memicu pemeriksaan korupsi - Deteksi ini dilewati dengan membebaskan skb normal tambahan di atas skb yang rusak untuk menimpa freelist head
- Pengembang KernelCTF menilai bypass ini dapat dikurangi jika pemeriksaan pointer next freelist head juga dilakukan pada saat free
TLB flush dan pencarian physical KASLR
- Jika page table diubah dengan cara tak lazim melalui Dirty Pagedirectory, informasi translasi lama dapat tetap tersisa di cache TLB CPU
- TLB di-flush dengan cara melakukan
fork()dari ruang pengguna, lalu proses anak menjalankanmunmap()dan masuk ke keadaan tidur - Metode ini dipastikan bekerja 100% pada CPU AMD dan VM QEMU
- Physical KASLR mempersempit ruang pencarian dengan memanfaatkan fakta bahwa alamat base fisik kernel disejajarkan ke
CONFIG_PHYSICAL_STARTatauCONFIG_PHYSICAL_ALIGN - Dengan asumsi memori fisik 8GiB dan alignment 16MiB, ada 512 kandidat; skrip get-sig dipakai untuk membuat signature base kernel guna identifikasi
modprobe_path dan memperoleh root shell
- Setelah memperoleh baca/tulis memori fisik arbitrer, PoC memindai sekitar 80MiB setelah base kernel untuk menemukan
modprobe_path - Pada konfigurasi umum, ia mencari pola
"/sbin/modprobe"dengan null padding, lalu memverifikasi variabel sebenarnya melalui apakah nilainya tercermin di/proc/sys/kernel/modprobe - Jika
CONFIG_STATIC_USERMODEHELPERaktif, string"/sbin/usermode-helper"dijadikan target - Untuk mendapatkan root shell, string
modprobe_pathatau static usermode helper ditimpa dengan path memfd berbentuk/proc/<pid>/fd/<fd> - Skrip eskalasi hak akses menghubungkan file descriptor exploit ke stdin/stdout milik shell agar dapat bekerja baik di terminal lokal maupun reverse shell
Eksekusi tanpa file dan susunan PoC
- PoC mendukung fileless execution tanpa menulis file ke disk
- Jika target memiliki Perl,
memfd_create()dapat dipakai untuk memuat biner exploit ke memori dan menjalankannya melalui/proc/$$/fd/<fd> - Dependensi kompilasi adalah
libnftnl-devdanlibmnl-dev - Build statis untuk KernelCTF menggunakan
musl-gcc, dipilih untuk menghindari static link glibc dan masalah opcode QEMU AVX512 - Sumber exploit dibagi ke beberapa file dan, karena ditujukan sebagai biner mandiri, saat terjadi error ia memilih crash/exit alih-alih mengembalikan error code
Stabilitas dan keterbatasan
- Karena status pagetable proses exploit dapat menjadi tidak stabil, setelah berhasil maupun gagal proses anak dibiarkan tidur alih-alih dihentikan untuk mengurangi ketidakstabilan kernel
- Aktivitas jaringan dapat menimbulkan noise pada freelist skb dan memengaruhi stabilitas
- Pada lingkungan SSH atau reverse shell, output stdout di sekitar momen double free dikurangi untuk meminimalkan alokasi/pembebasan skb akibat jaringan
- Pada beberapa pengujian perangkat keras, sistem crash setelah beberapa detik; karena frame WiFi juga memakai skb, aktivitas WiFi diduga ikut memengaruhi
- Jika adaptor WiFi dinonaktifkan di BIOS, exploit berjalan normal pada lingkungan tersebut
Kesimpulan dari proses riset
- PoC disempurnakan dengan sasaran kompatibilitas luas, stabilitas tinggi, dan eksekusi tersembunyi
- Selain 2 bulan pengembangan, 2 bulan tambahan digunakan untuk meningkatkan stabilitas dan kompatibilitas
- Exploit itu sendiri tidak terlalu bergantung pada perilaku slab allocator, dan lebih berfokus pada fitur yang luas penggunaannya seperti subsistem IPv4 dan memori virtual
- Bug awal memerlukan unprivileged user namespace dan nftables, tetapi teknik seperti Dirty Pagedirectory dan PCP draining dapat dimanfaatkan pada exploit nyata lainnya
- Pekerjaan ini menjadi contoh yang mendalami sekaligus subsistem jaringan dan subsistem manajemen memori pada kernel Linux
1 komentar
Komentar di Hacker News
Hari ini, exploit proof-of-concept untuk CVE-2024-1086 dipublikasikan, dan berfungsi di Debian, Ubuntu, dan lainnya
Versi yang terdampak adalah kernel Linux v5.14 hingga v6.6, dan dukungan untuk v6.4 hingga v6.6 bergantung pada pengaturan kernel
CONFIG_INIT_ON_ALLOC_DEFAULT_ONBug ini sudah ditambal pada Februari 2024, jadi perangkat Linux perlu diperbarui
https://github.com/Notselwyn/CVE-2024-1086/blob/main/src/mai...
modprobe_pathdan bahkan memasukkan brute force pid karena pendekatan tanpa fileMisalnya, saya ingin bertanya kenapa tidak memilih cara menambal
.textkernel dengan shellcode pendek untuk menjadi root dan keluar dari namespaceNamun tertulis bahwa branch yang sudah ditambal
v5.15.149>,v6.1.76>,v6.6.15>dikecualikanAda kalimat seperti ini di patch: “This reverts commit e0abdadcc6e1. [...] Its not clear to me why this commit was made.”
Saya penasaran apakah ada yang sudah menelusuri riwayat latar belakang commit ini
[1] https://lore.kernel.org/all/20240120215012.129529-1-fw@strle...
Saya sudah mencari di daftar netdev lama tetapi tidak menemukan apa pun, dan mungkin saja itu patch yang dikirim langsung ke committer, Pablo Neira Ayuso
Penulis aslinya adalah Patrick McHardy, yang kini menjadi sosok yang dihindari, dan kecuali Pablo mengingatnya atau bisa menemukannya di email, use case pastinya tampak sulit diungkap hanya dengan investigasi dasar
Isinya
netfilter: nf_tables: accept QUEUE/DROP verdict parameters, yang memungkinkan userspace menentukan nomor queue atau kode errno pada verdictQUEUEdanDROPTulisan ini juga sangat mengesankan dari sudut pandang penulisan keamanan
Saat menulis blog keamanan, selalu ada dilema “seberapa banyak pengetahuan latar dan pengetahuan prasyarat yang harus diasumsikan”, dan sulit menyeimbangkan agar tetap mudah diakses sekaligus bisa ditulis
Bagus sekali karena penulis lebih dulu menetapkan target pembaca dan memberikan penjelasan latar yang cukup, jadi saya mem-bookmark-nya untuk diberikan sebagai materi panduan kepada calon peneliti yang saya temui setiap tahun
Exploit ini bergantung pada akses namespace pengguna tanpa privilese:
sysctl kernel.unprivileged_userns_clone = 1Ini adalah nilai default pada kernel Debian/Ubuntu dan Arch Linux, dan jika Anda tidak membutuhkannya, misalnya untuk menjalankan perintah Docker tanpa sudo, sebaiknya dimatikan
Sandbox Chrome yang dipakai di aplikasi Electron atau 1Password juga terkait, dan binary pembantu sandbox juga bisa berjalan sebagai program setuid
Tidak mengherankan jika Proton juga mulai memakai namespace pengguna di masa depan, jadi pada Linux desktop umum mungkin lebih baik tidak mematikannya
Pada server atau Linux yang secara khusus diperkuat, mematikannya sering kali bukan pilihan yang buruk
Masalahnya, agar container “langsung bekerja”, dibutuhkan banyak hack di sisi jaringan, dan nilai jual utama Docker juga kurang lebih adalah menggantikan Anda melakukan hack berbahaya semacam itu
Pada akhirnya, solusi container apa pun menerima hack semacam itu, sehingga meskipun fitur namespace yang normal mengurangi akses, kernel justru membuka pintu karena hack jaringan
Saya tidak tahu kenapa namespace pengguna tanpa privilese diaktifkan secara default
Meski berjalan di dalam namespace “tanpa privilese”, saya mempertanyakan alasan memberi pengguna kemampuan menjalankan hal seperti iptables atau mount secara default
Misalnya Chrome memakai namespace untuk mengimplementasikan sandbox proses, tetapi memasang binary setuid-root agar tetap bisa berjalan tanpa namespace tanpa privilese
Karena binary setuid-root itu sendiri merupakan risiko keamanan, dalam jangka panjang lebih baik jika Chrome tidak perlu memasang binary seperti itu
Namun untuk itu, namespace pengguna tanpa privilese harus tersedia secara luas, dan bug seperti ini memperlambat masa depan tersebut
Selain itu, program yang membangun sandbox berbasis namespace seperti Chrome sering juga memakai seccomp, sehingga kode di dalam sandbox dicegah memakai fitur kernel yang tidak biasa seperti namespace
Pada desktop satu pengguna, manfaat menerapkan pemisahan yang kuat antara pengguna dan root tidak terlalu besar, dan sebagian besar hal yang menarik juga bisa diakses dari akun pengguna
Sebaliknya, sandbox seperti Chrome sangat penting untuk keamanan desktop, jadi pada desktop satu pengguna, mengaktifkan namespace pengguna tanpa privilese cenderung dipandang meningkatkan keamanan secara keseluruhan
Sistem multi-pengguna tentu saja cerita yang berbeda
Jika bug seperti ini tidak terus muncul, namespace pengguna tanpa hak istimewa akan menjadi fitur keamanan yang luar biasa
Misalnya, akan bagus jika menjalankan Flatpak tidak memerlukan biner setuid milik host untuk isolasi aplikasi
Sebagian besar nilai default tidak aman, dan diperlukan pengetahuan teknis serta pekerjaan hardening
Commit yang memperkenalkan masalah: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/lin...
Dalam
switch/casebersarang, adareturnpada jalur default, tetapi strukturnya tampak aneh karena setelah itu mengharapkan fall-throughhttps://lwn.net/Articles/882397/
https://bugs.launchpad.net/bugs/cve/2024-1086
Kerentanan use-after-free pada komponen
netfilter: nf_tablesdi kernel Linux memungkinkan eskalasi hak istimewa lokalFungsi
nft_verdict_init()mengizinkan nilai positif sebagai drop error di dalam putusan hook, dan akibatnyanf_hook_slow()dapat memprosesNF_DROPbersama drop error yang tampak sepertiNF_ACCEPT, sehingga bisa menimbulkan kerentanan double freeDisarankan untuk melakukan upgrade ke versi setelah
f342de4e2f33e0e39165d8639387aa6c19dff660Saya penasaran bagaimana eksploit seperti ini bisa mungkin meskipun ada mitigasi modern seperti ASLR
Di kelas universitas, saya pernah mendapat beberapa biner untuk dijalankan pada versi Ubuntu tertentu, lalu diberi tugas menemukan bug seperti use-after-free atau buffer overflow dan mengeksploitasinya; itu benar-benar sulit
Menemukan celahnya saja sulit, dan menulis shellcode yang tepat untuk melakukan sesuatu yang berguna dengan celah itu bahkan lebih sulit
Pada tahap yang lebih sulit, mitigasi seperti ASLR dan stack canary juga diaktifkan, dan bahkan dalam lingkungan mahasiswa yang terkendali pun rasanya hampir mustahil
Pada akhirnya harus 1) menemukan celah yang dapat dieksploitasi dan 2) menemukan payload biner yang tepat yang melakukan sesuatu yang berguna tanpa sekadar membuat program crash; saya jadi bertanya-tanya bagaimana itu bisa dilakukan di dunia nyata yang mestinya lebih sulit
[0] https://web.stanford.edu/class/archive/cs/cs107/cs107.1194/a...
Sambil mengambil kelas lain, waktu yang bisa dipakai untuk satu bug mungkin hanya beberapa jam hingga beberapa hari
Zerodium membayar 50 ribu dolar untuk eskalasi hak istimewa lokal Linux yang umum, dan dengan biaya developer eksploit berpengalaman, kira-kira itu bisa membeli 200 jam-orang
Artinya, para ahli menghabiskan waktu 10–100 kali lebih banyak daripada mahasiswa pemula
Bayangkan perbedaan antara orang yang baru pertama kali masuk bengkel kayu dan tukang kayu, pemula keramik dan perajin ahli, pelukis baru dan seniman profesional
Ditambah lagi, waktunya juga 10–100 kali lebih banyak
[1] https://zerodium.com/program.html
Ada teknik “klasik” untuk melewati sebagian besar proteksi terbaru, dan jika belum ada, kadang muncul serangan atau metode bypass baru
Misalnya, untuk bypass proteksi heap bisa melihat how2heap[0], ada juga contoh eksploit bypass KASLR[1], dan eksploit kali ini tampaknya menggunakan teknik dirty pagetable[2]
Polanya adalah permainan kucing dan tikus yang terus berlanjut: mitigasi ditambahkan, lalu peneliti menemukan cara melewatinya
[0] https://github.com/shellphish/how2heap
[1] https://www.willsroot.io/2022/12/entrybleed.html
[2] https://pwning.tech/nftables/#452-the-technique
Untuk menemukan hal seperti ini, satu orang dari kategori terakhir saja sudah cukup
Sekarang memang sangat sulit, dan bahkan dengan mitigasi dimatikan, menemukan kerentanan dan menulis eksploit tetap tidak mudah
Namun banyak orang yang mencari kerentanan seperti ini bekerja dalam tim, memparalelkan fuzzing, serta dapat menggabungkan atau merangkai pengetahuan dan eksploit lain
Keahlian dan bakat sebagian peneliti sungguh luar biasa, dan dalam bidang seperti ini pengalaman bertahun-tahun hingga puluhan tahun sangat bernilai
Namun jika menganggap bug besar yang ditemukan sekarang dicari oleh tim dengan pendanaan besar atau aktor negara, lebih mudah dipahami bahwa mereka dapat mengerahkan banyak tenaga dan sumber daya untuk melewati mitigasi yang ada
Menurut Ubuntu, semua rilis LTS terdampak, dan masalah ini telah diperbaiki pada kernel yang saat ini sudah dipatch: https://ubuntu.com/security/CVE-2024-1086
Focal diperbaiki pada
5.4.0-174.193, Jammy pada5.15.0-101.111, dan Mantic pada6.5.0-26.26Jika menggunakan dukungan diperpanjang, Xenial dan Bionic juga termasuk
Saya mencobanya di sistem Debian yang rentan; eskalasi hak akses tidak berhasil, tetapi pada eksekusi kedua seluruh sistem berhenti merespons
Eksekusi pertama hanya gagal begitu saja, jadi tetap sangat layak meluangkan waktu untuk melakukan patch
Pengaturan kernel saat ini dapat diperiksa di file seperti
/boot/configatau/proc/config.gz