1 poin oleh GN⁺ 3 jam lalu | 1 komentar | Bagikan ke WhatsApp
  • Sejak Linux 6.9, alat yang mengunci drive saat laptop masuk suspend gagal secara diam-diam, sehingga kunci enkripsi disk penuh LUKS tetap berada di memori
  • Penyebabnya adalah interaksi tak terduga antara refactoring akses block device yang masuk ke Linux 6.9 pada Mei 2024 dan kode enkripsi; perbaikan yang diusulkan berupa patch satu baris
  • Masalah ini tidak terlihat saat shutdown penuh, tetapi pada suspend-to-RAM kunci tetap tertinggal, sehingga penyerang yang mendapatkan laptop dalam keadaan menyala bisa mengambil kunci dari RAM
  • Temuan ini bermula saat merapikan port NixOS dari cryptsetup-suspend Debian dan melihat entri /proc/keys; dump memori QEMU kemudian memastikan volume key yang seharusnya terhapus masih tertinggal
  • Uji integrasi NixOS dan patch peringatan untuk cryptsetup telah diusulkan; fitur keamanan seperti penghapusan kunci tepat sebelum suspend mudah luput saat gagal bila tampak normal tetapi tidak ada verifikasi memori nyata

Masalah kunci LUKS yang tertinggal saat suspend sejak Linux 6.9

  • Sejak Linux 6.9, yaitu Mei 2024, alat yang mengunci drive saat laptop masuk suspend gagal secara diam-diam
  • Enkripsi disk penuh LUKS digunakan untuk melindungi data ketika laptop hilang, disita, atau dicuri, tetapi dalam kasus ini kunci enkripsi tetap berada di memori selama suspend
  • Saat shutdown penuh fungsinya masih berjalan, tetapi dampaknya lebih besar karena banyak orang lebih sering membiarkan laptop dalam mode suspend-to-RAM daripada mematikannya sepenuhnya
  • Jika seseorang mendapatkan laptop dalam keadaan menyala, kunci yang tertinggal di memori berpotensi terekspos
  • VeraCrypt disebut sebagai perangkat lunak dengan tujuan serupa di Windows, tetapi kemudian dalam komentar dikoreksi bahwa “canonical software” bukan berarti perangkat lunak yang paling banyak dipakai, melainkan rekomendasi representatif di bidang keamanan TI

Penyebab dan patch satu baris

  • Penyebabnya adalah commit refactoring kernel Linux md: port block device access to file
    • Perubahan itu sendiri merupakan refactoring yang masuk akal dan berguna, tetapi memicu interaksi jarak jauh dengan kode enkripsi
  • Perbaikan yang diusulkan adalah patch satu baris
  • Penulis patch menyatakan bahwa tanpa verifikasi formal, ia tidak bisa mengatakan patch ini benar dan tidak memiliki interaksi jarak jauh lainnya
  • Upaya lanjutan untuk mencegah terulangnya masalah ini juga muncul

Proses penemuan

  • Titik awalnya adalah pekerjaan merapikan port NixOS dari cryptsetup-suspend Debian
  • Baik versi asli Debian maupun port NixOS memiliki race condition yang merepotkan tetapi tidak berbahaya, yang kadang membuat laptop gagal masuk sleep
  • Untuk mengatasinya, penulis mencoba menghidupkan kembali patch kernel Pali Rohár yang belum digabung, yaitu patch penghapusan kunci dm-crypt saat suspend/hibernation
  • Dalam proses itu, saat menelusuri source code cryptsetup dan kernel, ditemukan bahwa menurut dokumentasi keyring melekat pada thread pemanggil dan dihapus saat thread berakhir
  • Namun, entri terlihat di /proc/keys, yang sebelumnya tidak diketahui, dan hal ini menimbulkan kecurigaan
  • Akhirnya sebuah mesin virtual QEMU dijalankan dan memorinya di-dump, lalu dipastikan bahwa LUKS volume key yang seharusnya sudah terhapus ternyata masih tetap ada

Proyek secure suspend-to-RAM NixOS

  • Proyek secure-suspend yang dipublikasikan secara terpisah menyediakan secure suspend-to-RAM eksperimental untuk NixOS
  • Pada enkripsi disk penuh biasa, saat laptop berada dalam kondisi suspend, kunci tetap berada di memori sehingga bisa rentan terhadap cold boot attack atau metode kebocoran RAM
  • Proyek ini menghidupkan kembali patch kernel lama dari Pali Rohár untuk menghapus kunci enkripsi LUKS saat suspend
  • Terinspirasi dari cryptsetup-suspend Debian, tetapi memakai patch kernel untuk menghindari race condition yang kadang membuat laptop gagal tidur, serta menambahkan tindakan pencegahan tambahan
  • Mendukung sepenuhnya root filesystem terenkripsi dan juga menyediakan uji integrasi
  • Patch kernel dan alat user space dapat disesuaikan untuk distribusi Linux lain
  • Proyek ini dipublikasikan sebagai secure-suspend

