1 puan yazan GN⁺ 3 시간 전 | 1 yorum | WhatsApp'ta paylaş
  • Linux 6.9'dan itibaren, dizüstü bilgisayar askıya alındığında sürücüyü kilitleyen araç sessizce başarısız oluyordu ve LUKS tam disk şifreleme anahtarı bellekte kalıyordu
  • Nedeni, Mayıs 2024'te Linux 6.9'a giren blok aygıt erişimi refaktörizasyonu ile şifreleme kodunun beklenmedik etkileşimi; önerilen düzeltme ise tek satırlık bir yama
  • Tam kapatmada sorun görünmese de suspend-to-RAM durumunda anahtar bellekte kalıyor ve gücü açık bir dizüstü bilgisayarı ele geçiren saldırgan için RAM'den anahtar çıkarılabilir hale geliyor
  • Bu durum, Debian cryptsetup-suspend'in NixOS portu düzenlenirken /proc/keys girdilerinin fark edilmesiyle ortaya çıktı; QEMU bellek dökümüyle silinmiş olması gereken volume key'in kaldığı doğrulandı
  • NixOS entegrasyon testi ve cryptsetup için uyarı yaması önerildi; askıya almadan hemen önce anahtar silme gibi güvenlik özellikleri normal çalışıyor görünse bile, gerçek bellek doğrulaması olmadan başarısızlıkları kaçırmak kolay

Linux 6.9'dan sonra askıya alma sırasında LUKS anahtarlarının kalması sorunu

  • Linux 6.9'dan, yani Mayıs 2024'ten beri, dizüstü bilgisayar askıya alındığında sürücüyü kilitleyen araç sessizce başarısız oluyordu
  • LUKS tam disk şifreleme, dizüstü bilgisayar kaybolduğunda, el konulduğunda veya çalındığında verileri korumak için kullanılır; ancak bu durumda askıya alma sırasında şifreleme anahtarı bellekte kalıyordu
  • Tam kapatmada hâlâ çalışıyordu, fakat dizüstü bilgisayarları tamamen kapatmak yerine sıkça suspend-to-RAM durumunda bırakmak etkisini büyütüyor
  • Gücü açık durumdaki bir dizüstü bilgisayarı ele geçiren biri varsa, bellekte kalan anahtar açığa çıkabilecek durumdaydı
  • Windows'ta aynı amaç için VeraCrypt'ten söz edildi, ancak daha sonra yorumlarda “canonical software” ifadesinin en yaygın yazılım değil, BT güvenliği alanında başlıca önerilen yazılım anlamına geldiği şeklinde düzeltme yapıldı

Neden ve tek satırlık yama

  • Neden, Linux çekirdeğindeki refaktörizasyon commit'i olan md: port block device access to file
    • Değişikliğin kendisi makul ve yararlı bir refaktörizasyondı, ancak şifreleme koduyla uzun menzilli etkileşim yarattı
  • Önerilen düzeltme tek satırlık bir yama
  • Yamanın yazarı, biçimsel doğrulama olmadan bu yamanın doğru olduğunu ve başka uzun menzilli etkileşimler yaratmadığını söyleyemeyeceğini belirtiyor
  • Tekrarını önlemek için ek çalışmalar da geldi

Nasıl keşfedildi

  • Başlangıç noktası, Debian cryptsetup-suspend'in NixOS portunu düzenleme çalışmasıydı
  • Hem Debian özgün sürümünde hem de NixOS portunda, dizüstü bilgisayarın bazen uykuya geçememesine yol açan, can sıkıcı ama zararsız bir race condition vardı
  • Bunu çözmek için, Pali Rohár'ın birleştirilmemiş çekirdek yaması olan dm-crypt suspend/hibernation anahtar silme yaması yeniden canlandırılmaya çalışıldı
  • Bu süreçte cryptsetup ve çekirdek kaynak kodu incelenirken, belgelerde keyring'in çağıran iş parçacığına bağlandığı ve iş parçacığı sona erdiğinde kaldırıldığı doğrulandı
  • Ancak daha önce fark edilmeyen /proc/keys girdileri görüldü ve bu durum şüpheyi artırdı
  • Sonunda bir QEMU sanal makinesi başlatılıp bellek döküldü ve silinmiş olması gereken LUKS volume key'in gerçekten kaldığı doğrulandı

