1 puan yazan GN⁺ 2024-07-02 | 1 yorum | WhatsApp'ta paylaş
  • OpenSSH sunucusu sshd içindeki bir sinyal işleyici yarış durumu nedeniyle, kimlik doğrulaması yapılmamış bir istemci, kimlik doğrulama öncesi zaman sınırı LoginGraceTime içinde varsayılan yapılandırmadaki sunucularda uzaktan kod yürütmeyi tetikleyebilir
  • Bu zafiyet, 2006 tarihli CVE-2006-5051'in bir regression'ıdır; Ekim 2020'de OpenSSH 8.5p1 içindeki sigdie() fonksiyonundan güvenlik önlemi kaldıran commit ile, 8.5p1 ve sonrası ile 9.8p1 öncesi sürümlerde yeniden ortaya çıktı
  • glibc tabanlı Linux'ta syslog(), malloc() ve free() gibi async-signal-unsafe fonksiyonları çağırdığı için, sandbox'a alınmamış sshd'nin privileged kodunda kimlik doğrulaması olmadan root RCE'ye yol açabilir
  • Deneyler i386 sanal makinede ve yaklaşık 10ms paket jitter'ına sahip kararlı bir ağda yapıldı; Debian 12.5.0 OpenSSH 9.2p1 üzerinde ortalama yaklaşık 10.000 deneme, MaxStartups=100 ve LoginGraceTime=120 koşullarında root shell'e ulaşmak yaklaşık 6-8 saat sürdü
  • OpenSSH, 6 Haziran 2024'te 81c1099 commit'iyle düzeltme yayımladı; güncelleme veya yeniden derleme zorsa LoginGraceTime 0 ile RCE engellenebilir, ancak MaxStartups bağlantı tükenmesi DoS riski kalır

Zafiyetin ortaya çıktığı nokta

  • OpenSSH sshd sorunu, kimlik doğrulama öncesi çalışan SIGALRM işleyicisinde başlıyor
    • İstemci LoginGraceTime içinde kimlik doğrulaması yapmazsa SIGALRM işleyicisi asenkron olarak çağrılıyor
    • Bu işleyici, syslog() gibi async-signal-safe olmayan fonksiyonları çağırıyor
    • Varsayılan değer LoginGraceTime=120 saniye; eski OpenSSH sürümlerinde bu süre 600 saniyeydi
  • Bu zafiyet, CVE-2006-5051'in bir regression
    • CVE-2006-5051, 2006'da Mark Dowd'un bildirdiği, OpenSSH 4.4 öncesindeki bir sinyal işleyici yarış durumu
    • Ekim 2020'de OpenSSH 8.5p1 içindeki 752250c commit'i, sigdie() içindeki #ifdef DO_LOG_SAFE_IN_SIGHAND korumasını yanlışlıkla kaldırdı
  • Sürümlere göre etki alanı net biçimde ayrılıyor
    • OpenSSH 4.4p1 öncesi: CVE-2006-5051 veya CVE-2008-4109 ile ilgili yamalar backport edilmediyse etkileniyor
    • OpenSSH 4.4p1 ve sonrası ile 8.5p1 öncesi: sigdie() güvenli _exit(1) çağrısına dönüştürüldüğü için bu yarış durumuna karşı savunmasız değil
    • OpenSSH 8.5p1 ve sonrası ile 9.8p1 öncesi: güvenlik önleminin kaldırılmasıyla yeniden savunmasız hale geldi

Etkilenen ortamlar ve istisnalar

  • Uzaktan sömürü hedefi glibc tabanlı Linux sistemler
    • glibc içindeki syslog(), dahili olarak malloc() ve free() gibi async-signal-unsafe fonksiyonları çağırıyor
    • Savunmasız kod, sshd'nin privileged kodunda bulunuyor ve sandbox olmadan tam yetkiyle çalışıyor
    • Sonuç olarak kimlik doğrulaması olmadan uzaktan root kod yürütme mümkün oluyor
  • Diğer libc'ler veya işletim sistemleri bu araştırmanın kapsamına dahil edilmedi
  • OpenBSD etkilenmiyor
    • OpenBSD'nin SIGALRM işleyicisi syslog() yerine syslog_r() çağırıyor
    • syslog_r(), OpenBSD'nin 2001'de geliştirdiği daha async-signal-safe bir sürüm

