1 puan yazan GN⁺ 2024-03-20 | 1 yorum | WhatsApp'ta paylaş
  • CVE-2023-6241, Arm Mali GPU bellek yönetim birimindeki bir mantık hatasıdır; kötü amaçlı bir Android uygulamasının, kernel MTE açık olan Pixel 8’de bile keyfi kernel kodu çalıştırmaya ve root yetkisi elde etmeye ulaşmasına olanak tanır
  • Etkilenenler, Command Stream Frontend(CSF) kullanan yeni Arm Mali GPU cihazlarıdır; Google Pixel 7 ve Pixel 8 buna dahildir
  • Zafiyet, JIT bellek genişletme sırasında kilidin kısa süreliğine açıldığı aralıktan yararlanarak GPU eşlemesi ile backing page dizisi arasında tutarsızlık oluşturma şeklinde çalışır
  • Exploit, serbest bırakılmış backing page üzerinde kalan GPU eşlemesini kullanır; bu sayfanın GPU bağlamının PGD’si olarak yeniden kullanılmasını sağladıktan sonra kernel belleğini ve kernel kodunu eşler
  • MTE, pointer ve bellek tag’i uyuşmazlıklarını yakalar; ancak bu saldırı akışı, GPU’nun fiziksel adreslere doğrudan erişmesiyle MTE koruma kapsamı dışında ilerler

Zafiyet kapsamı ve yama durumu

  • CVE-2023-6241, Arm Mali GPU zafiyetidir; kötü amaçlı bir Android uygulamasının cihazda keyfi kernel kodu çalıştırmasına ve root yetkisi almasına olanak tanır
  • 15 Kasım 2023’te Arm’a bildirildi ve 14 Aralık 2023’te yayımlanan Arm Mali driver r47p0 sürümünde düzeltildi
  • Android düzeltmeleri Mart 2024 güvenlik güncellemesine dahil edildi
  • Etkilenenler, CSF(Command Stream Frontend) özelliğini kullanan yeni Arm Mali GPU cihazlarıdır; Google Pixel 7 ve Pixel 8 örnek olarak gösteriliyor
  • Pixel 8’de kernel MTE etkinleştirilmişken de exploit’in çalıştığı doğrulandı

Arm64 MTE’nin savunma modeli

  • MTE(Memory Tagging Extension), modern Arm işlemcilerde bulunan, bellek bozulmasını tespit etmek için pointer’lar ile bellek bloklarının tag’lerini karşılaştıran bir donanım özelliğidir
  • Arm64 pointer’ları 64 bit olsa da gerçek uygulama adres alanı genellikle 52 bit veya daha az olduğundan üst bitlerin bir kısmı tag saklamak için kullanılabilir
  • Doğrusal overflow durumunda bitişik bellek bloklarının tag’i pointer tag’inden farklılaşabilir; use-after-free durumunda ise serbest bırakma ve yeniden ayırma sürecindeki tag değişimi nedeniyle uyuşmazlık oluşabilir
  • kCFI gibi sonraki aşama azaltma önlemlerinin aksine MTE, bellek bozulmasını ilk oluştuğu anda yakalamayı hedefleyen erken aşama bir azaltma önlemidir
  • Tag bitlerinin sayısı sınırlı olduğundan çakışmalar kaçınılmazdır; yalnızca 4 bit tag kullanılsa bile rastgele başarı olasılığı 1/16’ya düşer
  • Spectre gibi yan kanal saldırılarıyla pointer ve bellek bloğu değerleri sızdırılırsa doğru tag tutturularak MTE atlatılabilir; ancak bu tür sızıntılar çoğunlukla yerel saldırganlar için mümkündür
  • Şu anda yalnızca Google Pixel 8, geliştirici seçeneklerinden MTE’nin etkinleştirilmesine izin verir; MTE varsayılan olarak devre dışıdır
  • Kernel’de MTE’yi etkinleştirmek için ek prosedür gerekir

