CVE-2023-40547 – shim’in HTTP başlıklarına yanlış güvenmesinden kaynaklanan açık
(github.com/rhboot)- rhboot/shim’in
0226b56commit’i, dosya alma sürecinde HTTP başlığındaki boyut değerine aynen güvenilmesi nedeniyle ortaya çıkan CVE-2023-40547’yi düzeltiyor - Değiştirilmiş bir başlık, gerçek alınan veriden daha küçük bir boyut belirtirse shim gereken tampon belleğinden daha küçük bir alan ayırabilir
- Eski kod, ayırma için başlık değerini; kopyalama içinse protokol metaverisini kullanıyordu ve bu durum out-of-bounds write’a yol açabiliyordu
- Yama,
httpboot.ciçindekireceive_http_response()fonksiyonunda*buf_size < rx_message.BodyLengthkontrolünü yapıyor; başarısız olursaEFI_BAD_BUFFER_SIZEveInvalid Content-Lengtholarak işliyor - Değişiklik kapsamı
httpboot.cadlı tek dosyada 7 satır ekleme ve 1 satır silme; ayrıcaContent-Lenghtyazım hatası daContent-Lengtholarak düzeltilmiş
Açığın oluşma akışı
- CVE-2023-40547, shim’in HTTP veya ilgili protokollerle dosya aldığı sırada ortaya çıkan bir sorun
- Alınan veriyi saklayacak tamponu ayırma sürecinde HTTP başlığındaki boyut değeri kullanılıyor
- HTTP başlığı manipüle edilebilir ve gerçek alınan veriden daha küçük bir boyut belirtebilir
- Eski akışta tampon ayırma için başlık değeri kullanılırken, rx tamponundan veri kopyalanırken protokol metaverisi temel alınıyordu
- Bu fark nedeniyle ayrılan tampondan daha büyük veri kopyalanabiliyor ve bunun sonucunda out-of-bounds write oluşabiliyordu
Yama içeriği
- Yama,
httpboot.ciçindekireceive_http_response(EFI_HTTP_PROTOCOL *http, VOID **buffer, UINT64 *buf_size)fonksiyonuna savunma amaçlı bir kontrol ekliyor *buf_size == 0durumunda mevcut hata mesajındaki yazım hatasını düzeltiyor vegoto errorile hata akışına geçiyorFailed to get Content-Lenght→Failed to get Content-Length
- Yeni kontrol,
*buf_size < rx_message.BodyLengthkoşulunu denetliyor- Koşul doğruysa
efi_status = EFI_BAD_BUFFER_SIZEayarlanıyor Invalid Content-Lengthhatası yazdırılıyor- Ardından
goto errorile hata akışına geçiliyor
- Koşul doğruysa
Değişiklik kapsamı
- Değiştirilen dosya yalnızca
httpboot.c - Değişiklik miktarı 7 satır ekleme, 1 satır silme
- Esas nokta, alınan gövde uzunluğu olan
rx_message.BodyLengthdeğerinin ayırma boyutu olan*buf_sizedeğerinden büyük olup olmadığını kontrol eden mantık
İlgili kayıtlar
- Bu commit, CVE-2023-40547’yi gideren değişiklik olarak işaretlenmiş
- Commit mesajı, sorunun HTTP başlığına yanlış güvenilmesinden kaynaklandığını açıkça belirtiyor
- Açığı bildiren kişi, Microsoft Security Response Center’dan Bill Demirkapi olarak kaydedilmiş
1 yorum
Hacker News yorumları
shim, Secure Boot’u etkinleştirmek isteyen Linux dağıtımlarında yaygın kullanılan bir EFI önyükleyicisidir
Dağıtımlar açısından, kullanıcıların anahtarları kendilerinin kaydetmesini istemek yerine, varsayılan olarak yüklü Microsoft imzalı anahtarla Secure Boot’u kolayca açmak istenir
Ancak Microsoft genellikle GRUB gibi GPL önyükleyicileri imzalamadığı için, Microsoft anahtarıyla imzalanabilen shim oluşturuldu; shim de önyükleyeceği hedefin imzasını Machine Owner Key, yani MOK adlı ayrı bir anahtarla doğrular
shim’e önyüklenecek EFI ikili dosyası belirtilirken bir HTTP URL’si verilebilir; bu durumda HTTP sunucusu kötü niyetliyse sınır dışı yazmaya yol açabilir
Ancak normalde GRUB gibi yerel bir ikinci aşama önyükleyiciyi başlatmak için kullanıldığından, çoğu kurulumda sorun olma olasılığı düşük görünüyor
Secure Boot en başından beri imzalanmış ikili dosyaların bile DBX listesi ile iptal edilebilmesi için tasarlandı; bu liste UEFI’ye eklendiğinde, geçerli imzası olsa bile ilgili ikili dosya reddedilir
Bu hatayı içeren eski shim ikili dosyalarının imzaları listeye eklenirse, herkes kendi cihazında listeyi güncelleyebilir; LVFS gibi kapsül güncellemeleriyle de dağıtılabilir veya Secure Boot anahtarlarını ve değişkenlerini doğrudan yönetiyorsanız listeyi https://uefi.org/revocationlistfile adresinden indirip kaydedebilirsiniz
Öyle olsaydı Critical derecesi verilmezdi
Bu hata; yerelde ayrıcalıklı kötü amaçlı yazılım EFI bölümünün üzerine yazdığında, PXE önyüklemesi etkin bir bitişik ağda ortadaki adam saldırısı yapıldığında ve HTTP önyükleme kullanılırken uzaktan ortadaki adam saldırısıyla istismar edilebilir
Ayrıcalıksız bir uzaktan saldırgan ortadaki adam konumundaysa ve kurban cihaz HTTP önyükleme kullanıyorsa, doğrudan erişim olmadan da istismar edebilir
Kurban cihazda yetki ve kod çalıştırma elde etmiş bir uzaktan saldırgan, kurban HTTP önyükleme kullanmasa bile donanım yazılımı HTTP’yi destekliyorsa Secure Boot’u atlatabilir
Örneğin önyükleme sırası değişkenlerini değiştirip saldırganın kontrol ettiği bir sunucuyu gösterebilir ya da EFI bölümündeki önyükleyicinin üzerine normal shim ve GRUB2 imajlarını yazdıktan sonra
grub.cfgiçinde HTTP üzerinden yeni shim’i zincirleme yükletebilirÇünkü GRUB2’nin aygıt sözdizimi, HTTP dahil desteklenen aygıtların belirtilmesine izin verir
Ayrıca ayrıcalıksız bir bitişik saldırgan ortadaki adam konumundaysa ve kurban cihaz PXE önyükleme kullanıyorsa, PXE’deki shim → PXE’deki GRUB2 → HTTP’deki shim şeklinde zincirleyerek istismar edebilir
Kaynak: https://techcommunity.microsoft.com/t5/hardware-dev-center/u...
GPLv3’ün anti-Tivoization hükümleri Secure Boot imzalama anahtarının sağlanmasını gerektirebiliyorsa, MOK imzalama anahtarının da istek üzerine sağlanması gerekmez mi diye düşünüyorum
Öyleyse bu, herkesin Secure Boot üzerinden dolaylı olarak önyüklenecek rastgele kodu imzalayabilen bir anahtar elde etmesi anlamına gelir; bunun Microsoft’un GRUB gibi GPLv3 projelerine doğrudan imzalama anahtarı vermesiyle anlamlı biçimde farklı olup olmadığını bilmiyorum
Eski BIOS cihazlarda WBM’in GRUB’u zincirleme yüklemesini ayarlamıştım; UEFI cihazlarda ise henüz denemediğim için takıldığı bir nokta var mı bilmiyorum
“Neden güvenilmeyen ya da ele geçirilmiş bir sunucudan önyükleme yapılsın?”, “Sunucu ele geçirildiyse zaten kötü amaçlı ikili dosya gönderebilir; bu yüzden anlamsız değil mi?” diye merak edebilirsiniz; kısaca, shim’in en sonunda önyüklediği ikili dosyanın MOK ile imzalanmış olması gerekir
Bu yüzden ele geçirilmiş bir ağ içinde önyükleme yapılsa da, HTTP ile önyükleme yapılsa da, ele geçirilmiş bir sunucudan önyükleme yapılsa da HTTPS olup olmamasından bağımsız olarak aynı güvenlik garantilerinin korunması gerekir
Secure Boot sürüm düşürmeyi engellemediği için, ele geçirilmiş bir sunucunun sürüm düşürme saldırısında kullanılabilmesi bu güvenlik açığından ayrı bir konudur
Sürüm düşürme saldırılarına karşı koruma zaten daha sağlam bir yöntemle ayrıca uygulanmalıdır
Yine de shim’in neden HTTP önyüklemeyi doğrudan desteklemesi gerektiğini bilmiyorum
MOK ile imzalanmış ikinci bir yerel EFI ikili dosyasında ele alınabilirdi; muhtemelen uygulanması görece basit bir özellik olduğunu düşünmüşlerdir
Bu kodun gövde uzunluğunu neden iki farklı ölçüte göre ele aldığını anlamıyorum
RFC’ye göre HTTP/1.1’de Content-Length, HTTP istek/yanıt gövdesi uzunluğu için yetkili bilgidir
Bu uzunluğun ötesinde hat üzerinde bulunan veri, tanım gereği başka bir iletinin parçasıdır
Tersine Content-Length
rx_message.BodyLengthdeğerinden büyükse, bu henüz iletinin tamamının alınmadığı anlamına gelir; bu yüzden daha fazla beklenmeli ya da zaman aşımı hatası verilmelidirHer iki durumda da
rx_message.BodyLengthdeğerinin Content-Length ile aynı olduğunun garantisi yoksa bu hatalı bir değerdirDaha hoşgörülü davranmak istiyorsanız Content-Length başlığına bakmak için bir neden yok; sadece
rx_message.BodyLengthdeğerini tampon boyutu olarak alıp hat üzerindeki tüm veriyi alınan ileti olarak yorumlayabilirsinizMevcut kod gereksiz yere karmaşık ve hatalar bu şekilde içeri giriyor
Çevredeki koda https://github.com/rhboot/shim/blob/0226b56513b2b8bd5fd281bc... bakarsanız, döngü içinde veri parçaları alınırken her seferinde yeni verinin Content-Length ile belirlenen tampon kapasitesini aşıp aşmadığı kontrol ediliyor
Ancak daha önce döngü dışındaki ilk okuma için bu kontrol yapılmıyordu ve hata buydu
Yine de indirilen boyutun
*buf_size, yani Content-Length ile aynı olup olmadığını sonradan doğrulayan bir kod görünmüyorBu koşul bozulursa bağlantının fazla erken kapandığına işaret ediyor olabilir
Bu açıkça bir hata ve düzeltilmiş olması iyi, ama insan güvenilmeyen bir ana makineden kendi cihazını kim başlatır diye düşünüyor
Saldırgan HTTP hizmetini kötü amaçlı başlık gönderecek kadar ele geçirdiyse bu taşmayı aşmak en küçük sorun olur; sertifika da ele geçirilmiştir ve standarda uygun bir payload içine kötü amaçlı kod koyup gönderebilir
Hata olduğu doğru, ama Critical olup olmadığından emin değilim
Potansiyel olarak ele geçirilebilecek her şeyin Secure Boot ile imzalanmamış olması gerektiği bir güvenlik stratejisine ciddi ciddi inanıyorlar
İmzalı ama açık içeren tek bir şey bile varsa, onu herkesin Secure Boot+TPM şifreli diskini çözmek için kullanabilirsiniz
Bu yaklaşımın neden geçerli bir güvenlik modeli sayıldığını anlamak zor ve bu tür açıklar zaten yığınla var
Üstelik odadaki fil olan Windows’u tamamen görmezden geliyorlar
Bu zihniyete örnek: https://lkml.org/lkml/2018/4/3/767
Linus’un kaygılarına rağmen birçok dağıtımda Secure Boot ile başlatınca gerçekten bütünlük modu etkinleşiyor
Muhtemelen bunun nedeni Microsoft politikası ve dağıtımların Microsoft UEFI imzası alabilmek için o ileti dizisinde açıklanan prosedürü izlemeye zorlanması
Sonuç olarak Secure Boot’u açınca genellikle dağıtım özellikleri kısıtlanıyor; örneğin hazırda bekletme kullanılamaz hale geliyor
Önemli işler olurken HTTP’nin S’li olanını kullanmak gerekir
Cihaz başlatma da buna dahil ve HTTPS başlıkları her zaman şifreliydi
Yine de iyi bulunmuş bir hata
Hatalı başlık iki tarafta da gönderilebilir
Çünkü şifreleme için doğru saat ve tarih gerekiyor
RTC geçerli olabilir, ama saat dilimlerini iyi ele alıp almadığını da bilmiyorum; ayrıca her hâlükârda saat kaymış olabilir
Sorunu doğru anlamamış gibisiniz
Content-lengthgerçek gövde uzunluğu değil, Content-encoding sonrasındaki uzunlukturBu shim derlemelerinde httpboot var mı?
Bildiğim kadarıyla shim yalnızca diskteki başka EFI ikililerini çalıştırmaya yarıyor ve shim’in ağdan başlatma özelliğinin gerçekten kullanıldığını gördüğümü sanmıyorum
Yanılıyor olabilirim ama çoğu HTTP istemcisinin yalnızca belirtilen Content-Length kadar okuduğunu, okunan bayt sayısı Content-Length’ten azsa da bunu hata saydığını sanıyordum
Bana kalırsa UEFI spesifikasyonu, Content-Length başlığı ile yanıt gövdesi uzunluğu uyuşmadığında davranışın ne olacağını ayrıntılı biçimde belirlemiyor
Bu yüzden bazı uygulamaların sadece
connection:closeisteği oluşturup Content-Length’i kontrol etmemesi gayet mümkünBu güvenlik açığını MSRC bildirdi ve CVE açıklamasında gerçek istismara dair bir şey yok
İleride açıklanabilir de, teorik bir sorun da olabilir
Gerçek gövde uzunluğundan daha az okumanın neden tehlikeli olduğunu açıklayabilir misiniz?
Asıl tersinin tehlikeli olmasını beklerdim
Ancak boyutu değiştirilebilir HTTP başlığından alıyor ve saldırgan alınan veriden daha küçük bir boyut belirtebiliyor
Bu durumda kod ayırma için başlık değerini kullanıyor, alma tamponundan kopyalarken ise protokol meta verisindeki boyutu kullanıyor; bunun sonucunda sınır dışı yazma oluşuyor