Uzaktan sömürü araştırmasının önkoşulları

  • Bu yarış durumunu uzaktan sömürmek için üç sorunun çözülmesi gerekiyor
    • SIGALRM doğru anda araya girdiğinde sshd'yi tutarsız bir durumda bırakacak bir kod yoluna ihtiyaç var
    • Bu kod yoluna ulaşıp doğru anda kesilme olasılığını artırmak gerekiyor
    • Uzak ağ ortamında da bu zamanlamanın tutturulabilmesi gerekiyor
  • Araştırma, en yeni koruma mekanizmalarıyla doğrudan uğraşmak yerine eski OpenSSH'nin i386 ortamında başlayıp daha yeni sürümlere genişledi
  • Deney koşullarının belirgin sınırlamaları var
    • Hedef olarak bare-metal sunucular değil, yalnızca sanal makineler kullanıldı
    • Ağ, yaklaşık 10ms paket jitter'ına sahip nispeten kararlı bir bağlantıydı
    • Exploit'in çeşitli bölümleri daha da geliştirilebilir
    • amd64 exploit çalışması başladı, ancak daha güçlü ASLR nedeniyle çok daha zor

Eski OpenSSH sürümleri üzerinde deneyler

  • Debian 3.0r6, OpenSSH 3.4p1

    • Hedef SSH-2.0-OpenSSH_3.4p1 Debian 1:3.4p1-1.woody.3; Debian 3.0r6'nın 2005 ortamı
    • Bu Debian sürümü, privilege separation özelliğinin varsayılan olarak etkin olduğu ilk Debian sürümüydü ve dönemin başlıca zafiyet yamalarını içeriyordu
    • Sömürü, free() kesintisi ve heap tutarsızlığı durumundan yararlanıyor
      • Açık anahtar ayrıştırma kodundaki free() çağrısı SIGALRM ile kesiliyor
      • Sonrasında packet_close() içindeki başka bir free() çağrısında tutarsız heap durumundan yararlanılıyor
    • glibc 2.2.5'te Solar Designer'ın unlink() tekniğine karşı güçlendirme yoktu
    • Saldırı, __free_hook üzerine yazarak yürütme akışını heap üzerindeki shellcode adresine yönlendiriyor
    • Bu Debian sürümünde ne ASLR ne de NX bulunuyor
    • Zamanlama iyileştirildikten sonra ortalama yaklaşık 10.000 deneme gerekti
    • MaxStartups=10, LoginGraceTime=600 koşullarında uzaktan root shell'e ulaşmak ortalama yaklaşık 1 hafta sürdü
  • Ubuntu 6.06.1, OpenSSH 4.2p1

    • Hedef SSH-2.0-OpenSSH_4.2p1 Debian-7ubuntu3; Ubuntu 6.06.1'in 2006 ortamı
    • CVE-2006-5051'e karşı hâlâ savunmasız olan son Ubuntu sürümü
    • glibc 2.3.6, malloc ailesi fonksiyonlarına girerken zorunlu lock aldığı için, malloc sırasında kesinti oluşturup ardından başka bir malloc çağrısını sömürme yaklaşımı deadlock'a yol açıyor
    • Nihai sömürü yolu PAM üzerinden kuruluyor
      • pam_start(), sshd'nin global sshpam_handle işaretçisini ayarlıyor
      • _pam_add_handler() kesilirse başlatılmamış bir next alanı kalabiliyor
      • pam_end(), SIGALRM işleyicisi içinde çağrıldığında free() fonksiyonuna rastgele bir işaretçi verebiliyor
    • glibc'deki eski unlink() tekniği engellendiği için Malloc Maleficarum'un House of Mind fastbin sürümü kullanılıyor
    • Sahte arena, sshd'nin .got.plt bölümüne yöneltiliyor ve _exit() girdisi heap shellcode adresiyle üzerine yazılıyor
    • Bu Ubuntu sürümünde heap varsayılan olarak yürütülebilir durumda
    • Ortalama yaklaşık 10.000 deneme gerekti
    • MaxStartups=10, LoginGraceTime=120 koşullarında uzaktan root shell'e ulaşmak ortalama yaklaşık 1-2 gün sürdü
    • Şanssız bir saldırgan, root shell elde etmeden önce 10 MaxStartups bağlantısının tamamını deadlock'a sokabilir

