- ruby-saml 1.17.0 ve öncesinde bulunan CVE-2025-25291 ve CVE-2025-25292, tek bir geçerli imzayla herhangi bir kullanıcı olarak oturum açmayı mümkün kılarak SAML SSO ortamlarında hesap ele geçirme riskini artırıyor
- Açık, imza doğrulama akışında REXML ile Nokogiri'nin aynı XML belgesindeki farklı
Signatureöğelerini yorumlayabilmesine yol açan ayrıştırıcı farkından kaynaklanıyor SignedInfo,SignatureValue, assertion hash'i veDigestValue, farklı ayrıştırıcı sonuçlarından bir araya gelirken her kontrol geçse de hash ile imza arasındaki bağ kopabiliyor- GitHub, ruby-saml'i yeniden devreye almayı değerlendirirken bug bounty ve Security Lab incelemesi yürüttü; GitLab'de istismar edilebilir örnekler bulup güvenlik ekibine bildirdi; şu anda GitHub kimlik doğrulamasında ruby-saml kullanılmıyor
- Kullanıcıların ruby-saml 1.18.0 sürümüne güncellemesi gerekiyor;
omniauth-samlgibi ruby-saml'e bağlı kütüphaneler de düzeltilmiş sürümü referans alan bir sürüme birlikte yükseltilmeli
ruby-saml kimlik doğrulama atlatmasının etkisi
- ruby-saml 1.17.0 ve öncesinde yüksek önem dereceli 2 kimlik doğrulama atlatma açığı tespit edildi
- CVE-2025-25291
- CVE-2025-25292
- Saldırgan, hedef kuruluşun SAML response veya assertion doğrulamasında kullanılan anahtarla üretilmiş tek bir geçerli imzaya sahipse doğrudan bir SAML assertion oluşturup istediği kullanıcı olarak oturum açabiliyor
- Olası imza kaynakları şunlar olabilir
- Yetkisi düşük başka bir kullanıcının imzalı assertion'ı veya response'u
- Bazı durumlarda, herkese açık erişilebilen bir SAML IdP'nin imzalı metadata'sı
- Bu açık sonuç olarak hesap ele geçirme saldırılarında kullanılabiliyor
- GitHub şu anda kimlik doğrulamada ruby-saml kullanmıyor; ancak SAML kimlik doğrulamasında açık kaynaklı bir kütüphaneyi yeniden kullanma seçeneğini değerlendirirken ruby-saml'i incelemeye aldı
- ruby-saml başka popüler projelerde ve ürünlerde de kullanılıyor; GitHub, GitLab'de istismar edilebilir bir örnek tespit ederek GitLab güvenlik ekibine bildirdi
GitHub neden ruby-saml'i yeniden değerlendirdi?
- GitHub 2014'e kadar ruby-saml kullanıyordu, ancak o dönemde gerekli özellikler eksik olduğu için kendi SAML uygulamasına geçti
- Sonrasında kendi uygulamasında da şifrelenmiş assertion'larla ilgili CVE-2024-9487 gibi bug bounty raporları gelince GitHub, ruby-saml'i yeniden devreye alma seçeneğini değerlendirmeye başladı
- Ekim 2024'te ahacker1 tarafından bulunan ruby-saml kimlik doğrulama atlatma açığı CVE-2024-45409 kamuya açıklandı
- GitHub, ruby-saml'e geçiş olasılığını daha yakından değerlendirmek için özel bir bug bounty başlattı
- Seçilen araştırmacılara, ruby-saml ile SAML kimlik doğrulaması yapan GitHub test ortamına erişim sağlandı
- GitHub Security Lab de ruby-saml'in saldırı yüzeyini birlikte inceledi
İki XML ayrıştırıcısının oluşturduğu doğrulama tutarsızlığı
- Kod incelemesi sırasında ahacker1 ve GitHub Security Lab, ruby-saml'in imza doğrulama yolunda iki XML ayrıştırıcısının birlikte kullanıldığını belirledi
- REXML: Tamamen Ruby ile yazılmış bir XML ayrıştırıcısı
- Nokogiri: libxml2, libgumbo ve JRuby için Xerces gibi bileşenleri saran API'ler sunar ve XML ile HTML ayrıştırmayı destekler
- Sorunlu akış
xml_security.rbiçindekivalidate_signaturemetoduydu - Bu metod ilk
Signatureöğesini ve gerçekSignatureValuedeğerini REXML ile okuyorREXML::XPath.first(@working_copy, "//ds:Signature", {"ds"=>DSIG})
- Buna karşılık aynı doğrulama akışı içinde
SignatureveSignedInfo, Nokogiri ile yeniden bulunup canonicalize ediliyordocument.at_xpath('//ds:Signature', 'ds' => DSIG)noko_signed_info_element.canonicalize(canon_algorithm)
- assertion, Nokogiri ile çıkarılıp canonicalize edilip hash'lenirken karşılaştırma için kullanılan
DigestValueREXML'den geliyor - Son doğrulama malzemesi şu şekilde ayrışıyor
- assertion, Nokogiri ile çıkarılıp canonicalize edildikten sonra hash'leniyor
- karşılaştırılan hash, REXML'in okuduğu
DigestValuedeğerinden geliyor SignedInfo, Nokogiri ile çıkarılıp canonicalize ediliyorSignatureValue, REXML ile çıkarılıyor
SAML imza doğrulamasında kopan güvenlik bağı
- SAML response, IdP'den SP'ye oturum açan kullanıcı bilgisini XML biçiminde taşır
- HTTP POST binding kullanıldığında SAML response kullanıcının tarayıcısından geçerek SP'ye ulaştığı için, kullanıcının mesajı değiştirememesini sağlamak adına imza doğrulaması gerekir
- Basitleştirilmiş bir SAML response'ta önemli bilgiler genellikle
AssertioniçindekiSubjectveNameIDalanlarında bulunur - Genellikle assertion veya tüm SAML response imzalanabilir
- assertion imzalıysa doğrulama iki adımda yapılır
Signatureçıkarılmış assertion canonicalize edilip hash'lenir veDigestValueile karşılaştırılırSignedInfocanonicalize edilir veSignatureValueile imza doğrulanır
- Bu açıkta iki adım ayrı ayrı başarılı olsa bile aynı veriyi doğruladıkları garanti edilmez
- hash gerçek assertion'ın hash'i olabilir
- imza ise başka bir
SignedInfoöğesine ait olabilir
- Gerekli güvenlik özelliği, hash'lenen içerik, hash ve imza arasında doğrudan bağ kurulmasıdır; doğrulama sonrasında da bilgi yalnızca gerçekten doğrulanmış bölümden okunmalıdır
Gerçek istismarın nasıl kurulduğu
- Temel koşul, REXML ile Nokogiri'nin aynı XML belgesinde farklı
Signatureöğeleri görmesini sağlamaktı ve bunun gerçekten mümkün olduğu gösterildi - ahacker1, bug bounty sürecinde önce ayrıştırıcı farkına dayalı çalışan bir istismar geliştirdi
- Bunun ilhamı, Mattermost'tan Juho Forsén'in 2021'de yayımladığı XML roundtrips vulnerabilities yazısından geldi
- GitHub Security Lab ise Trail of Bits'in Ruby fuzz aracı ruzzy ile başka bir ayrıştırıcı farkı tabanlı istismar oluşturdu
- Örnek istismar,
StatusDetailöğesi içine yalnızca Nokogiri'nin görebildiği ek birSignatureyerleştiriyor - Doğrulama akışı şu şekilde ayrılıyor
- Nokogiri'nin gördüğü signature içindeki
SignedInfocanonicalize ediliyor - doğrulama, REXML'in gördüğü signature'dan çıkarılan
SignatureValueile yapılıyor - Nokogiri'nin ID ile bulduğu assertion canonicalize edilip hash'leniyor
- bu hash, REXML'in okuduğu
DigestValueile karşılaştırılıyor
- Nokogiri'nin gördüğü signature içindeki
- Sonuçta geçerli
SignedInfoile geçerli imza birbiriyle uyuşuyor; manipüle edilmiş assertion ile onun hesaplanan digest'i de uyuştuğu için ruby-saml assertion'ı kabul ediyor
Azaltma önlemleri ve tespit sınırlamaları
- SAML response Nokogiri ile ayrıştırılırken ayrıştırma hatalarının kontrol edilmesi, şu anda bilinen bazı özel istismarları engelleyebilir
- Nokogiri ayrıştırma hataları istisna olarak fırlatılmadığı için, ayrıştırılmış belgenin
errorsüyesi doğrudan kontrol edilmelidir - Örnek kod
Nokogiri::XML::ParseOptions::STRICT | Nokogiri::XML::ParseOptions::NONETseçeneklerini kullanıyor vedoc.errors.any?olduğunda hata üretiyor - Bu yaklaşım tam bir düzeltme olmasa da, en az bir istismarı çalışamaz hale getiriyor
- Bilinen güvenilir bir ihlal göstergesi yok
- Olası bir gösterge yalnızca debug benzeri ortamlarda çalışıyor
- Bunu açıklamak, çalışan istismarın uygulama ayrıntılarını fazla ortaya çıkaracağı için paylaşılmadı
- Önerilen kontrol yöntemi, SP tarafında kullanıcının beklenen konumuyla uyuşmayan IP adreslerinden gelen SAML oturum açma kayıtları gibi şüpheli girişleri aramaktır
Düzeltme yönü ve güncellenmesi gerekenler
- İlk düzeltme, API uyumluluğu sorunları nedeniyle XML ayrıştırıcılardan birini kaldırmıyor
- Daha temel sorun, hash doğrulaması ile imza doğrulamasının ayrılmış olmasıydı ve bu ayrım ayrıştırıcı farkları üzerinden istismar edilebildi
- XML ayrıştırıcılardan birini kaldırma çalışması zaten başka nedenlerle planlanmıştı; ek iyileştirmelerle birlikte büyük bir sürümde yapılması mümkün görünüyor
- ruby-saml kullanıcıları, düzeltmeyi içeren 1.18.0 sürümüne güncelleme yapmalı
- ruby-saml kullanan kütüphaneler de birlikte kontrol edilmeli
- Örnek: omniauth-saml
- Bu kütüphane de düzeltilmiş ruby-saml sürümünü referans alan bir sürüme güncellenmeli
- GitHub Security Lab, ileride GitHub Security Lab repository içinde kavram kanıtı istismar kodunu yayımlamayı planlıyor
Açıklama ve müdahale takvimi
- 2024-11-04: ruby-saml ile SAML kimlik doğrulamasını değerlendiren GitHub test ortamı için kimlik doğrulama atlatmasını kanıtlayan bug bounty raporu alındı
- 2024-11-04: Olası azaltma yöntemlerini belirleme ve test çalışmaları başladı
- 2024-11-12: İlk azaltma planını etkisiz kılan ikinci bir kimlik doğrulama atlatması bulundu
- 2024-11-13: ruby-saml maintainer'ı Sixto Martín ile ilk temas kuruldu
- 2024-11-14: İki ayrıştırıcı farkı ruby-saml'e bildirildi ve maintainer hemen yanıt verdi
- 2024-11-14: maintainer ile ahacker1 olası yama üzerinde çalışmaya başladı
- İlk fikirlerden biri XML ayrıştırıcılardan birini kaldırmaktı, ancak geriye dönük uyumluluğu bozmadan bu mümkün olmadı
- 2025-02-04: ahacker1, geriye dönük uyumluluğu olmayan bir düzeltme önerdi
- 2025-02-06: ahacker1, geriye dönük uyumlu bir düzeltme de önerdi
- 2025-02-12: GitHub Security Lab advisory için 90 günlük süre doldu
- 2025-02-16: maintainer, geriye dönük uyumluluğu koruyan ve anlaşılması kolay bir düzeltme yaklaşımı üzerinde çalışmaya başladı
- 2025-02-17: ruby-saml sürümü ile GitLab on-premises ürün sürümünü koordine etmek için GitLab ile ilk temas kuruldu
- 2025-03-12: Düzeltilmiş ruby-saml sürümü yayımlandı
1 yorum
Hacker News yorumları
GitHub’ın SAML implementasyonunun işe yaramaz olduğunu düşünüyorum.
Asıl amaç kişisel hesapları enterprise ortama getirip kullanmak; GitHub sitesinin içinde bir ölçüde çalışıyor ama GitHub ile giriş yapan bir uygulama organizasyon düzeyinde onaylandıktan sonra organizasyon üyeliklerini okumasını engellemiyor.
SAML oturumu yalnızca ilgili uygulama o kullanıcıdan aldığı token ile veri çekerken gerekli oluyor; pratikte ise SAST araçları neredeyse her zaman uygulama instance token’ı kullanıyor ve organizasyon içinde bir GitHub hesabı olduğu sürece kodu gösteriyordu.
Tailscale’e bildirince düzeltti; Sonarcloud kimseye söylemememi istedi; GitHub ise birkaç hafta sonra “tamamen beklenen davranış” diye yanıt verdi. Ama bildirdiğim hiçbir vendor bunu böyle anlamamıştı ve dokümantasyon da GitHub’ın yanıtıyla çelişiyordu.
Güvenlik bug’ı bildirmek, tesadüfen bulsanız bile tatmin edici olmayan bir iş; bunu meslek olarak yapmayı hayal etmek zor.
GitHub’ın, iş PR’larını merge ederken çok nadiren kişisel e-posta adresini varsayılan olarak kullandığı olmuştu; biri sorarsa, GitHub’da ya da başka yerde kişisel ve iş amaçlı kullanımı aynı hesapta karıştırmamasını öneririm.
Depo/commit/PR analiz aracı olan https://dev.log.xyz’yi geliştirirken “GitHub’da görülebilen şey Devlog’da da görülebilir” ilkesini tutturmak için çok uğraştık ve tüm deneyim çok bunaltıcıydı.
GitHub’ın OAuth izin seçicisi de gereğinden fazla kafa karıştırıcı; “GitHub ile giriş yap” sırasında hangi organizasyonun hangi bilgisinin paylaşıldığından emin olmak zor.
JavaScript’e aşina genç bir geliştiriciyi istemci tarafı doğrulamanın tek başına yeterli olmadığına ikna etmek bile zor; özellik gereksinimlerini ve bütçeyi belirleyen işletme sahiplerini ikna etmek daha da zor.
Herhangi bir tür parola kasası, hatta fiziksel bir kasa ya da parolaların yeniden kullanılması bile sonuçta daha güvenli hale gelebilir.
Sonuçta minimalizm yine kazanmış oluyor.
“GitHub doesn’t currently use ruby-saml for authentication, but began evaluating the use of the library with the intention of using an open source library for SAML authentication once more” deniyor.
Yakın zamanda SAML implementasyonu yapmak zorunda kaldım; bu başlık hiç şaşırtıcı gelmedi.
SAML spesifikasyonunun kendisi oldukça makul, ama dayandığı XML imzaları, hatta daha da ötesinde XML canonicalization, eğer buna standart denebilirse, gerçekten akıl almaz düzeyde.
Böyle çarpık ve bozulmuş bir spesifikasyonu ancak bir komite üretebilir; tek bir kişinin zihni bu kadar çelişkili fikirleri bir arada tutup birleştiremezdi gibi geliyor.
İmzayı sadece out-of-band iletmek bile SAML’yi implementasyonu keyifli bir şey haline getirirdi.
XML kelimenin tam anlamıyla eXtensible Markup Language iken, SAML standardizasyon komitesi bunun üstüne bir de kendilerine ait genişletme mekanizması dili icat etmiş.
Bir kimlik doğrulama çerezine girecek bilgiden pek de farklı olmayan küçücük bir veri için protokol üstüne protokol bindirmek, ancak en büyük ve en bürokratik komitelerin üretebileceği özel bir aptallık türü.
Farklı hesaplara ayrı ayrı giriş yapma fikrinin kendisi makul görünüyor.
Hesapları birbirine bağlayıp tek seferde büyük ölçekli ele geçirilmeye açık hale getiren yapı ise temelden daha riskli.
SAML, daha geniş anlamda XML-DSIG, yaygın kullanılan güvenlik protokolleri arasında kelimenin tam anlamıyla en kötüsü bence.
Genel olarak ne pahasına olursa olsun OAuth’a geçilmeli; en azından yeni bir ürünü piyasaya çıkarırken buna dayanmayı reddederdim.
Çok tehlikeli ve pratik biçim doğrulamada bir atılım olmadığı sürece bunun son DSIG açığı ya da en kötü açık olacağını hayal etmek zor.
Kriptografiye daha dokunmadan bile enterprise yazılım düşüncesinin zirvesi bu.
Birilerinin WS-* ve OASIS/XACML gibi şeylerin mailing list’lerini ve standardizasyon kurumlarındaki felaketi derinlemesine kazması gerekiyor.
Doğru mu?
Ugh, başka seçenek yoksa dışında kimse REXML kullanmamalı.
Hatalı XML’i bile seve seve parse ediyor ve sonraki aşamalarda sonsuz sayıda soruna yol açıyor.
Kelimenin tam anlamıyla XML’i düzenli ifadelerle parse ediyor; bunun neden yapılmaması gerektiğini gösteren harika bir örnek.
Projeler Nokogiri kullanmaya performans için değil, doğruluk için başladı.
Düzenli dil olmayan bir şeyi düzenli ifadelerle parse etmeyin.
Yakın zamanda o3’ü test ettim; belirli bir kod bloğundaki kütüphaneyle ilgisiz bir sorunu düzeltmeye çalıştığında, o bloğun kullandığı kütüphaneyi sürekli değiştiriyordu.
Sonnet’te böyle bir şey görmedim.
Bu şekilde düzeltme sürecinde, kod tabanında ya da standart kütüphanede zaten bulunduğu için testleri geçen ve Gemfile değişikliği de gerektirmeyen daha düşük nitelikli bir kütüphaneye/gem’e geçilerek sorunun içeri sızması kolay görünüyor.
SAML tasarımı gereği güvenli değil
Eskiden beri bunu daha iyi açıklayan yazılar var; örneğin https://joonas.fi/2021/08/saml-is-insecure-by-design/
Buradaki eski bir başlıktan aklımda kalan ifade “anlama değil, baytlara imza at” idi
Ayrıştırıcılar arasındaki farklar öngörülebilir ve bazen kaçınılmazdır
İmzalı yanıttan ne elde etmeye çalıştığınız çok önemlidir
Modern TLS’in ikilemlerinden biri şu: bazen tek bir dahili CA’ya güvenmek istersiniz ve bu kolay yoldur; ancak bir iş ortağının CA sertifikasını kabul ediyorsanız ve birden fazla iş ortağınız varsa, artık yalnızca uç sertifikaya bakamazsınız, zincirin kökü de karar verme sürecinde aynı derecede önemli hale gelir
Bu yüzden mümkünse AWS imza algoritmasından da kaçınmayı öneririm
V4 teoride güvenli, ancak AWS bunu iki kez berbat etti; SigV1 ve SigV3 tasarım gereği güvenli olmamasına rağmen her nasılsa tasarım incelemesinden geçip kamuya açıldı
Harika bir yazı
Yazıda da belirtildiği gibi, ahacker1 büyük bir alkışı hak ediyor
SAML uygulamalarını güvenli hale getirmek için çok incelikli ve değerli işler yapıyor; SSOReady de onun çalışmalarına gerçekten minnettar
Bu haftanın başında WorkOS da ahacker1 ile işbirliği hakkında güzel bir yazı yayımladı: https://workos.com/blog/samlstorm
“GitLab’da bu açığın istismar edilebilir bir örneğini bulduk ve güvenlik ekibine bildirdik” kısmı var; merak edenler için, GitLab düzeltmeyi zaten yayımladı
https://about.gitlab.com/releases/2025/03/12/patch-release-g...
İlgili bir yazı olarak Latacora’nın 2019 tarihli How (not) to sign a JSON object[1] yazısı var
Özetle, ağaç yapılarını iç içe geçirerek imzalamak zor ve tuzaklarla dolu bir iş
Zarfın mesajı ham bir dize olarak taşıması ve o ham dizenin imzalanması daha kolaydır
[1]: https://www.latacora.com/blog/2019/07/24/how-not-to/
Buradaki daha basit sonuç, imzanın olması gereken yerde imzayı aramak değil mi?
“//ds:Signature” gibi aşırı genel bir XPath kullanıp beklenmedik bir konumdaki herhangi bir imzayı bulmaya çalışmayın
Yalnızca tehlikeli bileşeni cerrahi biçimde çıkarmak değil; biraz da bebeği banyo suyuyla birlikte atmak, geniş çaplı kesip biçmek ve kemoterapi uygular gibi davranmak gerekir
Kendine saygısı olan bir BT yöneticisi, gelecek planlarından SAML’i çıkarmalı
SSO fikrinin tamamı da şüpheli; XML ayrıştırma haftada iki kez darbe yediğine göre bundan sonra kaçınılmalı
XML’i JSON ile değiştirme politikasında ne sorun var?
Tasarım, protokoller ve veri biçimleri düzeyinden başlayarak böyle olmalı
Genel web geliştirme alışkanlıkları ve tasarım kaygıları, güvenlik kodunun gerektirdikleriyle uyuşmaz; çoğu zaman doğru kod yazmak için gerekenlerin de tam tersidir
Blog yazısının açığı anlatırken asıl sorun olan ayrıştırıcı farkını atlaması biraz sinir bozucu
Hikâyenin girişini yazıp doruk noktasını atlamak gibi
(...//ds:DigestValue).firstChild.nodeValueyapılırken.firstChild’ın Node olup olmadığı kontrol edilmemiş; sorunlu durumda bu bir Comment idiBu yüzden normalleştirilmemiş taraf “gizlenmiş” imzayı gördü, yorumu atan düzeltilmiş taraf ise Node’u gördü; iki uygulama imzalı belge hakkında farklı hüküm verince tatsız şeyler oluyor
Somut ayrıntılar yakında ortaya çıkar herhalde