Linux 6.9'dan sonra LUKS askıya alma, disk şifreleme anahtarını bellekten silemiyor
(mathstodon.xyz)- 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/keysgirdilerinin 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
- NixOS otomatik testi: gelecekteki regresyonları saptamak için entegrasyon testi
- cryptsetup merge request: sessizce başarısız olmak yerine uyarı vermesini sağlayan yama
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/keysgirdileri 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-suspendprojesi, 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
Hacker News yorumları
İlginç bir hata olduğu doğru, ama başlık biraz clickbait gibi hissettiriyor
Anladığım kadarıyla
cryptsetup luksSuspendresmi 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üyorumDesteklenen 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
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 ediyorcryptsetup 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
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ış durduYine 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...
Muhtemelen
luksSuspendsonrası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ğildiBaş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
Ama Debian önce isteğe bağlı
cryptsetup-suspendeklentisini yaptı; bu, anahtarları bellekten silmesi gerekenluksSuspendkomutunu ç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ı
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ı
cryptsetup-luksSuspendkullanmadığı belliBu 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
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
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?
Ö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
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
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
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
Ş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
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/532499Fedora 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
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