1 puan yazan GN⁺ 2024-01-27 | 1 yorum | WhatsApp'ta paylaş
  • rhboot/shim’in 0226b56 commit’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.c içindeki receive_http_response() fonksiyonunda *buf_size < rx_message.BodyLength kontrolünü yapıyor; başarısız olursa EFI_BAD_BUFFER_SIZE ve Invalid Content-Length olarak işliyor
  • Değişiklik kapsamı httpboot.c adlı tek dosyada 7 satır ekleme ve 1 satır silme; ayrıca Content-Lenght yazım hatası da Content-Length olarak 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.c içindeki receive_http_response(EFI_HTTP_PROTOCOL *http, VOID **buffer, UINT64 *buf_size) fonksiyonuna savunma amaçlı bir kontrol ekliyor
  • *buf_size == 0 durumunda mevcut hata mesajındaki yazım hatasını düzeltiyor ve goto error ile hata akışına geçiyor
    • Failed to get Content-LenghtFailed to get Content-Length
  • Yeni kontrol, *buf_size < rx_message.BodyLength koşulunu denetliyor
    • Koşul doğruysa efi_status = EFI_BAD_BUFFER_SIZE ayarlanıyor
    • Invalid Content-Length hatası yazdırılıyor
    • Ardından goto error ile hata akışına geçiliyor

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.BodyLength değerinin ayırma boyutu olan *buf_size değ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

 
GN⁺ 2024-01-27
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

    • Orijinal yazıdaki hatayı bulan kişiyim; bu sorunun yalnızca HTTP önyükleme kullanıldığında istismar edilebileceği yaygın bir yanlış anlama
      Ö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.cfg iç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
    • Bunun nedeni, Microsoft hukuk ekibinin; Microsoft GPLv3 lisanslı bir önyükleyici olan GRUB’u imzalarsa, GPLv3 nedeniyle geliştiricilere imzalama anahtarını sağlama zorunluluğu doğabileceğini düşünmesi
      Kaynak: https://techcommunity.microsoft.com/t5/hardware-dev-center/u...
    • Bir önyükleyicinin neden ağ iletişimi yaptığını merak ediyordum; EFI ikili dosyasının HTTP URL olarak belirtilebildiği açıklamasıyla anlaşılıyor
    • shim’in Microsoft’un kaygılandığı sorunu nasıl atlattığını merak ediyorum
      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
    • Amaç yerel bir ikinci aşama önyükleyiciyi başlatmaksa, Windows Boot Manager da aynı rolü üstlenemez mi diye düşünüyorum
      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.BodyLength değ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ı verilmelidir
    Her iki durumda da rx_message.BodyLength değerinin Content-Length ile aynı olduğunun garantisi yoksa bu hatalı bir değerdir
    Daha hoşgörülü davranmak istiyorsanız Content-Length başlığına bakmak için bir neden yok; sadece rx_message.BodyLength değerini tampon boyutu olarak alıp hat üzerindeki tüm veriyi alınan ileti olarak yorumlayabilirsiniz
    Mevcut kod gereksiz yere karmaşık ve hatalar bu şekilde içeri giriyor

    • Yalnızca ilgili commit’e bakınca yanlış anlamak kolay
      Ç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üyor
      Bu 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

    • Secure Boot’u zorlayanlar da benzer türden
      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
    • İyi savunma ancak derinlemesine savunma gibi birden çok savunma katmanı oluşturmaktır ve bu hata o katmanlardan birinde delik açıyor
    • Bazı kilitli cihazlara sızmak için de kullanılabilir
    • Diğer ileti dizisindeki harika açıklamaya bakılırsa https://news.ycombinator.com/item?id=39135275 saldırı vektörü yalnızca HTTP ile sınırlı olmadığı için Critical sayılabilir
  • Ö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

    • Burada HTTPS alakasız
      Hatalı başlık iki tarafta da gönderilebilir
    • HTTPS’in bu kullanım için mümkün olup olmadığından emin değilim
      Çü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
    • Bu, S’nin olup olmamasıyla ilgili bir sorun değil
      Sorunu doğru anlamamış gibisiniz
  • Content-length gerçek gövde uzunluğu değil, Content-encoding sonrasındaki uzunluktur

    • “HTTP/1.1, çoğunu yok sayınca gerçekten keyifli derecede basit bir protokol”
  • Bu 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

    • HTTP istemcisini UEFI, EFI sürücüsü olarak sağlıyor
      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:close isteği oluşturup Content-Length’i kontrol etmemesi gayet mümkün
      Bu 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

    • shim, HTTP veya ilgili protokollerle dosya getirirken alınan veriyi saklamak için bir tampon ayırmaya çalışıyor
      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
    • Açıklamaya göre tampon Content-Length’e göre ayrılıyor, fakat gerçekte alınan tamponun boyutu kadar kopyalandığı için ayrılan alanın dışına yazılıyor