Mengapa verifikasi keamanan suspend sulit

  • Munculnya lock screen setelah suspend tidak berarti perangkat penyimpanan benar-benar terkunci
  • Jika disk bisa langsung diakses segera setelah bangun dari suspend, itu berarti perangkat penyimpanan sejak awal tidak dalam keadaan terkunci
    • Misalnya, akses disk bisa diperiksa dengan skrip yang terus berjalan di balik lock screen
    • Jika koneksi SSH dengan public key memungkinkan tanpa terlebih dahulu membuka perangkat penyimpanan terenkripsi, mudah untuk memastikan bahwa perangkat penyimpanan tidak terkunci
  • Ada juga komentar bahwa konfigurasi default Ubuntu atau Debian sama sekali tidak mencoba menyediakan perlindungan seperti ini
  • Apakah upaya mengunci perangkat penyimpanan benar-benar berjalan dengan benar harus diverifikasi secara terpisah
    • Timestamp log bisa dibuat sebelum suspend tetapi baru tercatat setelah wake
    • Sebaliknya, log yang dibuat segera setelah wake sebelum waktu sistem disesuaikan bisa terlihat seperti waktu saat suspend
  • Apakah penguncian perangkat penyimpanan terjadi tepat sebelum suspend atau tepat setelah resume mungkin terlihat sama bagi pengguna, tetapi sangat berbeda secara menentukan dari sisi keamanan
  • Uji integrasi NixOS dilakukan dengan mem-boot sistem di mesin virtual dan men-dump memori untuk memastikan apakah kunci benar-benar dihapus saat suspend

