Zenbleed: Bagaimana pencarian kinerja CPU dapat membahayakan kata sandi Anda

Zenbleed: Bagaimana pencarian kinerja CPU dapat membahayakan kata sandi Anda

Node Sumber: 2184757

Ingat Heartbleed?

Itu adalah bug, pada tahun 2014, yang memperkenalkan sufiks -berdarah untuk kerentanan itu membocorkan data secara sembarangan cara yang tidak dapat dikontrol oleh penyerang maupun korban.

Dengan kata lain, penjahat tidak dapat menggunakan bug gaya berdarah untuk serangan presisi, seperti “Temukan file kata sandi bayangan di /etc direktori dan unggah ke saya,” atau “Cari mundur dalam memori hingga 16 digit ASCII berturut-turut pertama kali dijalankan; itu nomor kartu kredit, jadi simpanlah untuk nanti.”

Di Heartbleed, misalnya, Anda dapat mengelabui server yang belum ditambal agar mengirimkan pesan yang seharusnya berukuran paling banyak 16 byte, tetapi itu salah memasukkan hingga sekitar 64,000 byte tambahan yang ditempelkan di bagian akhir.

Anda tidak dapat memilih apa yang ada di dalam 64,000 byte yang dijarah itu; Anda baru saja mendapatkan apa pun yang kebetulan berada di dekat memori dengan pesan asli yang seharusnya Anda terima.

You might get chunks of all zeros, or unknown encrypted data for which you don’t have the decryption key…

…tetapi kadang-kadang Anda akan mendapatkan fragmen teks-jelas sisa dari halaman web yang diunduh pengunjung sebelumnya, atau bagian dari email yang baru saja dikirim orang lain, atau bahkan blok memori dengan kunci kriptografis pribadi milik server di dalamnya.

Banyak jarum di tumpukan jerami yang tak ada habisnya

Penyerang biasanya mengeksploitasi bug berbasis bleed hanya dengan memicunya berulang kali secara otomatis, mengumpulkan tumpukan besar data yang tidak sah, lalu menyisirnya nanti di waktu senggang mereka.

Jarum ternyata sangat mudah diambil dari tumpukan jerami jika (a) Anda dapat mengotomatiskan pencarian dengan menggunakan perangkat lunak untuk melakukan kerja keras untuk Anda, (b) Anda tidak memerlukan jawaban segera, dan (c) Anda punya banyak dan banyak tumpukan jerami, sehingga Anda dapat melewatkan banyak atau bahkan sebagian besar jarum dan masih mendapatkan simpanan yang cukup besar.

Bug bernama berdarah lainnya termasuk Mengoceh, yang dengan sengaja memicu kesalahan memori sementara untuk menebak apa yang disimpan di bagian terdekat dari chip RAM, dan Pilihan berdarah, di mana Anda dapat menanyakan server web berulang kali tentang opsi HTTP mana yang didukungnya, hingga Anda tidak sengaja mengirimkan balasan dengan data orang lain di dalamnya.

In analogy, a bleed-style bug is a bit like a lottery that doesn’t have any guaranteed mega-jackpot prizes, but where you get a sneaky chance to buy 1,000,000 tickets for the price of one.

Ya, pemburu bug Google terkenal Tavis Ormandy baru saja melaporkan bug baru semacam ini yang dia dijuluki Zenbleed, karena bug berlaku untuk AMD terbaru Zen 2 jajaran prosesor berperforma tinggi.

Sayangnya, Anda dapat mengeksploitasi bug dari hampir semua proses atau utas di komputer dan secara acak mengeluarkan data dari hampir semua tempat di memori.

Misalnya, program yang berjalan sebagai pengguna yang tidak memiliki hak istimewa di dalam mesin virtual tamu (VM) yang seharusnya ditutup dari bagian sistem lainnya mungkin berakhir dengan data dari pengguna lain di VM yang sama, atau dari VM lain di tempat yang sama. komputer, atau dari program host yang seharusnya mengendalikan VM, atau bahkan dari kernel sistem operasi host itu sendiri.

Ormandy mampu membuat kode proof-of-concept yang membocorkan sekitar 30,000 byte data orang lain per detik per inti prosesor, 16 byte sekaligus.

Kedengarannya tidak banyak, tetapi 30KB/dtk cukup untuk mengungkap 3GB kekalahan sepanjang hari, dengan data yang diakses lebih teratur (termasuk kata sandi, token autentikasi, dan data lain yang seharusnya dirahasiakan) mungkin muncul berkali-kali.

Dan dengan data yang diekspos dalam potongan 16-byte, penyerang cenderung menemukan banyak fragmen yang dapat dikenali dalam informasi yang ditangkap, membantu mereka menyaring dan menyortir tumpukan jerami dan fokus pada jarum.