Mali JIT belleğinde oluşan yarış durumu

  • Mali GPU driver’ını kullanan kullanıcı uygulaması, driver dosyasını açar ve ioctl çağrılarıyla kbase_context kernel nesnesini oluşturup başlatır
  • kbase_context, GPU cihazı ile kullanıcı alanı uygulaması arasında paylaşılan çeşitli bellek türlerini yönetir
  • Mali GPU’nun bellek bölgesi kbase_va_region ile temsil edilir; nr_pages sanal boyutu, gpu_alloc->nents ise gerçek backing page sayısını gösterir
  • JIT belleği, ömrü kernel driver tarafından yönetilen native memory’dir; uygulama JIT belleğini GPU komutlarıyla ayırır veya serbest bırakır
  • CSF GPU’larda yazılım komutları ve donanım komutları farklı kuyruklara konur
    • KBASE_IOCTL_KCPU_QUEUE_CREATE ile kbase_kcpu_command_queue oluşturulabilir
    • KBASE_IOCTL_KCPU_QUEUE_ENQUEUE ile komutlar kuyruğa eklenir
    • BASE_KCPU_COMMAND_TYPE_JIT_ALLOC ve BASE_KCPU_COMMAND_TYPE_JIT_FREE, JIT ayırma ve serbest bırakma için kullanılır
  • kbase_jit_allocate, serbest bırakılmış JIT bellek havuzunda yeniden kullanılabilir bir bölge arar; fiziksel boyut yetersizse kbase_jit_grow ile backing page sayısını artırır
  • kbase_jit_grow, kbase_mem_pool_grow çağrısı sırasında kctx->reg_lock ve kctx->mem_partials_lock kilitlerini geçici olarak bırakabilir
  • kctx->reg_lock, bellek bölgelerine eşzamanlı erişimi koruduğundan kilidin açıldığı aralık bir yarış penceresi hâline gelir

CVE-2023-6241 tetikleme akışı

  • GPU, fiziksel sayfalarla backing edilmemiş bir bellek bölgesi adresine erişirse GPU bellek erişim hatası oluşur
  • kbase_mmu_page_fault_worker, bölgenin genişletilebilir olup olmadığını kontrol ettikten sonra gerekli backing page’leri hemen ayırıp eşleyebilir
  • JIT bölgesi oluşturulurken KBASE_REG_PF_GROW ve KBASE_REG_GPU_WR içeren GROWABLE_FLAGS_REQUIRED koşulunu karşılar
  • JIT bölgesi serbest bırakılırken eklenen KBASE_REG_DONT_NEED flag’i, kbase_jit_grow başındaki kbase_mem_evictable_unmake içinde kaldırılır
  • Sonuç olarak kbase_mem_pool_grow çalışırken oluşan yarış penceresinde aynı JIT bölgesinde GPU page fault oluşturulursa fault handler bu bölgeyi genişletebilir
  • Fault handler reg->gpu_alloc->nents değerini değiştirirse, kbase_jit_grow’un daha önce sakladığı old_size ve delta değerleri gerçek durumla uyumsuz hâle gelir
  • Ardından kbase_alloc_phy_pages_helper_locked ve kbase_mem_grow_gpu_mapping, stale değerlerle backing page ayırma ve GPU eşleme işlemleri yaptığında GPU eşlemesi ile pages dizisi arasında tutarsızlık oluşur
  • Bu yarış, kbase_mem_pool_grow büyük bellek ayırma işlemi içerdiği için kolayca kazanılabilir

GHSL-2023-005 yamasından sonra değişen saldırı yöntemi

  • Önceki zafiyet GHSL-2023-005 kapsamında başka bir thread, KBASE_IOCTL_MEM_COMMIT ile JIT bölgesini küçülterek old_size ve delta değerlerini geçersiz kılabiliyordu
  • GHSL-2023-005 yamasından sonra KBASE_IOCTL_MEM_COMMIT ioctl ile JIT bellek boyutu değiştirilemez hâle geldi
  • CVE-2023-6241’de yarış penceresinde bölge küçültülemiyor, yalnızca büyütülebiliyor
  • Sadece büyütme durumunda son bazı backing page’ler GPU’ya eşlenmemiş olur; ancak baştan itibaren sürekli eşlenmiş yapı korunduğu için bu hemen sorun yaratmaz
  • Exploit, ek GPU fault’larıyla unmapped gap’in arkasında yeni eşleme oluşturur; ardından JIT serbest bırakma yoluyla shrink başlangıç noktasını bu gap’in içine denk getirerek istismar edilebilir bir durum oluşturur