1 komentar

 
GN⁺ 3 jam lalu
Komentar Hacker News
  • Ini memang bug yang menarik, tetapi judulnya terasa agak clickbait
    Setahu saya, cryptsetup luksSuspend lebih merupakan ekstensi buatan Debian daripada fitur yang didukung secara resmi, jadi sepertinya regresi ini juga hanya memengaruhi Debian
    Saya kurang yakin apakah pantas menyalahkan kernel untuk fitur yang tidak didukung atau diuji secara luas
    Meski begitu, ini tetap mengesankan, dan bagus bahwa sekarang ada pengujian agar regresi ini tidak muncul lagi. Saya juga setuju dengan pendapat OP bahwa NixOSTests memang sangat hebat
    Namun, dari judulnya saja masalah ini terlihat seperti isu yang tersebar luas, bukan sesuatu yang hanya mengenai satu distro tertentu

    • Saya memang mengincar judul yang akurat secara teknis dan tidak berniat memancing klik
      Benar. Ini tidak memengaruhi orang yang memakai konfigurasi bawaan, karena sejak awal mereka tidak akan berharap kunci volume tetap aman selama suspend
      Solusi Debian telah di-port ke beberapa, mungkin sebagian besar, distro lain, dan kemungkinan ada cukup banyak orang yang mempertahankan port mereka sendiri
      Halaman manual thread-keyring(7) menjanjikan bahwa “thread keyring dihancurkan saat thread yang mereferensikannya berakhir”
      Proyek cryptsetup bergantung pada sifat ini dalam mekanisme memindahkan kunci dari ruang pengguna ke ruang kernel, dan kernel 6.9 memperkenalkan regresi yang merusak sifat tersebut
    • Saya bingung mengapa ini disebut khusus Debian. luksSuspend adalah fitur upstream dan ditambahkan pada rilis v1.1.0 tahun 2009
      Saya pernah sesekali memakainya di Arch dan openSUSE dulu, dan fitur ini jelas ada juga di distro selain Debian
      Mungkin yang dimaksud adalah integrasi otomatis dengan system suspend, tetapi itu melenceng dari inti persoalan. luksSuspend didokumentasikan menghapus kunci dari memori sistem, dan perilaku itu berhenti bekerja karena patch refaktorisasi di Linux 6.9
      Namun, secara praktik ini juga bisa dilihat sebagai bug di sisi cryptsetup. Alasannya, ia bergantung pada perilaku masa hidup yang sangat spesifik dari kunci keyring kernel, dan bisa juga diperdebatkan bahwa penghapusan seharusnya dilakukan lebih eksplisit dari ruang pengguna
      [1]: https://gitlab.com/cryptsetup/cryptsetup/-/commit/3cea5dcc7b...
      [2]: https://gitlab.com/cryptsetup/cryptsetup/-/blob/main/docs/v1...
      [3]: https://gitlab.com/cryptsetup/cryptsetup/-/merge_requests/93...
    • Subperintahnya ada di repositori resmi cryptsetup dan penjelasannya tampak benar: https://gitlab.com/cryptsetup/cryptsetup/-/blob/main/man/cry...
    • Saya pernah memakai fitur ini di Arch, dan ini bisa digunakan juga pada LUKS secara umum. Hanya saja, setahu saya ini tidak dipakai secara default saat suspend
      Mungkin yang dimaksud adalah perangkat yang setelah luksSuspend benar-benar menjalankan suspend RAM dengan cara yang berguna, dan itu awalnya ditujukan untuk Debian lalu kemudian hadir juga di Arch, tetapi di keduanya bukan pengaturan bawaan
    • Saya penasaran Debian mulai mendistribusikan 6.9 sejak versi berapa
  • Saya tidak melihat banyak alternatif lain. Jika melakukan suspend, yakni RAM suspend, semuanya disimpan di RAM dan terenkripsi, tetapi setahu saya kunci master tetap berada di memori kernel
    Sebaliknya, jika melakukan hibernate, yakni suspend ke disk, seluruh isi RAM termasuk kunci master ditulis ke disk dan dienkripsi, lalu RAM dibersihkan
    Saat dibangunkan kembali, Anda harus memasukkan passphrase lagi untuk mendekripsi kunci master dan memuat kembali isi disk ke memori

    • Benar. Di sebagian besar distro Linux bawaan, jika Anda langsung men-suspend laptop, semua hal termasuk kunci master tetap berada di memori
      Namun Debian lebih dulu membuat add-on opsional cryptsetup-suspend, yang menjalankan perintah luksSuspend yang seharusnya menghapus kunci dari memori lalu meminta passphrase lagi saat resume
      Hingga kernel 6.8 ini bekerja sesuai penjelasan, tetapi mulai kernel 6.9 diam-diam berhenti berfungsi
    • CPU Intel/AMD dalam sekitar 5 tahun terakhir sama-sama mendukung enkripsi seluruh memori yang transparan bagi sistem operasi
      Jika fitur ini diaktifkan, serangan cold boot menjadi masalah masa lalu. Biasanya fitur ini tidak aktif secara default hanya karena menurunkan kecepatan RAM sekitar 0,5%
  • Karena setelah Sleep tidak perlu memasukkan lagi kata sandi boot, jelas kunci enkripsi masih ada di memori

    • Jelas distro tersebut tidak memakai cryptsetup-luksSuspend
  • Ini bukan masalah yang terlalu saya khawatirkan
    Satu-satunya alasan saya memakai enkripsi disk adalah agar saat menjual laptop, saya tidak perlu khawatir ada orang mengobrak-abrik dokumen pajak atau informasi kartu kredit
    Tentu laptopnya juga saya hapus, tetapi jika datanya terenkripsi di level drive, menurut saya risikonya sangat kecil untuk dipulihkan lagi dengan alat forensik dan sejenisnya

    • Sebagai kompromi yang cukup masuk akal, cukup hapus saja header LUKS
      LUKS memakai algoritme anti-forensik yang mengharuskan seluruh kunci volume tersedia untuk membuka disk. Blok-blok kunci digabungkan dan di-XOR dengan algoritme difusi untuk membentuk kunci master yang sebenarnya, jadi secara teori menghapus satu sektor saja dari kunci volume sudah seharusnya membuat semuanya tidak bisa dipulihkan
      Artinya, jika satu blok kunci saja hilang, sisanya tidak bisa ditebak dengan mudah
    • Dengan asumsi kunci enkripsinya kuat, penghapusan secara teori adalah pekerjaan yang redundan
  • Saya sama sekali bukan ahli keamanan, tetapi melihat bug keamanan fatal yang belakangan ini rutin ditemukan karena “satu baris pengecekan C lintas-berkas terlewat saat refactoring”, saya jadi meragukan premis basis kode C open source yang besar dan aman itu sendiri
    Ini bukan masalah yang hanya ada di C, tetapi terutama di C menurut saya jauh lebih sulit untuk menegakkan dan melacak invariant secara konsisten, dan itu makin terasa saat kode diubah
    Saya juga tidak tahu apakah pemrograman fungsional yang mengenkode invariant ke dalam tipe benar-benar solusi yang realistis dan bisa diskalakan. Model checking? LLM fuzzing? Lebih sedikit elemen dasar dengan batas yang jelas? Apakah seLinux “diverifikasi” dengan cara seperti itu?

    • Kekurangan C memang terlihat jelas dan saya juga biasanya tidak merekomendasikannya untuk proyek baru, tetapi saya tidak menganggap bug spesifik ini sebagai contoh bagus yang akan ditangkap oleh borrow checker Rust atau sistem tipe bahasa lain. Alat analisis statis pun tampaknya tidak akan menangkapnya
      Pada dasarnya bentuknya seperti ini:
      original: DoTheThing()
      new: DoTheThingSlightlyDifferentButKeepMyCredentialsAlive()
      fix: DoTheThingSlightlyDifferentButDoInFactNOTKeepMyCredentialsAlive()
      Berdasarkan pengalaman saya, banyak bug yang sulit pada akhirnya berasal dari pelanggaran invariant sistem tingkat tinggi, dan hal seperti ini tampaknya bukan sesuatu yang bisa diotomatisasi
      Dengan sesuatu seperti Lean pun kita bisa membuktikan bahwa program memenuhi properti tertentu, tetapi properti itu tetap harus terpikirkan terlebih dahulu. Pembuktian tidak otomatis menemukan invariant sebagai penggantinya
      Jika properti keamanan yang relevan itu sudah terpikirkan, menulis regression test seharusnya tidak sulit. Menurut saya bagian yang benar-benar sulit bukan mengekspresikan implementasi dengan aman, melainkan menyadari bahwa ada properti yang harus dipertahankan oleh implementasi
    • Premis tentang basis kode terbuka yang aman itu sendiri tidak masalah
      Masalahnya adalah lebih mudah diaudit tidak otomatis berarti benar-benar lebih banyak diaudit
      Tetap perlu orang yang cukup ahli dan punya cukup waktu untuk mengerjakannya
    • Bahkan kalau diterjemahkan ke Rust pun hasilnya mungkin hanya menjadi “satu baris pengecekan Rust terlewat”
      Ini bug yang muncul karena perhatian lintas-kepentingan beririsan dan kurangnya pengetahuan lintas domain. Di Lisp atau assembly pun mungkin akan sama saja
    • Pelajaran yang bisa diambil di sini adalah: jika suatu fitur tidak punya setidaknya test case terkait, maka itu sebenarnya bukan fitur sungguhan
    • Alasan premis “basis kode C open source yang besar dan aman” terlihat meragukan adalah karena code review kadang tidak jauh berbeda dari versi idealisasi masalah berhenti, dengan akses ke versi spesifikasi yang sudah diformalkan
      Dengan kata lain, tidak ada definisi yang ketat tentang apa yang termasuk isu keamanan
  • Apakah lembaga federal sangat membutuhkan cara untuk mendapatkan kuncinya? Apakah ini bugdoor? Sudahkah riwayat commit ditelusuri?
    Belakangan saya terlalu sering melihat pola seperti ini sampai mulai terasa mencurigakan. Bisa juga karena orang makin peka terhadap hal seperti ini sehingga lebih sering mempostingnya

    • Ini regresi. Aplikasi user-space juga akan gagal secara diam-diam, dan ini hasil dari serangkaian kelalaian
      Fakta bahwa kunci enkripsi ada di memori tidak otomatis berarti bisa diekstrak. Ini lebih seperti dibiarkan tetap ada tanpa perlu dan tanpa batas waktu di tempat yang seharusnya tidak menyimpannya
  • Regresi seperti ini mudah terlewat karena semuanya tetap terlihat “berfungsi”. Bug keamanan sering kali tidak menampakkan dirinya sendiri

    • Betul. Itulah sebabnya integration test lebih penting untuk fitur seperti ini
      Menulisnya juga menyenangkan, dan itu memungkinkan saya menjalankan git-bisect untuk menemukan refactoring kernel spesifik yang memperkenalkan bug ini: https://github.com/NixOS/nixpkgs/pull/532499
  • Di laptop Fedora saya, Linux diatur agar setelah suspend 15 menit langsung hibernate ke disk. Jika daya memori benar-benar diputus, bug khusus Debian seperti ini tidak menjadi masalah
    Ekstensi alat Linux dari Debian secara teori memang bagus, tetapi kalau benar-benar khawatir soal serangan cold boot, bukan hanya kunci LUKS melainkan semua kunci dan dokumen penting harus dihapus dari memori
    Jadi pada akhirnya satu-satunya cara yang benar untuk mencegah cold boot memang hibernate

  • Coba bayangkan seperti apa thread HN ini jika kerentanan ini ada di sistem operasi komersial
    Komentar teratas pasti akan bilang Applosoft sudah tidak peduli lagi pada kualitas perangkat lunak, atau “beginilah jadinya kalau sampah vibe coding dibiarkan masuk ke OS”
    Komentar di bawahnya pasti berupa teori konspirasi tentang kompleks industri pengawasan dan NSA, yang di tempat lain mungkin terdengar gila, tetapi di HN tidak akan terasa begitu

  • Saya tidak mengerti kenapa sesuatu sepenting ini tidak diuji pada setiap build