Debian 12.5.0, OpenSSH 9.2p1 deneyi

  • syslog() ve glibc malloc yolu

    • Hedef SSH-2.0-OpenSSH_9.2p1 Debian-2+deb12u2; Debian 12.5.0'ın 2024 tarihli current stable ortamı
    • Bu ortam, CVE-2006-5051 regression'ına karşı savunmasız
    • Bu sürümün SIGALRM işleyicisi packet_close() veya pam_end() çağırmıyor; bunun yerine syslog() yoluna gidiyor
      • grace_alarm_handler() sigdie() çağırıyor
      • sigdie(), sshlogv() ve do_log() üzerinden syslog() çağırıyor
    • Debian glibc 2.36 içindeki syslog(), ilk çağrıda malloc kullanıyor
      • __localtime64_r() yolunda __tzfile_read() çağrılıyor
      • fopen(), FILE yapısı için malloc(304) çağırıyor
      • Dahili read buffer için de malloc(4096) çağrılıyor
    • glibc malloc, Ekim 2017'den beri tek iş parçacıklı durumda zorunlu lock almıyor
    • sshd gibi tek iş parçacıklı süreçlerde malloc yarışından yararlanma olanağı doğuyor
  • ASLR koşulları ve i386 kısıtları

    • Debian 12.5.0 i386 ortamında bir ASLR zayıflığı var
    • sshd'nin PIE'si, heap'i, kütüphanelerin çoğu ve stack normalde rastgeleleştiriliyor
    • glibc'nin kendisi ise her zaman 0xb7200000 veya 0xb7400000 adresine map ediliyor
    • glibc adresi %50 olasılıkla tahmin edilebiliyor
    • Exploit, glibc'nin 0xb7400000 adresine map edildiğini varsayıyor
    • Çünkü bu adres 0xb7200000'a göre biraz daha sık görülüyordu
  • Heap tutarsızlığı ve FILE yapısı sömürüsü

    • Seçilen malloc yolu, büyük bir free chunk'ı ikiye bölen split yolu
    • Bunun sonucunda döndürülecek chunk ve bir remainder chunk oluşuyor
    • SIGALRM, remainder chunk unsorted list'e bağlandıktan sonra ama size alanı başlatılmadan önce araya girerse heap tutarsızlığı oluşuyor
    • Saldırgan, önceki heap allocation'larından kalan verilerle remainder chunk'ın size alanını kontrol edebiliyor
    • Remainder chunk gerçekte olduğundan daha büyük gösterilerek başka heap chunk'larıyla örtüşmesi sağlanıyor
    • SIGALRM işleyicisi içindeki malloc bu chunk'ı kullandığında heap belleği bozuluyor
    • Hedef, __tzfile_read() içindeki fopen() tarafından heap üzerinde ayrılan FILE yapısı
      • Sınırlı heap corruption ile FILE yapısındaki _vtable_offset değerinin 1 baytı üzerine yazılıyor
      • glibc libio fonksiyonları, vtable işaretçisini varsayılan konum yerine farklı bir offset'te aramaya başlıyor
      • Saldırgan, bu konumdaki sahte vtable pointer'ını ve _codecvt pointer'ını önceki heap allocation kalıntılarıyla kontrol ediyor
    • i386 glibc üzerinde bu teknik, __fread_unlocked() sırasında rastgele bir __fct fonksiyon işaretçisinin çağrılmasını sağlayabiliyor
    • amd64 glibc'nin _vtable_offset alanını kullanmadığı görülüyor
  • Heap yerleşimi ve 27 yarış penceresi

    • Tek bir küçük yarış penceresi yarış durumunu kazanmak için yeterli olmadığından 27 çift büyük boşluk ve küçük boşluk oluşturuluyor
    • 28 çift, PACKET_MAX_SIZE olan 256KB sınırını aşıyor
    • Nihai paket, malloc(~4KB), malloc(304), malloc(~4KB), malloc(304) sırasını zorunlu kılıyor
    • Her büyük boşluk split işlemi doğru anda kesilirse, SIGALRM işleyicisindeki fopen() ilgili küçük boşluğu FILE yapısı olarak ayırıyor
    • Heap yerleşimini kurmak için sshd'nin açık anahtar ayrıştırma kodu kullanılıyor
      • cert_parse() ve cert_free() yolları üzerinden keyfiye yakın malloc() ve free() dizileri yürütülüyor
      • Bellek sızıntısı bulunamadığı için tcache chunk'ları geçici barrier chunk olarak kullanılıyor
    • Beş tür açık anahtar paketi gönderiliyor
      • a/ kontrol edilemeyen heap allocation'larının tcache chunk'larına gitmesi sağlanıyor
      • b/ 27 çift large/small hole ve barrier chunk oluşturuluyor
      • c/ fake header, fake footer, fake vtable ve _codecvt pointer yazılıyor
      • d/ yaklaşık 256KB'lik büyük bir string allocate edilip serbest bırakılarak boşluklar unsorted list'ten ilgili malloc bin'lerine taşınıyor
      • e/ son malloc dizisi zorlanarak 27 küçük yarış penceresi açılıyor
  • Yeni sürümler için zamanlama stratejisi

    • Eski sürümlerde kullanılan feedback tabanlı zamanlama stratejisi OpenSSH 9.2p1 hedefinde işe yaramadı
    • Beşinci açık anahtar ayrıştırması yaklaşık 10ms sürdüğü için büyük yarış penceresi fazla geniş kaldı
    • OpenSSH 7.8p1'de gelen user_specific_delay(), yanıtları en fazla yaklaşık 9ms geciktirerek mevcut feedback yöntemini bozdu
    • Yeni strateji, kasıtlı iki hata yanıtının süresini karşılaştırıyor
      • Açık anahtar ayrıştırmasından hemen önce hata üreten bir paket gönderiliyor
      • Açık anahtar ayrıştırmasından hemen sonra hata üreten bir paket gönderiliyor
      • İki yanıt süresi arasındaki farkla son açık anahtar ayrıştırmasının süresi ölçülüyor
    • Bu stratejiyle yarış durumu ortalama yaklaşık 10.000 denemede kazanıldı
    • MaxStartups=100, LoginGraceTime=120 koşullarında yarış durumunu kazanmak ortalama yaklaşık 3-4 saat sürdü
    • ASLR nedeniyle uzaktan root shell'e ulaşmak için ortalama yaklaşık 6-8 saat gerekti