GPU eşleme kaldırmadaki zayıf varsayım

  • kbase_mmu_teardown_pgd_pages, GPU sayfa tablolarını dolaşarak entry’leri invalid olarak işaretler ve GPU adres eşlemesini kaldırır
  • Bu fonksiyon, daha yüksek seviyeli PTE invalid ise o entry’nin kapsadığı büyük adres aralığının tamamının zaten unmapped olduğunu varsayıp atlar
  • Bir seviye 2 PTE, 512 sayfalık aralığı kapsar
  • Normal bir kbase_va_region içinde eşlenmiş sanal adresler her zaman bölgenin başlangıcından itibaren kesintisizdir ve ortada gap bulunmaz; bu yüzden bu atlama davranışı güvenlidir
  • CVE-2023-6241 exploit’i, eşlemeler arasında unmapped gap oluşturduktan sonra shrink başlangıç noktasını gap’in içine yerleştirir
  • kbase_mmu_teardown_pgd_pages, invalid seviye 2 PTE ile karşılaşınca 512 sayfayı atlar; ancak bunun arkasındaki bazı adresler gerçekte eşlenmiş olabilir
  • Hatalı şekilde atlanan GPU adresleri, backing page serbest bırakıldıktan sonra da ilgili fiziksel sayfaya erişimi sürdürür

Kernel kodu çalıştırmaya giden süreç

  • JIT bölgesi serbest bırakıldığında backing page’ler iade edilir; ancak hatalı şekilde kalan GPU eşlemesi, serbest bırakılan sayfalara erişmeye devam edebilir
  • Serbest bırakılmış backing page daha sonra başka kernel sayfaları için yeniden kullanılabilir
  • Kullanılan tekniklerden biri, serbest bırakılmış backing page’in GPU kbase_context’inin PGD(page table global directory)’si olarak yeniden kullanılmasını sağlamaktır
  • Mali driver’daki backing page ayırma işlemi hiyerarşik olarak yapılır
    • Önce mevcut kbase_context’in kbase_mem_pool’undan sayfa alınır
    • Yetersiz kalırsa pool->next_pool kullanılır
    • Bu da yetersiz kalırsa kernel buddy allocator üzerinden doğrudan sayfa ayrılır
  • pool->next_pool, Mali driver tarafından yönetilen ve tüm kbase_context’lerin paylaştığı bir bellek havuzudur; GPU bağlamının PGD ayırmalarında da kullanılır
  • Serbest bırakılmış sayfa PGD olarak yeniden kullanılırsa, geride kalan GPU adresiyle bu PGD GPU üzerinden tekrar yazılabilir
  • PGD yeniden yazıldığında, keyfi kernel belleği ve kernel kodu GPU’ya eşlenebilir
  • Bu durumda kernel kodu yeniden yazılarak keyfi kernel kodu çalıştırmak mümkün olur; kernel verileri okunup yazılarak process credential değişimi ve SELinux’un devre dışı bırakılması da yapılabilir
  • Pixel 8 için exploit ve yapılandırma notları GitHub Security Lab deposunda yayımlandı

MTE’nin neden atlatılabildiği

  • Bu exploit akışında MTE’ye özel ayrı bir atlatma adımı gerekmez
  • MTE, pointer’ın işaret ettiği bellek bloğunun tag’inin eşleşip eşleşmediğini denetleyerek hatalı dereference işlemlerini yakalayan bir özelliktir
  • CVE-2023-6241’in tetiklendiği anda pages dizisi ile GPU eşlemesi arasında tutarsızlık oluşur; ancak her birine ayrı bakıldığında invalid entry bulunmaz
  • kbase_mmu_teardown_pgd_pages GPU eşleme kaldırmayı atladığında, serbest bırakılmış bellek sayfasının fiziksel adresi GPU sayfa tablosunda kalır
  • GPU bu serbest bırakılmış sayfaya erişirken fiziksel adrese doğrudan eriştiği için pointer dereference denetiminden geçmez
  • MTE’nin GPU bellek erişimine etkisi de kesin değildir
  • Sonuç olarak bu bug, bir yardımcı işlemci olan GPU’nun fiziksel belleğe doğrudan eriştiği yolu kullanarak MTE korumasını atlatır