NixOS secure suspend-to-RAM projesi

  • Ayrı olarak yayımlanan secure-suspend projesi, NixOS üzerinde deneysel güvenli suspend-to-RAM sunuyor
  • Normal tam disk şifrelemede, dizüstü bilgisayar askıya alındığında anahtarlar bellekte kalır; bu da cold boot attack veya RAM sızıntısı yöntemlerine karşı zafiyet oluşturabilir
  • Bu proje, Pali Rohár'ın eski çekirdek yamasını yeniden canlandırarak askıya alma sırasında LUKS şifreleme anahtarlarını silmeyi amaçlıyor
  • Debian cryptsetup-suspend'den ilham aldı, ancak çekirdek yaması kullanarak dizüstü bilgisayarın bazen uykuya dalamamasına yol açan race condition'dan kaçınıyor ve ek önlemler ekliyor
  • Şifrelenmiş root filesystem'i tam olarak destekliyor ve entegrasyon testi de sağlıyor
  • Çekirdek yaması ve kullanıcı alanı araçları başka Linux dağıtımlarına da uyarlanabilir
  • Proje secure-suspend adresinde yayımlanıyor

Askıya alma güvenliğini doğrulamak neden zor

  • Askıya almadan sonra ekran kilidinin görünmesi, depolama aygıtının gerçekten kilitlendiği anlamına gelmez
  • Askıdan uyandıktan hemen sonra diske doğrudan erişilebiliyorsa, depolama aygıtının baştan beri kilitlenmediği anlaşılır
    • Örneğin, kilit ekranının arkasında çalışmaya devam eden bir betikle disk erişimi kontrol edilebilir
    • Askıya almadan sonra önce şifreli depolamayı açmadan SSH açık anahtarıyla bağlanılabiliyorsa, depolamanın kilitlenmediğini doğrulamak kolaydır
  • Yorumlarda, Ubuntu veya Debian varsayılan yapılandırmasının böyle bir koruma sağlamaya çalışmadığı da belirtildi
  • Depolamayı kilitleme girişiminin gerçekten doğru çalışıp çalışmadığı ayrıca doğrulanmalı
    • Log zaman damgaları askıya almadan önce oluşturulmuş ama uyanmadan sonra yazılmış olabilir
    • Tersine, uyanmadan hemen sonra sistem saati düzeltilmeden önce oluşturulan loglar askıya alma anının zamanı gibi görünebilir
  • Depolama kilidinin askıya almadan hemen önce mi, yoksa yeniden başladıktan hemen sonra mı gerçekleştiği kullanıcı deneyimi açısından aynı görünebilir, ama güvenlik açısından belirleyici biçimde farklıdır
  • NixOS entegrasyon testi, sistemi sanal makinede başlatıp belleği dökerek anahtarın askıya alma sırasında gerçekten silinip silinmediğini kontrol ediyor