amd64 exploit durumu

  • amd64 hedefi olarak Rocky Linux 9 seçildi
    • Hedef imaj Rocky-9.4-x86_64-minimal.iso
    • OpenSSH 8.7p1 bu sinyal işleyici yarış durumuna karşı savunmasız
    • glibc, ASLR zayıflığı nedeniyle 2MB katlarında map edildiğinden partial pointer overwrite daha güçlü hale geliyor
  • Rocky Linux 9 üzerindeki glibc 2.34 syslog(), dahili olarak __open_memstream() çağırıyor
    • Heap üzerinde FILE yapısı için malloc() yapıyor
    • calloc(), realloc() ve free() de çağrılarak ek hareket alanı sağlanıyor
  • Heap corruption primitive'i, heap üzerinde ayrılan iki FILE yapısı ve glibc adresinin 21 sabit biti temel alınarak amd64'te de sömürünün mümkün olduğu değerlendiriliyor
    • Beklenen süre i386'daki 6-8 saatten uzun olsa da 1 haftadan kısa olacağı öngörülüyor
  • Ubuntu 24.04 için ayrı bir gözlem de var
    • Ubuntu 24.04, sshd child sürecinin ASLR'ını her seferinde yeniden rastgeleleştirmiyor; yalnızca açılışta bir kez rastgeleleştiriyor
    • Bunun nedeni, rexec_flag değerini kapatan systemd-socket-activation.patch yaması olarak izleniyor
    • Bu normalde kötü bir tercih olsa da, bu zafiyette SIGALRM işleyicisindeki syslog() ilk syslog() çağrısı olmadığı için malloc fonksiyonlarını çağırmıyor ve böylece sömürüyü engelliyor
    • İlgili yama: https://git.launchpad.net/ubuntu/+source/…

