1 poin oleh GN⁺ 2024-01-27 | 1 komentar | Bagikan ke WhatsApp
  • Commit 0226b56 pada rhboot/shim memperbaiki CVE-2023-40547, yang terjadi karena shim memercayai begitu saja nilai ukuran pada header HTTP saat menerima file
  • Jika header yang dimanipulasi menetapkan ukuran yang lebih kecil daripada data yang benar-benar diterima, shim dapat mengalokasikan ruang yang lebih kecil daripada buffer yang dibutuhkan
  • Kode sebelumnya menggunakan nilai header untuk alokasi, tetapi menggunakan metadata protokol untuk penyalinan, sehingga dapat berujung pada out-of-bounds write
  • Patch memeriksa *buf_size < rx_message.BodyLength di receive_http_response() pada httpboot.c, dan jika gagal menanganinya sebagai EFI_BAD_BUFFER_SIZE serta Invalid Content-Length
  • Cakupan perubahan adalah 7 baris ditambahkan dan 1 baris dihapus pada satu file httpboot.c, dan typo Content-Lenght juga diperbaiki menjadi Content-Length

Alur terjadinya kerentanan

  • CVE-2023-40547 adalah masalah yang terjadi saat shim mengambil file melalui HTTP atau protokol terkait
  • Dalam proses mengalokasikan buffer untuk menyimpan data yang diterima, nilai ukuran pada header HTTP digunakan
  • Header HTTP dapat dimanipulasi, dan dapat menetapkan ukuran yang lebih kecil daripada data yang benar-benar diterima
  • Alur sebelumnya memakai nilai header untuk alokasi buffer, tetapi saat menyalin data dari buffer rx, alur tersebut menggunakan metadata protokol sebagai acuan
  • Karena perbedaan ini, data yang lebih besar daripada buffer yang dialokasikan dapat disalin, dan akibatnya out-of-bounds write dapat terjadi

Isi patch

  • Patch menambahkan pemeriksaan defensif ke receive_http_response(EFI_HTTP_PROTOCOL *http, VOID **buffer, UINT64 *buf_size) di httpboot.c
  • Jika *buf_size == 0, patch memperbaiki typo pada pesan galat yang sudah ada dan berpindah ke goto error
    • Failed to get Content-LenghtFailed to get Content-Length
  • Pemeriksaan baru memeriksa kondisi *buf_size < rx_message.BodyLength
    • Jika kondisi benar, efi_status = EFI_BAD_BUFFER_SIZE ditetapkan
    • Galat Invalid Content-Length dicetak
    • Setelah itu berpindah ke goto error

Cakupan perubahan

  • File yang diubah hanya satu, yaitu httpboot.c
  • Jumlah perubahan adalah 7 baris ditambahkan dan 1 baris dihapus
  • Intinya adalah logika yang memeriksa apakah panjang body yang diterima, rx_message.BodyLength, lebih besar daripada ukuran alokasi, *buf_size

Catatan terkait

  • Commit ini ditandai sebagai perubahan yang menyelesaikan CVE-2023-40547
  • Pesan commit menyatakan bahwa masalah ini berasal dari kesalahan memercayai header HTTP
  • Pelapor kerentanan tercatat sebagai Bill Demirkapi dari Microsoft Security Response Center