Harga kinerja

Kami tidak akan mencoba menjelaskan kelemahan Zenbleed di sini (silakan lihat Tavis Ormandy's artikel sendiri untuk perincian), tetapi kami akan fokus pada alasan mengapa bug muncul di tempat pertama.

Seperti yang mungkin sudah Anda duga, mengingat bahwa kami telah menyinggung proses, utas, inti, dan manajemen memori, bug ini adalah efek samping dari "fitur" internal yang dikemas oleh prosesor modern untuk meningkatkan kinerja sebanyak mungkin. , termasuk trik rapi tapi rawan bug yang dikenal dalam perdagangan sebagai eksekusi spekulatif.

Secara umum, ide di balik eksekusi spekulatif adalah bahwa jika inti prosesor tidak akan digunakan, mungkin menunggu untuk mengetahui apakah inti seharusnya turun. THEN atau itu ELSE jalur keputusan if-then-else dalam program Anda, atau menunggu pemeriksaan kontrol akses perangkat keras untuk menentukan apakah benar-benar diizinkan untuk menggunakan nilai data yang disimpan di alamat memori tertentu atau tidak…

… maka itu layak untuk dibajak, dan dihitung terlebih dahulu (itulah bagian "eksekusi spekulatif") jika jawabannya berguna.

Jika jawaban spekulatif ternyata tidak perlu (karena berhasil THEN hasil ketika kode turun ELSE path sebagai gantinya), atau berakhir terlarang untuk proses saat ini (dalam kasus pemeriksaan akses yang gagal), itu dapat dibuang begitu saja.

Anda dapat memikirkan eksekusi spekulatif seperti pembawa acara kuis yang mengintip jawaban di bagian bawah kartu saat mereka mengajukan pertanyaan saat ini, dengan asumsi bahwa kontestan akan mencoba menjawab dan mereka harus langsung merujuk ke jawabannya. jauh.

Namun dalam beberapa acara kuis, kontestan dapat mengatakan "Lulus", melewatkan pertanyaan dengan maksud untuk kembali lagi nanti.

Jika itu terjadi, tuan rumah perlu mengesampingkan jawaban yang tidak terpakai, dan melanjutkan dengan pertanyaan berikutnya, dan selanjutnya, dan seterusnya.

Tetapi jika pertanyaan yang "dilewati" muncul lagi, seberapa besar fakta bahwa mereka sekarang mengetahui jawabannya sebelumnya akan memengaruhi cara mereka menanyakannya untuk kedua kalinya?

Bagaimana jika mereka secara tidak sengaja membaca pertanyaan secara berbeda, atau menggunakan nada suara yang berbeda yang mungkin memberikan petunjuk yang tidak diinginkan kepada kontestan?

Lagi pula, satu-satunya cara yang benar untuk "melupakan" sesuatu adalah dengan tidak pernah mengetahuinya sejak awal.

Masalah dengan vektor

Dalam bug Zenbleed Ormandy, sekarang secara resmi dikenal sebagai CVE-2023-20593, masalah muncul ketika prosesor AMD Zen 2 menjalankan instruksi khusus yang ada untuk mengatur banyak hal yang disebut register vektor menjadi nol pada saat yang bersamaan.

Register vektor digunakan untuk menyimpan data yang digunakan oleh instruksi pemrosesan data dan numerik kinerja tinggi khusus, dan di sebagian besar prosesor Intel dan AMD modern, register vektor berukuran lebar 256 bit, tidak seperti register tujuan umum CPU 64 bit yang digunakan untuk tujuan pemrograman tradisional. .

Register vektor khusus ini biasanya dapat dioperasikan pada 256 bit (32 byte) sekaligus, atau hanya 128 bit (16 byte) sekaligus.

Faktanya, karena alasan historis, CPU saat ini memiliki dua rangkaian instruksi kode mesin bergaya vektor yang sama sekali berbeda: sekelompok baru yang dikenal sebagai AVX (ekstensi vektor lanjutan), yang dapat bekerja dengan 128 atau 256 bit, dan kelompok instruksi yang lebih tua dan kurang kuat yang disebut SSE (streaming ekstensi SIMD, di mana SIMD pada gilirannya berarti satu instruksi/banyak data), yang hanya dapat bekerja dengan 128 bit sekaligus.

Mengganggu, jika Anda menjalankan beberapa kode AVX gaya baru, kemudian beberapa kode SSE gaya lama, dan kemudian beberapa kode AVX lainnya, instruksi SSE di tengah mengacaukan 128 bit teratas dari register AVX 256-bit yang ketinggalan zaman, meskipun instruksi SSE, setidaknya di atas kertas, hanya melakukan perhitungannya pada 128 bit terbawah.

So the processor secretly saves the top 128 bits of the AVX registers before switching into backwards-compatible SSE mode, and then quietly restores the saved values when you next start using AVX instructions, thus avoiding any unexpected side-effects from mixing old and new vector code.

Tetapi proses simpan-dan-pulihkan ini merusak kinerja, yang keduanya Intel dan AMD panduan pemrograman memperingatkan Anda tentang sangat.

AMD berkata:

Ada penalti yang signifikan untuk menggabungkan instruksi SSE dan AVX ketika 128 bit teratas dari register YMM [256-bit-wide] berisi data bukan nol.

Transisi ke salah satu arah akan menyebabkan micro-fault menumpahkan atau mengisi 128 bit atas dari keenam belas register YMM.

Akan ada penalti sekitar 100 siklus untuk memberi sinyal dan menangani kesalahan ini.

Dan Intel mengatakan hal serupa:

The hardware saves [and restores] the contents of the upper 128 bits of the [256-bit-wide] YMM registers when transitioning from AVX to SSE, and then restores these values when transitioning back […]

Operasi simpan dan pulihkan keduanya menyebabkan penalti yang berjumlah beberapa puluh siklus jam untuk setiap operasi.

Untuk menghemat hari, ada instruksi vektor khusus yang disebut VZEROUPPER yang membidik 128 bit teratas dari setiap register vektor sekaligus.

Dengan menyebut VZEROUPPER, bahkan jika kode Anda sendiri tidak benar-benar membutuhkannya, Anda memberi sinyal ke prosesor bahwa Anda tidak lagi peduli dengan 128 bit teratas dari register 256-bit tersebut, sehingga mereka tidak perlu menyimpan jika instruksi SSE jadul datang bersama selanjutnya.

Ini membantu mempercepat kode Anda, atau setidaknya menghentikan Anda memperlambat kode orang lain.

Dan jika ini terdengar seperti sedikit kludge…

… yah, memang begitu.

Ini adalah peretasan tingkat prosesor, jika Anda suka, hanya untuk memastikan bahwa Anda tidak mengurangi kinerja dengan mencoba memperbaikinya.

Di mana CVE-2023-20593 masuk?

Semua fiksasi kinerja ini membawa Ormandy ke lubang kebocoran data Zenbleed, karena:

  • Kode AVX sangat umum digunakan untuk tujuan non-matematis, seperti bekerja dengan teks. Misalnya, perpustakaan pemrograman Linux yang populer glibc menggunakan instruksi dan register AVX untuk mempercepat fungsi strlen() yang digunakan untuk menemukan panjang string teks di C. (Berbicara secara longgar, strlen() menggunakan kode AVX memungkinkan Anda mencari melalui 16 byte string sekaligus mencari byte nol yang menunjukkan di mana itu berakhir, alih-alih menggunakan loop konvensional yang memeriksa byte demi byte.)
  • Prosesor Zen 2 AMD tidak dapat diurungkan dengan andal VZEROUPPER ketika jalur kode eksekusi spekulatif gagal. Saat "menghapus nol" 128 bit teratas dari register 256-vektor karena prosesor salah menebak dan VZEROUPPER operasi perlu dibalik, register terkadang berakhir dengan 128 bit (16 byte) "dipulihkan" dari kode AVX orang lain, bukan data yang sebenarnya ada sebelumnya.

Dalam kehidupan nyata, tampaknya programmer jarang menggunakannya VZEROUPPER dengan cara yang perlu dibalik, atau bug ini mungkin telah ditemukan bertahun-tahun yang lalu, bahkan mungkin selama pengembangan dan pengujian di AMD sendiri.

Namun dengan bereksperimen secara hati-hati, Ormandy menemukan cara membuat loop kode AVX yang tidak hanya berulang kali memicu eksekusi spekulatif dari VZEROUPPER instruksi, tetapi juga secara teratur memaksa instruksi itu untuk dibatalkan dan register AVX "tidak nol".

Sayangnya, banyak program konvensional lainnya yang banyak menggunakan instruksi AVX, bahkan jika itu bukan jenis aplikasi seperti game, alat rendering gambar, cracker kata sandi, atau cryptominer yang Anda harapkan membutuhkan kode bergaya vektor berkecepatan tinggi.

Sistem operasi Anda, klien email, browser web, server web, editor kode sumber, jendela terminal – hampir semua program yang Anda gunakan secara rutin – hampir pasti menggunakan kode AVX yang adil untuk meningkatkan kinerja.

Jadi, bahkan dalam kondisi yang sangat umum, Ormandy terkadang berakhir dengan sisa-sisa data program lain yang tercampur ke dalam data AVX-nya sendiri, yang dapat dideteksi dan dilacaknya.

Lagi pula, jika Anda tahu apa yang seharusnya ada di register AVX setelah a VZEROUPPER operasi dibatalkan, mudah dikenali ketika nilai dalam register tersebut salah.

Dalam kata-kata Ormandy sendiri:

[B] operasi asic seperti strlen(), memcpy() dan strcmp() [temukan panjang string teks, salin memori, bandingkan string teks] akan menggunakan register vektor – sehingga kami dapat secara efektif memata-matai operasi yang terjadi di mana pun di sistem!

Tidak masalah jika itu terjadi di mesin virtual lain, kotak pasir, wadah, proses, apa pun.

Seperti yang kami sebutkan sebelumnya, jika Anda memiliki kumpulan harian 3GB data hantu yang dipilih secara acak dan tidak terstruktur per inti CPU, Anda mungkin tidak mendapatkan lotre yang setara dengan jackpot jutaan dolar.

Tetapi Anda hampir pasti memenangkan hadiah yang setara dengan ribuan $1000, tanpa mengambil risiko mencampuri proses dan halaman memori orang lain seperti yang perlu dilakukan oleh malware tradisional “pengintaian RAM”.

Apa yang harus dilakukan?

CVE-2023-20593 diungkapkan secara bertanggung jawab, dan AMD telah memproduksi a tambalan mikrokode untuk mengurangi cacat tersebut.

Jika Anda memiliki CPU keluarga Zen 2 dan Anda khawatir dengan bug ini, bicarakan dengan vendor motherboard Anda untuk informasi lebih lanjut tentang cara mendapatkan dan menerapkan perbaikan yang relevan.

Pada sistem operasi dengan perangkat lunak yang mendukung tweaking yang disebut MSR (register khusus model) di prosesor Anda yang mengontrol konfigurasi tingkat rendahnya, ada flag tidak berdokumen (bit 9) yang dapat Anda atur dalam register model yang tidak terdokumentasi dengan baik (MSR 0xC0011029) yang tampaknya mematikan perilaku yang menyebabkan bug.

MSR 0xC0011029 dirujuk dalam milis kernel Linux arsip sebagai DE_CFG register, rupanya kependekan dari dekode konfigurasi, dan bit terkenal lainnya dalam register ini digunakan untuk mengatur aspek lain dari eksekusi spekulatif.

Karena itu kami menebak itu DE_CFG[9], yang merupakan kependekan dari "bit 9 of MSR 0xC0011029", memutuskan apakah mengizinkan instruksi dengan efek samping kompleks seperti VZEROUPPER untuk dicoba secara spekulatif sama sekali.

Jelas, jika Anda tidak pernah mengizinkan prosesor untuk meniadakan register vektor kecuali Anda sudah tahu pasti bahwa Anda tidak perlu "menghapus nol" register tersebut dan membatalkan perubahan, bug ini tidak akan pernah dapat dipicu.

Fakta bahwa bug ini tidak terlihat sampai sekarang menunjukkan bahwa eksekusi spekulatif di dunia nyata VZEROUPPER tidak terlalu sering terjadi, sehingga peretasan/perbaikan tingkat rendah ini sepertinya tidak akan berdampak nyata pada kinerja.

Artikel Ormandy menyertakan deskripsi tentang cara mengonfigurasi ulang bit MSR yang relevan di prosesor Zen 2 Anda di Linux dan FreeBSD.

(Kamu akan lihat DE_CFG[9] digambarkan sebagai a sedikit ayam, jargon untuk pengaturan konfigurasi yang Anda putar on berbalik lepas fitur yang Anda takuti.)

OpenBSD, kami dengar, akan memaksa DE_CFG[9] aktif secara otomatis pada semua prosesor Zen 2, sehingga menekan bug ini secara default untuk mencari keamanan atas kinerja; pada Linux dan BSD lainnya, Anda dapat melakukannya dengan alat baris perintah (diperlukan root) seperti wrmsr dan cpucontrol.

Mac pengguna dapat bersantai karena semua Mac non-ARM memiliki chip Intel, sejauh yang kami tahu, daripada yang AMD, dan prosesor Intel tidak diketahui rentan terhadap bug khusus ini.

Windows pengguna mungkin perlu menggunakan peretasan driver kernel tidak resmi (hindari ini kecuali Anda benar-benar tahu apa yang Anda lakukan, karena risiko keamanan boot dalam mode "izinkan driver lama"), atau untuk menginstal debugger WinDbg resmi, aktifkan debugging kernel lokal, dan gunakan skrip WinDbg untuk men-tweak MSR yang relevan.

(Kami mengakui bahwa belum mencoba salah satu dari mitigasi ini, karena kami tidak memiliki komputer berbasis AMD saat ini; beri tahu kami bagaimana Anda melakukannya jika Anda melakukannya!)


Stempel Waktu:

Lebih dari Keamanan Telanjang