Yama ve hafifletme önlemleri

  • OpenSSH, 6 Haziran 2024'te 81c1099 commit'iyle bu yarış durumunu düzeltti
    • 81c1099: sshd(8) için sorunlu istemci davranışını cezalandıran bir özellik eklendi
    • async-signal-unsafe kod, sshd'nin SIGALRM işleyicisinden listener process'e taşınarak senkron şekilde işleniyor
  • Bu düzeltme, büyük 81c1099 commit'i ile daha da büyük bir defense-in-depth commit'i olan 03e3de4 üzerine kurulu olduğu için backport edilmesi zor olabilir
  • Backport zorsa sshsigdie() içinden async-signal-unsafe kod kaldırılabilir veya yorum satırına alınarak yalnızca _exit(1) çağrısı bırakılabilir
  • Güncelleme ya da yeniden derleme mümkün değilse yapılandırma dosyasında LoginGraceTime değeri 0 yapılabilir
    • Bu ayar, bu advisory'deki uzaktan kod yürütmeyi engeller
    • Ancak bunun karşılığında tüm MaxStartups bağlantılarının tüketildiği bir DoS durumuna açık kalınır

Açıklama takvimi

  • 2024-05-19: OpenSSH geliştiricileriyle iletişime geçildi; ardından yama ve inceleme süreci tekrarlandı
  • 2024-06-20: distros@openwall ile iletişime geçildi
  • 2024-07-01: coordinated release date kapsamında açıklandı