1 komentar

 
GN⁺ 2024-01-27
Komentar Hacker News
  • shim adalah bootloader EFI yang umum dipakai oleh distro Linux yang ingin mengaktifkan Secure Boot
    Dari sudut pandang distro, mereka ingin memudahkan pengguna mengaktifkan Secure Boot dengan kunci tanda tangan Microsoft yang sudah tersedia secara bawaan, alih-alih membuat pengguna mendaftarkan kunci sendiri
    Namun, karena Microsoft umumnya tidak menandatangani bootloader GPL seperti GRUB, dibuatlah shim yang bisa ditandatangani dengan kunci Microsoft, dan shim memverifikasi tanda tangan target boot-nya dengan kunci terpisah yang disebut Machine Owner Key, yaitu MOK
    Saat menentukan biner EFI yang akan di-boot di shim, URL HTTP bisa diberikan, dan jika server HTTP bersifat berbahaya, hal ini dapat memicu penulisan di luar batas
    Namun, karena biasanya dipakai untuk mem-boot bootloader tahap kedua lokal seperti GRUB, pada kebanyakan instalasi kemungkinan risikonya tampak rendah
    Secure Boot sejak awal memang dirancang agar biner yang sudah ditandatangani pun bisa dicabut lewat daftar DBX, dan jika daftar ini dimasukkan ke UEFI, biner terkait akan ditolak meski memiliki tanda tangan yang valid
    Jika tanda tangan biner shim lama yang memiliki bug ini ditambahkan ke daftar tersebut, masing-masing perangkat dapat memperbarui daftarnya sendiri; daftar itu juga bisa didistribusikan melalui pembaruan kapsul seperti LVFS, dan jika Anda mengelola sendiri kunci serta variabel Secure Boot, Anda juga bisa mengunduh lalu mendaftarkan daftar tersebut dari https://uefi.org/revocationlistfile

    • Saya adalah penemu bug di tulisan asli, dan anggapan bahwa isu ini hanya bisa dieksploitasi saat menggunakan HTTP boot adalah kesalahpahaman yang umum
      Kalau memang begitu, ini tidak akan diberi peringkat Critical
      Bug ini bisa dieksploitasi secara lokal saat malware berprivilegi menimpa partisi EFI, saat melakukan serangan man-in-the-middle di jaringan sekitar yang mengaktifkan PXE boot, dan sebagai serangan man-in-the-middle jarak jauh saat memakai HTTP boot
      Penyerang jarak jauh tanpa hak akses yang berada di posisi man-in-the-middle dapat mengeksploitasinya tanpa akses langsung jika perangkat korban menggunakan HTTP boot
      Penyerang jarak jauh yang mendapatkan hak akses dan eksekusi kode di perangkat korban dapat melewati Secure Boot meskipun korban tidak memakai HTTP boot, asalkan firmware mendukung HTTP
      Misalnya, dengan mengubah variabel urutan boot untuk menunjuk ke server yang dikendalikan penyerang, atau dengan menimpa bootloader di partisi EFI menggunakan image shim dan GRUB2 yang tampak normal, lalu membuat grub.cfg melakukan chainload ke shim baru melalui HTTP
      Ini dimungkinkan karena sintaks perangkat GRUB2 dapat menentukan perangkat yang didukung, termasuk HTTP
      Selain itu, penyerang sekitar tanpa hak akses yang berada di posisi man-in-the-middle dan menghadapi perangkat korban yang memakai PXE boot dapat mengeksploitasinya dengan merangkai PXE shim → PXE GRUB2 → shim via HTTP
    • Microsoft tampaknya berpendapat bahwa jika mereka menandatangani GRUB, bootloader berlisensi GPLv3, maka GPLv3 bisa memberi pengembang hak untuk memaksa penyediaan kunci tanda tangan kepada mereka
      Sumber: https://techcommunity.microsoft.com/t5/hardware-dev-center/u...
    • Saya sempat bertanya-tanya kenapa bootloader melakukan komunikasi jaringan, tetapi penjelasan bahwa biner EFI bisa ditentukan lewat URL HTTP membuatnya masuk akal
    • Saya penasaran bagaimana shim menghindari masalah yang dikhawatirkan Microsoft
      Jika klausul anti-Tivoization GPLv3 dapat menuntut penyediaan kunci tanda tangan Secure Boot, bukankah kunci tanda tangan MOK juga harus diberikan jika diminta?
      Kalau begitu, siapa pun pada dasarnya bisa memperoleh kunci untuk menandatangani kode arbitrer yang akan di-boot secara tidak langsung melalui Secure Boot, dan saya tidak yakin itu secara bermakna berbeda dari hasil jika Microsoft langsung menerbitkan kunci tanda tangan untuk proyek GPLv3 seperti GRUB
    • Jika tujuannya adalah mem-boot bootloader tahap kedua lokal, rasanya Windows Boot Manager juga bisa menjalankan peran yang sama
      Di perangkat BIOS lama saya pernah membuat WBM melakukan chainload ke GRUB, tetapi di perangkat UEFI saya belum pernah mencobanya, jadi saya tidak tahu apakah ada hambatan tertentu
  • Anda mungkin bertanya, “Mengapa melakukan boot dari server yang tidak tepercaya atau telah dikompromikan?” atau, “Kalau servernya sudah dikompromikan, bukankah cukup mengirim biner berbahaya saja sehingga ini tidak berarti?” Singkatnya, biner yang pada akhirnya di-boot oleh shim harus ditandatangani dengan MOK
    Karena itu, baik saat boot di jaringan yang telah dikompromikan, via HTTP, maupun dari server yang telah dikompromikan, jaminan keamanannya seharusnya tetap sama terlepas dari apakah HTTPS digunakan atau tidak
    Secure Boot tidak mencegah downgrade, jadi fakta bahwa server yang dikompromikan bisa dipakai untuk serangan downgrade adalah hal terpisah dari kerentanan ini
    Perlindungan terhadap serangan downgrade memang pada akhirnya harus diimplementasikan secara terpisah dengan cara yang lebih kuat
    Meski begitu, saya tidak tahu mengapa shim perlu mendukung HTTP boot secara langsung
    Ini bisa saja ditangani oleh biner EFI lokal kedua yang ditandatangani dengan MOK, tetapi mungkin fitur itu dianggap relatif sederhana untuk diimplementasikan

  • Saya tidak paham mengapa kode ini memperlakukan panjang body dengan dua acuan berbeda
    Menurut RFC, dalam HTTP/1.1 Content-Length adalah informasi otoritatif tentang panjang body permintaan/respons HTTP
    Data yang berada di jalur setelah panjang itu, secara definisi, adalah bagian dari pesan lain
    Sebaliknya, jika Content-Length lebih besar daripada rx_message.BodyLength, artinya seluruh pesan belum diterima, jadi harus menunggu lagi atau memunculkan error timeout
    Dalam kedua kasus, jika tidak ada jaminan bahwa rx_message.BodyLength sama dengan Content-Length, berarti nilainya salah
    Jika ingin menanganinya dengan lebih longgar, tidak ada alasan untuk melihat header Content-Length; cukup gunakan rx_message.BodyLength sebagai ukuran buffer dan tafsirkan semua data di jalur sebagai pesan yang diterima
    Kode saat ini rumit tanpa perlu, dan bug seperti ini pun masuk dengan cara seperti itu

    • Jika hanya melihat commit tersebut secara terpisah, mudah untuk salah paham
      Dari kode di sekitarnya https://github.com/rhboot/shim/blob/0226b56513b2b8bd5fd281bc... terlihat bahwa di dalam loop, potongan data diterima dan setiap kali diperiksa apakah data baru melebihi kapasitas buffer yang ditentukan oleh Content-Length
      Namun sebelumnya, pemeriksaan itu tidak dilakukan untuk pembacaan pertama di luar loop, dan itulah bug-nya
      Meski begitu, saya tidak melihat ada kode yang melakukan pemeriksaan akhir bahwa ukuran yang diunduh sama dengan *buf_size, yaitu Content-Length
      Jika kondisi ini gagal, itu bisa menjadi sinyal bahwa koneksi ditutup terlalu cepat
  • Ini jelas bug dan syukurlah sudah diperbaiki, tetapi saya juga bertanya-tanya siapa yang men-boot perangkatnya dari host yang tidak tepercaya
    Jika penyerang sudah menguasai layanan HTTP sampai bisa mengirim header berbahaya, menghindari overflow ini adalah masalah yang paling kecil; sertifikat pun sudah disusupi, dan mereka juga bisa menyisipkan malware ke payload yang sesuai spesifikasi lalu mengirimkannya
    Ini memang bug, tetapi saya tidak yakin ini layak disebut Critical

    • Orang-orang yang mendorong Secure Boot juga termasuk golongan serupa
      Mereka sungguh percaya pada strategi keamanan bahwa semua hal yang berpotensi dikompromikan tidak boleh tidak ditandatangani oleh Secure Boot
      Jika ada satu saja sesuatu yang ditandatangani namun rentan, itu bisa dipakai untuk mendekripsi disk terenkripsi Secure Boot+TPM milik semua orang
      Sulit memahami mengapa pendekatan seperti ini dianggap sebagai model keamanan yang valid, dan kerentanan seperti ini sudah sangat banyak
      Selain itu, Windows, si gajah di dalam ruangan, sepenuhnya diabaikan
      Contoh pola pikir seperti ini: https://lkml.org/lkml/2018/4/3/767
      Terlepas dari kekhawatiran Linus, pada banyak distro mode integritas benar-benar aktif saat boot dengan Secure Boot
      Mungkin karena kebijakan Microsoft dan situasi di mana distro dipaksa mengikuti prosedur yang dijelaskan di thread tersebut demi mendapatkan tanda tangan Microsoft UEFI
      Akibatnya, saat Secure Boot diaktifkan, fitur distro biasanya dibatasi, misalnya tidak bisa memakai hibernasi
    • Pertahanan yang baik hanyalah pertahanan berlapis seperti defense in depth, dan bug ini membuat lubang pada salah satu lapisannya
    • Ini juga bisa dipakai untuk membobol sebagian perangkat yang terkunci
    • Jika melihat penjelasan yang sangat bagus di thread lain https://news.ycombinator.com/item?id=39135275, ini bisa dianggap Critical karena vektor serangannya tidak terbatas pada HTTP
  • Saat sesuatu yang penting sedang terjadi, pakailah HTTP yang ada S-nya
    Booting perangkat juga termasuk di sini, dan header HTTPS sejak awal selalu terenkripsi
    Meski begitu, bug ini ditemukan dengan baik

    • HTTPS tidak relevan di sini
      Header yang salah tetap bisa dikirim dalam kedua kasus
    • Saya tidak yakin HTTPS memungkinkan untuk penggunaan ini
      Karena enkripsi membutuhkan waktu dan tanggal yang akurat
      RTC mungkin valid, tetapi saya juga tidak tahu apakah penanganan zona waktunya benar, dan bagaimanapun waktunya bisa saja meleset
    • Ini tidak ada hubungannya dengan ada atau tidaknya S
      Sepertinya Anda belum memahami masalahnya dengan benar
  • Content-length bukan panjang body yang sebenarnya, melainkan panjang setelah Content-encoding

    • “HTTP/1.1 itu protokol yang sangat menyenangkan dan sederhana kalau sebagian besarnya diabaikan”
  • Apakah build shim ini menyertakan httpboot?
    Setahu saya shim hanya untuk menjalankan binary EFI lain di disk, dan saya rasa saya belum pernah melihat fitur network boot milik shim benar-benar dipakai

  • Mungkin saya yang kurang paham, tetapi saya kira sebagian besar klien HTTP hanya membaca sampai Content-Length yang ditentukan, dan jika byte yang terbaca lebih sedikit daripada Content-Length maka dianggap error

    • Klien HTTP disediakan oleh UEFI sebagai driver EFI
      Menurut saya spesifikasi UEFI tampaknya tidak secara spesifik menentukan perilaku saat header Content-Length dan panjang body respons tidak cocok
      Jadi sangat mungkin beberapa implementasi hanya membuat permintaan connection:close dan tidak memeriksa Content-Length
      Kerentanan ini dilaporkan oleh MSRC dan deskripsi CVE tidak membahas eksploitasi nyata
      Mungkin nanti akan diungkap, atau mungkin ini hanya masalah teoretis
  • Bisa jelaskan mengapa membaca lebih sedikit dari panjang body yang sebenarnya itu berbahaya?
    Saya justru mengira kebalikannya yang berbahaya

    • Saat mengambil file melalui HTTP atau protokol terkait, shim mencoba mengalokasikan buffer untuk menyimpan data yang diterima
      Namun ukurannya diambil dari header HTTP yang bisa dimanipulasi, dan penyerang bisa menentukan ukuran yang lebih kecil daripada data yang diterima
      Dalam kasus ini, kode memakai nilai header untuk alokasi, tetapi saat menyalin dari buffer penerimaan menggunakan ukuran dari metadata protokol, sehingga terjadi penulisan di luar batas
    • Dari penjelasannya, buffer dialokasikan berdasarkan Content-Length, tetapi kemudian data disalin sebanyak ukuran buffer yang benar-benar diterima, sehingga penulisan keluar dari batas alokasi pun terjadi