1 yorum

 
GN⁺ 3 시간 전
Hacker News yorumları
  • İlginç bir hata olduğu doğru, ama başlık biraz clickbait gibi hissettiriyor
    Anladığım kadarıyla cryptsetup luksSuspend resmi olarak desteklenen bir özellikten çok Debian’ın yaptığı bir genişletmeye yakın; bu yüzden bu regresyondan etkilenen de yalnızca Debian değil mi diye düşünüyorum
    Desteklenen ya da yaygın biçimde test edilen bir özellik bile değilken çekirdeği suçlamanın ne kadar doğru olduğundan emin değilim
    Yine de etkileyici ve bu regresyonun tekrar oluşmaması için test eklenmiş olması iyi. OP’nin NixOSTests’in gerçekten harika olduğu görüşüne de katılıyorum
    Ancak yalnızca başlığa bakınca sorun tek bir dağıtıma özgü değil de yaygın bir problemmiş gibi görünüyor

    • Teknik olarak doğru bir başlık hedeflemiştim, tıklama çekmeye çalışmadım
      Doğru. Varsayılan ayarları kullananları etkilemiyor; çünkü zaten suspend sırasında volume key’in güvende olmasını beklemeyeceklerdir
      Debian’ın çözümü başka birçok, muhtemelen çoğu dağıtıma port edildi ve kişisel portlarını sürdüren epey kişi de olmuş olabilir
      thread-keyring(7) man sayfası “thread keyring’in, ona referans veren thread sonlandığında yok edileceğini” vaat ediyor
      cryptsetup projesi, anahtarı kullanıcı alanından çekirdek alanına taşıma mekanizmasında bu özelliğe dayanıyordu; çekirdek 6.9 ise bu özelliği bozan bir regresyon getirdi
    • Bunun neden Debian’a özel dendiğini anlamakta zorlanıyorum. luksSuspend upstream bir özellik ve 2009’da v1.1.0 sürümünde eklendi
      Geçmişte Arch ve openSUSE’de de ara sıra kullandım; Debian dışındaki dağıtımlarda da kesinlikle mevcut
      Sanırım system suspend ile otomatik entegrasyonu kastediyor olabilirler, ama bu asıl noktadan sapıyor. luksSuspend’ın anahtarları sistem belleğinden sildiği belgelenmiş durumda ve Linux 6.9’daki ilgili refactoring yaması yüzünden bu davranış durdu
      Yine de pratikte cryptsetup tarafında bir hata olarak da görülebilir. Çünkü çekirdek keyring anahtarlarının çok belirli bir yaşam süresi davranışına dayanıyordu; kullanıcı alanında daha açık biçimde silmesi gerekirdi denebilir
      [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...
    • Alt komut resmi cryptsetup deposunda var ve açıklaması da doğru görünüyor: https://gitlab.com/cryptsetup/cryptsetup/-/blob/main/man/cry...
    • Bu özelliği Arch’ta kullandım ve genel LUKS ile de kullanılabiliyor. Ancak bildiğim kadarıyla suspend sırasında varsayılan olarak kullanılmıyor
      Muhtemelen luksSuspend sonrasında RAM suspend’i gerçekten işe yarar biçimde çalıştıran aygıttan söz ediyorlar; bu başlangıçta Debian hedefliydi, daha sonra Arch’a da geldi, ama ikisinde de varsayılan değildi
    • Debian’ın 6.9’u ilk olarak hangi sürümde dağıttığını merak ediyorum
  • Başka bir yöntem pek görünmüyor. Uykuya, yani RAM suspend’e geçince her şey RAM’de tutuluyor ve şifrelenmiş oluyor; ancak hatırladığım kadarıyla master key çekirdek belleğinde kalıyor
    Buna karşılık hibernate, yani diske suspend yapılınca RAM’in tüm içeriği master key de dahil olmak üzere diske yazılıyor, şifreleniyor ve RAM temizleniyor
    Yeniden uyandırırken master key’i çözmek ve disk içeriğini tekrar belleğe almak için passphrase’i yeniden girmek gerekiyor

    • Doğru. Çoğu varsayılan Linux dağıtımında dizüstünü sadece suspend ederseniz master key dahil her şey bellekte kalır
      Ama Debian önce isteğe bağlı cryptsetup-suspend eklentisini yaptı; bu, anahtarları bellekten silmesi gereken luksSuspend komutunu çalıştırıyor ve resume sırasında passphrase’i yeniden istiyor
      Çekirdek 6.8’e kadar anlatıldığı gibi çalışıyordu; çekirdek 6.9’dan itibaren ise sessizce çalışmamaya başladı
    • Son yaklaşık 5 yıldaki Intel/AMD CPU’ların ikisi de işletim sistemine şeffaf olan tam bellek şifreleme desteğine sahip
      Bu özelliği açarsanız cold boot saldırıları geçmişte kalır. Genelde RAM hızını yaklaşık %0,5 düşürdüğü için varsayılan olarak kapalıdır
  • Sleep’ten sonra açılış parolasını yeniden girmediğime göre, şifreleme anahtarı hâlâ bellekte kalıyor olmalı

    • Dağıtımın cryptsetup-luksSuspend kullanmadığı belli
  • Bu benim için çok da dert ettiğim bir sorun değil
    Disk şifrelemesi yapmamın tek nedeni, dizüstünü satarken birinin vergi belgelerimi ya da kredi kartı bilgilerimi kurcalamasından endişe etmemek
    Elbette dizüstünü de siliyorum, ama veriler sürücü düzeyinde şifreliyse adli analiz araçları gibi şeylerle verilerin kurtarılma riskinin çok küçük olduğunu düşünüyorum

    • Makul bir ara çözüm olarak yalnızca LUKS header’ını silmek de yeterli olabilir
      LUKS, diski açmak için volume key’in tamamının gerekli olduğu bir anti-forensics algoritması kullanır. Anahtar bloklarını bir diffusion algoritmasıyla birleştirip XOR’layarak gerçek master key’i oluşturur; teorik olarak volume key’in tek bir sektörünü silmek bile tamamını kurtarılamaz hâle getirmelidir
      Yani anahtarın tek bir bloğu bile yoksa geri kalanını kolayca tahmin edemezsiniz
    • Şifreleme anahtarının güçlü olduğu varsayımıyla, silme teoride fazladan yapılan bir iştir
  • Güvenlik uzmanı falan değilim ama bugünlerde “refactoring sırasında dosyalar arasında dolaşan tek satırlık bir C kontrolünü kaçırmaktan kaynaklanan” kritik güvenlik hatalarının düzenli olarak bulunmasına bakınca, devasa, güvenli açık kaynak C kod tabanı varsayımının kendisi şüpheli geliyor
    Bu yalnızca C’ye özgü bir sorun değil ama özellikle C’de değişmezleri tutarlı biçimde zorlamak ve izlemek daha zor; kod değişirken daha da öyle olduğunu düşünüyorum
    Değişmezleri tipe kodlayan fonksiyonel programlamanın pratikte ölçeklenebilir bir çözüm olup olmadığını da bilmiyorum. Model checking? LLM fuzzing? Net sınırlara sahip daha az temel yapı taşı? seLinux bu şekilde “kontrol edilmiş” bir şey miydi?

    • C’nin dezavantajları ortada ve yeni projeler için genel olarak önermem de, bu belirli hatanın Rust’ın borrow checker’ının ya da başka bir dilin tip sisteminin yakalayacağı iyi bir örnek olduğunu sanmıyorum. Statik analiz araçları da yakalayamaz gibi
      Özünde şöyle bir şey:
      original: DoTheThing()
      new: DoTheThingSlightlyDifferentButKeepMyCredentialsAlive()
      fix: DoTheThingSlightlyDifferentButDoInFactNOTKeepMyCredentialsAlive()
      Deneyimime göre zor hataların önemli bir kısmı üst düzey sistem değişmezlerinin ihlalinden çıkıyor ve bunlar otomatikleştirilebilecek şeyler gibi görünmüyor
      Lean gibi bir şeyle bile programın belirli bir özelliği sağladığını kanıtlayabilirsiniz, ama o özelliği önce aklınıza getirmiş olmanız gerekir. Kanıt, değişmezi sizin yerinize keşfetmez
      İlgili güvenlik özelliğini aklınıza getirmiş olsaydınız regresyon testi yazmak zor olmazdı. Bence gerçekten zor kısım, uygulamayı güvenli biçimde ifade etmek değil; uygulamanın koruması gereken bir özellik olduğunu fark etmek
    • Güvenli kamusal kod tabanı varsayımının kendisi sorun değil
      Sorun, denetlenebilirliğin daha yüksek olmasının otomatik olarak daha fazla denetim yapılacağı anlamına gelmemesi
      Yeterli beceriye sahip insanların yeterli zamanı ayırıp çalışması gerekiyor
    • Rust’a çevirseniz de “Rust’ta tek satırlık bir kontrol kaçırıldı” olurdu
      Bu, kaygı alanlarının kesişmesinden ve alanlar arası bilginin eksikliğinden doğan bir hata. Lisp’te ya da assembly’de de muhtemelen aynı olurdu
    • Buradan çıkarılacak ders şu: Bir özellikle ilgili en azından ilgili test case yoksa, o gerçek bir özellik değildir
    • “Devasa, güvenli açık kaynak C kod tabanı” varsayımının şüpheli görünmesinin nedeni, kod incelemenin bazen spesifikasyonun biçimselleştirilmiş bir sürümüne erişebilen idealize edilmiş durdurma probleminden çok da farklı olmaması
      Başka bir deyişle, neyin güvenlik sorunu olduğuna dair katı bir tanım yok
  • Federal kurumların anahtarı elde edecek bir yola umutsuzca ihtiyaç duymuş olması mı gerekiyordu? Bu bir bugdoor mu? Commit izi sürüldü mü?
    Son zamanlarda bu kalıbı çok gördüğüm için biraz şüphelenmeye başlıyorum. Belki de insanlar buna daha duyarlı hale geldiği için daha çok paylaşıyorlardır

    • Bu bir regresyon. Kullanıcı alanı uygulaması da sessizce başarısız olmuş olurdu; bir dizi dikkatsizliğin sonucu
      Şifreleme anahtarının bellekte olması, çıkarılabileceği anlamına gelmez. Daha çok, aslında olmaması gereken bir yerde gereksiz yere süresiz bırakılmış gibi
  • Böyle regresyonları kaçırmak kolaydır çünkü her şey “çalışmaya” devam eder. Güvenlik hataları çoğu zaman kendini belli etmez

    • Doğru. Bu yüzden bu tür özelliklerde entegrasyon testleri daha önemli
      Yazması da keyifliydi ve bu hatayı getiren somut kernel refactoring’ini bulmak için git-bisect çalıştırmayı mümkün kıldı: https://github.com/NixOS/nixpkgs/pull/532499
  • Fedora dizüstümde Linux’u, suspend’den 15 dakika sonra diske hibernate edecek şekilde ayarladım. Belleğin gücünü keserseniz bu tür Debian’a özgü hata sorun olmaz
    Debian’ın Linux araç genişletmesi teoride iyi ama gerçekten cold boot saldırılarından endişe ediyorsanız yalnızca LUKS anahtarı değil, tüm anahtarlar ve önemli belgeler de bellekten silinmeli
    Bu yüzden cold boot’u engellemenin düzgün yolu nihayetinde hibernate

    • Katılıyorum. Ya da FridgeLock’u diriltmek de bir yol: https://www.sec.in.tum.de/i20/publications/fridgelock-preven...
    • Peki resume ederken belleği çözmek için anahtar nereden alınacak?
      Bildiğim kadarıyla TPM kullanmadan pratik değil. TPM kullanınca da kaderinizi fiilen TPM’e teslim etmiş oluyorsunuz
  • Bu zafiyet ticari bir işletim sisteminde olsaydı bu HN başlığının nasıl görüneceğini hayal etmek yeterli
    En üstteki yorum kesinlikle Applosoft’un artık yazılım kalitesini umursamadığı ya da “OS’e vibe coding çöpü sokarsanız böyle olur” gibi bir şey olurdu
    Altındaki yorum da gözetim endüstriyel kompleksi ve NSA hakkında komplo teorileri olurdu; başka yerlerde delice sayılırdı ama HN’de değil

  • Bu kadar önemli bir şeyin neden her build’de test edilmediğini anlamıyorum