1 yorum

 
GN⁺ 2024-07-02
Hacker News yorumları
  • İlginç biçimde, RCE düzeltmesi neredeyse bir ay önce herkese açık şekilde “araya karışmış” gibi görünüyor.
    PerSourcePenalties etkin olduğunda sshd(8), kimlik doğrulama öncesi alt oturum süreçlerinin çıkış durumunu izler ve tekrarlanan kimlik doğrulama hataları ya da sshd çökmeleri gibi koşulları istemci adresine belirli bir süre için ceza olarak kaydeder.
    https://github.com/openssh/openssh-portable/commit/81c1099d2...
    Saldırgana bir şeyler anlatan tersine analiz edilebilir bir yamadan ziyade, ikili dosya yapısını değiştirip belirli bir zafiyeti ortadan kaldıran ve aynı zamanda bu exploit ailesinin tamamını hafifleten bir yan etkisi varmış gibi görünüyor; bu yüzden epey zekice duruyor.

    • Bu RCE düzeltmesi değil; gerçek RCE düzeltmesi şu: https://news.ycombinator.com/item?id=40843865
      Yukarıdaki değişiklik, çöp bağlantılarla başa çıkmak için önceden duyurulmuş bir özellikti; yalnızca yarış durumunu kazanmayı zorlaştırarak bu zafiyeti de hafifletiyor.
      Önceki tartışma: https://news.ycombinator.com/item?id=40610621
    • Bu düzeltmenin dağıtımlara şimdiden yansıtılıp yansıtılmadığını ya da çekilip çekilmediğini merak ediyorum.
    • Bu yorumun yanlış olup hemen altında düzeltilmesine rağmen 2 gün boyunca en üstte kalması ilginç.
      İnsanların iş parçacığındaki ilk yorumu okuyup oyladıktan sonra yanlış bir izlenimle ayrılıp ayrılmadığını merak ediyorum.
  • OpenSSH sürüm notlarındaki bir bölüm ilginç.
    “ASLR etkin 32 bit Linux/glibc sistemlerde başarılı istismar gösterildi. Laboratuvar koşullarında saldırı, sunucunun izin verdiği maksimum değere kadar ardışık bağlantıların ortalama 6-8 saat sürdürülmesini gerektiriyor. 64 bit sistemlerde de mümkün olduğuna inanılıyor, ancak henüz gösterilmiş değil. Bu tür saldırıların iyileştirilmesi muhtemel.”
    https://www.openssh.com/releasenotes.html

  • Hatanın eklendiği diff'e [1] bakınca, analize göre sorun sigdie() işlevinin #ifdef DO_LOG_SAFE_IN_SIGHAND ile sarmalandığı biçimden, sshsigdie() işlevinin doğrudan sshlogv() çağırdığı biçime refactor edilirken #ifdef'in düşmüş olması.
    Ne bunu engelleyebilirdi? Pull request'lere daha fazla kişi mi bakmalıydı? Tüm dünyanın güvenli erişim için dayandığı bir yazılımın fiilen iki kişi [2] tarafından bakımının yapılıyor gibi görünmesi şaşırtıcı.
    [1] https://github.com/openssh/openssh-portable/commit/752250caa...
    [2] https://github.com/openssh/openssh-portable/graphs/contribut...

    • Olaydan sonra ne yapılsaydı engellenebilirdi demek kolay.
      Bu durumda #ifdef'in neden gerekli olduğunu açıklayan bir yorum olsaydı yardımcı olabilirdi. Örneğin “buradaki kod async-signal-safe olmalı ve kilit durumu belirsiz olabilir” gibi.
      Ancak dürüst olmak gerekirse getrlimit de şu listede yok: https://man7.org/linux/man-pages/man7/signal-safety.7.html
      Yine de async-signal-safety ile ilgili yorum taşıyan bir kod kaldırılmış ya da değiştirilmiş olsaydı, incelemede göze çarpma ihtimali vardı. Alıntılanan kodda yalnızca SAFE_IN_SIGHAND gibi bir ifade, bu kodun sinyal işleyicisi içinde güvenli olması gerektiğini ima ediyor.
    • OpenBSD, sistemi async-signal-safe ve reentrant syslog işlevleri kullanacak şekilde refactor ettiği için, bu kodu yazan kişi değişikliğin güvenli olduğunu basitçe varsaymış olabilir.
      OpenBSD ssh geliştiricilerinin gerçekten desteklediklerini iddia etmediği diğer platformlarda hâlâ async-signal-unsafe işlevler kullanıldığını unutmuş ya da bilmiyor olabilir.
    • Açık kaynak. Daha iyisini yapabileceğinizi düşünüyorsanız istediğiniz gibi fork edebilirsiniz.
      Açık kaynak geliştiricilerinden bir şey almaya hakkınız yok. Onlar da hata yapabilir ve kaç bakımcı ya da inceleyici bulunduracaklarına kendileri karar verebilir.
      https://gist.github.com/richhickey/1563cddea1002958f96e7ba95...
    • “Tüm dünyanın güvenli erişim için dayandığı yazılımın fiilen iki kişi tarafından bakımı yapılıyor” sözü, zorunlu olarak şu xkcd'yi akla getiriyor: https://xkcd.com/2347/
    • Bunu engellemenin birkaç yolu vardı.
      1. Rastgele işlevlerin sinyal işleyicisi olarak ayarlanmasına izin vermeyen düzgün bir programlama dili kullanmak. Genel libc'de bu açıkça güvenli değildir; güvenli Rust ya da Java'da bunu bu şekilde yapamazsınız.
      2. Async-signal-unsafe bir işlev çağrıldığında bellek bozulması yerine en fazla deadlock oluşturan, iyi uygulanmış bir libc kullanmak. Sinyal içinde çalışan kodu, thread-local storage erişimi açısından ayrı bir thread gibi ele alırsanız bu görece kolay mümkündür; global mutex yoksa ya da mutex'i tutan kesintiye uğramış kodu sürdürebiliyorsanız deadlock da önlenebilir.
      3. Kod değiştirirken ve onaylarken düşünmek. [1]'de olduğu gibi gerekçesiz şekilde #ifdef'i kaldıran insanlar gibi davranmamak.
      4. OpenSSH yerine iyi programcılar tarafından yazılmış, basit ve iyi tasarlanmış yazılım kullanmak.
  • Sürüm notları da okunmaya değer: https://www.openssh.com/releasenotes.html
    Bu aslında ilginç bir signal race condition hatasının bir varyantı. Zafiyet raporuna göre “OpenBSD özellikle savunmasız değil; çünkü SIGALRM işleyicisi, OpenBSD’nin 2001’de yaptığı, asenkron sinyaller açısından daha güvenli syslog() sürümü olan syslog_r()’yi çağırıyor”
    Yani sinyal güvenliği azaltımı, OpenBSD geliştiricilerinin sinyal işleyicisinin içine önemsiz olmayan kod koymasına yol açmış; bu kod başka sistemlere taşınınca güvensiz hale gelmiş. Genel kabul gören bilgiye ve Unix kod geleneklerine uygun şekilde sinyal işleyicisinin içindeki kodu minimuma indirecek bir refactoring yapılsaydı bu hatadan kaçınılabilirdi

    • Theo de Raadt, bu hatayı ve benzerlerini önleme konusunda oldukça yerinde bir gözlem yapmış: hiçbir sinyal işleyicisi signal-safe sistem çağrısı olmayan bir fonksiyonu çağırmamalı
      Çünkü zaman geçtikçe geçişli çağrıların bir yerinde asenkron sinyaller açısından güvenli olmayan bir çağrının araya karışması çok kolaydır; ayrıca o yolun sinyal bağlamından erişilebilir olduğu da her zaman açık değildir
    • Bu zafiyeti yamaması gereken genç sistem yöneticileri veya stajyerler arasında, OpenBSD bu çözümü uyguladığında henüz doğmamış olan epey kişi olması muhtemel
  • OpenSSH instance’larımı yükselttikten sonra, bunların glibc’ye değil musl’a linklendiğini gördüğüm için musl’ın syslog(3)ünün de allocation yapıp yapmadığına, dolayısıyla aynı şekilde kolayca exploit edilip edilemeyeceğine baktım
    Görünüşe göre öyle değil: https://github.com/bminor/musl/blob/master/src/misc/syslog.c
    Orada olanların hepsi stack üzerinde ya da yeniden girişi kilitle engelleyen statik değişkenler. {d,sn,vsn}printf() çağrıları da musl’da allocation yapmıyor, ama glibc’de yapabilir. Gözden kaçırdığım bir şey var mı?

    • Rich’in doğrulaması: https://fosstodon.org/@musl/112711796005712271
    • Allocation konusundaki değerlendirme doğruysa, en kötü durumda kilit recursive olmadığı için deadlock yaşanması gibi görünüyor
      Yine de sigalrm içinde deadlock olursa bağlantı temizliğini engelleyebilir ve bu da hizmet reddine yol açabilir
  • FreeBSD için yama çıktı
    Etkilenip etkilenmediği net değil. Bilinen exploit yalnızca glibc’de mümkündü ve FreeBSD glibc kullanmıyor, ama güvenli tarafta kalmak iyi olur
    https://www.freebsd.org/security/advisories/FreeBSD-SA-24:04...

  • Rapora göre sshd’yi güncelleyemiyor ya da yeniden derleyemiyorsanız, yapılandırma dosyasında LoginGraceTime değerini 0 yapmak tek başına bu sinyal işleyici race conditionını düzeltebilir
    Bu durumda sshd, tüm MaxStartups bağlantılarının tüketildiği hizmet reddine açık hale gelir; ancak bu duyuruda belirtilen uzaktan kod çalıştırmaya karşı güvenli olur
    Dolayısıyla sshd_config içine LoginGraceTime 0 yazmak bir azaltım gibi görünüyor

    • Bir dakika, https://www.man7.org/linux/man-pages/man5/sshd_config.5.html değer 0 ise zaman sınırı olmadığını söylüyor
      Bu daha kötü değil mi?
    • Daha gerçekçi workaround, grace time’ı yeterince uzun yapmak ya da tersine maksimum bağlantı sayısını ayarlayarak başarılı saldırı olasılığını denemeye değmeyecek kadar uzak bir geleceğe itmek olabilir
    • sshd’yi her saat cold restart yapmak da exploit edilebilirliği azaltır ya da daha zor hale getirir mi?
  • Debian 12 için yama çıktı; Debian 11 etkilenmiyor
    https://security-tracker.debian.org/tracker/CVE-2024-6387

    • Focal(20.04) etkilenen bir sürüm değil gibi, Jammy(22.04) ise etkileniyor gibi görünüyor
    • Debian 12 sunucusunda az önce apt update ve upgrade çalıştırdım; yükseltilen tek şey OpenSSH paketiydi
    • Pi OS bullseye’a da güncellenmiş openssh’nin geldiğini doğruladım
  • Gerçekten iyi bir keşif.
    Doğrudan bu işin içinde olan biri değilim ama güvenlik araştırmalarında “kazanmak” için tek bir sorunu bulup düzeltmek ya da ödül almak değil, uzaktan erişime kadar uzanan tüm zinciri bulmak gerektiği havası sık sık hissediliyor.
    Tek bir açık, örneğin tek bir bellek bozulması ya da sandbox’tan kaçış bulmak bile yeterli olmalı değil mi diye düşünüyorum. Şu anda küçük sorunlar o kadar fazla ki, insanların bunu gerçekten ciddiye alması ya da bug bounty ödemesi için sonuna kadar giden bir hack göstermenin gerekip gerekmediğini bilmiyorum.

    • Sömürülebilir olmayan bir sorun bulup CVE numarası, takdir, hatta ödül isteyen çok sayıda güvenlik araştırmacısı adayı var.
      Örneğin bir uygulama hatalı güvenilen girdi aldığında çöküyorsa, ama uygulamanın doğası gereği saldırganlara açık olması amaçlanmamışsa ve pratikte de bunun olması gerçekçi değilse, çoğu kişi bunu güvenlik hatası değil, sadece bug olarak görür. Düzeltilmesi iyi olur ama aynı seviyede değildir; ayrıca bunları bulmak da çok zor değildir.
      Bu yüzden bu örnekteki gibi “gerçek” güvenlik hataları ile güvenlik etkisi olmayan hataları ayırmak gerekiyor; sorunun sömürülebilir olduğunu kanıtlamak çok önemli.
      Güvenlik etkisi olmayan bug’lar sonsuz sayıda olacağından, bu kanıtlama gereksiniminin yakın zamanda ortadan kalkacağını sanmıyorum.
    • Başka bir açıdan bakarsak, güvenilmeyen veriyi verdiğimde savunmasız hâle gelen bir serileştirme/ters serileştirme kütüphanesi yaptığımı varsayalım.
      Bu tasarım gereğidir; kullanıcılar lambda fonksiyonları dahil her şeyi serileştirip ters serileştirebilir. Kütüphanem yalnızca güvenilen kaynaklardan gelen verilerin işlenmesi için tasarlanmıştır.
      Bildiğim kadarıyla kimse bu kütüphaneyi güvenilmeyen verileri işlemek için kullanmıyor. Popüler bir kütüphane, yapılandırma dosyasını okumak için benim kütüphanemi kullanıyor, ancak onlar yapılandırma dosyasını güvenilen veri olarak görüyor. Ayrıca başkalarının kütüphanemi nasıl kullandığını denetlemek benim işim değil.
      Bu durumda projemde uzaktan kod çalıştırma açığı var diye en yüksek öncelikli bir CVE kaydı açmak doğru mu?
    • Raporlayan tarafta bulunmuş biri olarak, “sömürülebilir güvenlik açığı” ile “bir gün sömürülebilir bir güvenlik açığına dönüşebilecek güvenlik zayıflığı” çok farklı şeyler.
      Ödül her zaman ilk kategoriye ödenir. İkinci kategoriye giren raporlar, kavram kanıtı veya sömürülebilirlik kanıtı yoksa itibar ya da sinyal açısından zarar bile verebilir.
      Belirli koşullar sağlanana kadar sömürülebilir hâle gelmeyen zayıflıklar neredeyse her zaman vardır. Pwn2Own gibi yarışmalarda da birden fazla açığın zincirlenerek sonunda cihazın ele geçirildiği ve bunların yıllarca yamalanmadan kaldığı sık görülür. Araştırmacılar etkiyi en üst düzeye çıkarmak için böyle zayıflıkları uzun süre bekletebilir.
      Üzücü ama gerçek bu.
    • Güvenlik özdeyişine göre: POC || GTFO
    • Alıcı sonuca para öder. Tedarikçi ise zincirin tek tek halkaları için de para öder.
  • OpenSSH sürüm notları: https://www.openssh.com/txt/release-9.8
    Yükseltme yapamayan ya da yapmak istemeyenler için asgari yama: https://marc.info/?l=oss-security&m=171982317624594&w=2

    • “64 bit sistemlerde sömürünün de mümkün olduğu düşünülüyor, ancak şu an itibarıyla kanıtlanmış değil.”