MTE sonrasında da kalan saldırı yüzeyi

  • CVE-2023-6241, kernel MTE etkinleştirilmiş Pixel 8’de bile tek bir bug ile keyfi kernel kodu çalıştırmaya ulaşılabildiğini gösteriyor
  • MTE, bellek bozulması azaltmalarında önemli bir ilerlemedir ve birçok bellek bozulması zafiyetini istismar edilemez hâle getirebilir; ancak her derde deva bir savunma değildir
  • Bu vakada GPU, fiziksel belleğe doğrudan erişerek MTE’yi atlatır
  • CPU tarafındaki donanım ve yazılım azaltma önlemleri arttıkça, yardımcı işlemciler ve onların kernel driver’ları güçlü bir saldırı yüzeyi olmaya devam edebilir

1 yorum

 
GN⁺ 2024-03-20
Hacker News yorumları
  • Buradaki kilit nokta, GPU'nun uzun zamandır Android’in baş ağrılarından biri olması.
    GPU’nun AP’ye çok güçlü erişim yetkileri var; bu da öne konan hafifletmeleri fiilen aşabilmesini sağlıyor. Sürücünün eşleme kodundaki hatalar güçlü saldırı primitiflerine dönüşüyor ve gerçek dünyadaki exploit’lerde de tekrar tekrar kötüye kullanıldı. Sonuçta mimari yeniden tasarlanana kadar çok şeyin değişmesi zor görünüyor.

    • Yarım yamalak yapılmış mobil GPU’ların kendi MMU’larını koymayı bırakıp standart giriş/çıkış MMU’su kullanması gerektiğini düşünüyorum.
    • Burada AP ne anlama geliyor?
  • Bu zafiyette ilginç olan, Arm Mali GPU’nun bellek yönetim birimindeki mantıksal hata olması ve Memory Tagging Extension’ı aşabilmesi.
    Ancak yazının geri kalanı, asıl nedenin bir yarış durumu olduğunu ve use-after-free’in bunun sonucu olduğunu açıklıyor gibi görünüyor.

  • Mart güncellemesinden önceki GrapheneOS kurulumları da etkilenmiş olabilir miydi?

    • GrapheneOS’un ana hedeflerinden biri güvenlik güncellemelerini mümkün olduğunca hızlı dağıtmak olduğundan, upstream’de yamalandıysa GrapheneOS’a neredeyse kesin olarak dahil edilmiştir.
      Zaman zaman yayımlanmadan önce AOSP güvenlik yama seviyelerini benimser veya henüz herkese açık olmayan AOSP ya da kernel kaynaklarındaki güvenlik düzeltmelerini de backport eder.
    • Bu, GPU’nun içindeki donanıma yakın bir sorun, belki de firmware ile ilgili bir mesele gibi göründüğünden Mart güncellemesinden sonra da etkisinin süreceğini düşünmüştüm. Çünkü o güncelleme Bluetooth stack’iyle ilgiliydi.
      Düzeltme: Dikkate almayın. Yakın tarihli GrapheneOS blogundaki “MTE’nin tüm sistem uygulamalarına da uygulanmasıyla ilgili bir sorun bulduk” yazısıyla karıştırmışım. GrapheneOS, 2024030600 sürümünde “tam 2024-03-05 güvenlik yama seviyesini” aldığına göre bu yama da dahil edilmiş görünüyor.
  • Olasılıksal Arm MTE bellek güvenliği, deterministik CHERI donanımına giden yolda bir basamak taşıdır: https://saaramar.github.io/memory_safety_blogpost_2022/ ve https://news.ycombinator.com/item?id=39668053
    Doğru hafifletme, birincil saldırı ilkelini, yani hatanın kök nedenini hedeflemelidir. Donanım çözümleri arasında CHERI (Morello, CheriIoT) ve MTE; yazılım hafifletmeleri arasında kalloc_type+dataPAC, AUTOSLAB, Firebloom, GuardedMemcpy, CastGuard ve saldırı yüzeyinin azaltılması; güvenli programlama dilleri arasında ise Rust ve Swift vardır. MTE ile CHERI birbirini iyi tamamlar ve bu alandaki hataları kök nedenlerinde ortadan kaldırmaya yardımcı olur. MSR, MSRC ve Azure Silicon, CHERI’yi en küçük RISC-V çekirdeği belirtimi olan RISC-V32E’ye kadar küçültme yönünü destekledi.
    Microsoft Research, IoT cihazları için CHERI donanım/yazılım yığınını açık kaynak olarak yayımladı: https://msrc.microsoft.com/blog/2023/02/first-steps-in-cheri...
    CHERI tabanlı mikrodenetleyici, komut kümesi mimarisi (ISA), uygulama ikili arayüzü (ABI), izolasyon modeli ve yazılım yığınının çekirdek kısmı birlikte tasarlandığında çok güçlü güvenlik garantileri elde etmeyi amaçlar. Bu mikrodenetleyici, CHERI-ISA özellikleriyle uzamsal güvenliğin deterministik hafifletilmesini; yük bariyerleri, sıfırlama, geri kazanım ve 1 bitlik bilgi akışı denetimiyle heap ve bölmeler arası stack zamansal güvenliğinin deterministik hafifletilmesini; ek CHERI-ISA özellikleri ve küçük bir monitörle ince taneli bölmelendirmeyi sağlar.
    David Chisnall, Cambridge Üniversitesi, https://lobste.rs/s/gnjx2n/c_can_be_memory_safe#c_9ohzku via https://eclypsium.com/blog/a-faster-path-to-memory-safety-ch...
    “Çeşitli güvenilir bilişim tabanlarında yer alan yaklaşık 13 milyar satır açık kaynak C/C++ kodu var; tescilli kodlar dahil edilince bu daha da büyüyor. Bugün herkes C/C++ yazmayı bıraksa ve tüm yazılım mühendisleri eski kodu güvenli bir dille yeniden yazmaya odaklansa bile, her şeyi değiştirmek 5 ila 10 yıl sürer; uzun süredir doğrulanmış kodu, güvenli dillerin izin verdiği kalıplara uyan farklı algoritmalar ve veri yapıları gerektiren yeni kodla değiştirirken çok sayıda mantık hatası doğması da çok olasıdır.”
    “Yeniden yazma yapılmadan yalnızca C/C++ kodu yazmayı bırakırsak, tipik kod değiştirme hızında güvenilir bilişim tabanının tamamen güvenli hale gelmesi yaklaşık 50 yıl alır. Herkes C/C++’ı bırakma konusunda anlaşmazsa en az 100 yıl sürer.”
    “Buna karşılık büyük CPU üreticileri 5 yıl içinde CHERI CPU’lar çıkarırsa, programcılar davranışlarını değiştirmese bile bugünden itibaren 15 yıl içinde makinelerin çoğu, özellikle de yüksek değerli makineler, bellek güvenliğine sahip olur.”

    • Gömülü/IoT’ye benzer kullanımlar için CHERI ile ilgileniyorsanız, lowRISC CHERIoT için birkaç FPGA tabanlı değerlendirme platformu geliştiriyor: https://www.sunburst-project.org/
      İlki Sonata sistemi: https://github.com/lowRISC/sonata-system. FPGA ile çeşitli çevre birimleri ve header’lara sahip özel bir PCB’den oluşuyor. PCB tasarımı tamamlandı ve Mouser üzerinden temin edilebilir olacak; kart yerleşimi de açık kaynak olduğundan isterseniz kendiniz de monte edebilirsiniz. Şu anda FPGA için RTL üzerinde çalışılıyor. Tamamlandığında belgeleri ve araçlarıyla birlikte CHERIoT tabanlı mikrodenetleyici tarzı bir sisteme sahip olacaksınız.
      Ayrıca Sonata ile OpenTitan Earl Grey güven kökünü birleştiren Symphony sistemini de geliştiriyorlar: https://github.com/lowRISC/symphony-system
    • Solaris SPARC ADI de var. Oracle ve Solaris SPARC’ın mevcut durumu nedeniyle çoğu kişi bunu unutmuş durumda; bu üzücü.
    • Bu, CPU dışındaki bir donanım hatası olduğu için CHERI’nin nasıl yardımcı olacağını bilmiyorum.
      Üstelik en son baktığımda CHERI sağlam değildi. Üzerinde yine de bellek hataları yazılabiliyordu; bu artık düzeltildi mi?
    • “Her şeyi değiştirmek 5 ila 10 yıl” yıllar cinsindeyse fazla iyimser görünüyor.
      Sadece bisiklet kulübesi tartışmaları bile o kadar sürecek gibi.
    • Temel sorun, kullanıcının kötü amaçlı kod çalıştırması ve bir MMU hash çakışmasını istismar etmesi gibi görünüyor.
      Bu exploit’in Rust dahil çoğu dille yazılabileceğini düşünüyorum.
  • Donanım o kadar mı kötü? Aman Tanrım...

    • GPU donanımı hatalarla doludur. Kabul edilebilir bir maliyetle sürücüde etrafından dolanılamayan bir sorun olduğunda donanım ancak yeniden basılır.
      Bu yaklaşımın mümkün olmasının nedeni, GPU’nun CPU gibi nispeten doğrudan donanım erişimine izin vermemesidir.
    • Bu, CPU’da çalışan bir sürücü hatasıdır
  • Harika bir araştırma ve yazı; GitHub blogunda yayımlanmış olması biraz şaşırtıcı ama sevindirici
    GitHub’ın bu tür araştırmalar yapmasının “iş gerekçesinin” ne olduğunu bilen var mı? Mutlaka bir iş gerekçesi olması gerektiğini söylemiyorum, ama burada görünce biraz şaşırdım

    • Man Yue Mo, GitHub tarafından satın alınmadan önce Semmle’de çalışıyordu (https://blog.sonatype.com/steps-to-responsible-disclosure, https://github.blog/2019-09-18-github-welcomes-semmle/)
      Bu araştırma işlevi GitHub Security Lab’e dönüştü. Semmle, CodeQL’i geliştirdi; bugün GitHub tarafından sunuluyor (https://docs.github.com/en/code-security/code-scanning/intro...). GitHub ve Microsoft, CodeQL’i “derin güvenlik içgörüleri” ile ilişkilendirmek istiyor (https://www.microsoft.com/en-us/security/blog/2023/11/02/ann...)
      Bu yüzden böyle özgün güvenlik araştırmalarını finanse etmeye devam ediyorlar; sektördeki güvenlik uygulayıcıları da bundan memnun
    • Bu çalışma GitHub’ın Security Lab’inden çıkmış: https://securitylab.github.com/
    • Microsoft tarafından satın alınmasıyla bu tür araştırmaları destekleyecek kaynaklar oluştu
      GitHub uygulaması da var ve o uygulamanın güvenliği GitHub’ın kapsamı dışında değil. Bir saldırgan telefona gizlenen bir uygulama yükleyebilirse kullanıcıymış gibi pek çok şey yapabilir. GitHub’da etkisi olan biri söz konusuysa zarar oldukça büyük olabilir; dolayısıyla bu tür açıkları bulmak GitHub’ın da yararına
    • GitHub’da Arm için barındırılan Actions runner’ları da var
      Bu nedenle MTE kullanarak sandboxing için Arm donanımındaki güvenlik özelliklerini kontrol edip doğrulamakla ilgileniyor olabilirler
    • Bana göre bu, fiilen temel araştırmaya daha yakın [0]
      İlk bakışta GitHub adlı ürün için Android güvenlik uzmanlarına mutlaka ihtiyaç yok. Ama uzun vadede potansiyel getirileri var
      [0]: https://en.wikipedia.org/wiki/Basic_research
  • GPU’su çok az olan ya da hiç olmayan CPU’lar ve telefonlar yapıp bunlara iş telefonu diyen örneklerin hâlâ olmaması şaşırtıcı
    Güvenlik, maliyet ve güç tüketimi açısından avantajları açık görünüyor

    • Bariz dezavantaj, yüksek çözünürlüklü dokunmatik ekranın olmaması ve bunun bizi Blackberry ya da Palm Treo’ya geri götürmesi. Aslında bunlar iş telefonu olarak satılmıştı