- CVE-2025-25291 dan CVE-2025-25292 yang ditemukan pada ruby-saml 1.17.0 dan sebelumnya meningkatkan risiko pengambilalihan akun di lingkungan SAML SSO karena memungkinkan login sebagai pengguna arbitrer hanya dengan satu tanda tangan yang valid
- Kerentanan ini berasal dari perbedaan parser pada jalur verifikasi tanda tangan, di mana REXML dan Nokogiri dapat menafsirkan elemen
Signatureyang berbeda dari dokumen XML yang sama - Saat
SignedInfo,SignatureValue, hash assertion, danDigestValuedigabungkan dari hasil parser yang berbeda, setiap pemeriksaan bisa lolos tetapi keterkaitan antara hash dan tanda tangan dapat terputus - GitHub melakukan bug bounty dan peninjauan Security Lab saat meninjau kemungkinan penggunaan kembali ruby-saml, menemukan instance yang bisa dieksploitasi di GitLab dan memberi tahu tim keamanannya, dan saat ini tidak menggunakan ruby-saml untuk autentikasi GitHub
- Pengguna harus memperbarui ke ruby-saml 1.18.0, dan library yang merujuk ke ruby-saml seperti
omniauth-samljuga harus dinaikkan ke rilis yang merujuk versi yang sudah diperbaiki
Dampak bypass autentikasi ruby-saml
- Dua kerentanan bypass autentikasi dengan tingkat keparahan tinggi telah dikonfirmasi pada ruby-saml 1.17.0 dan sebelumnya
- CVE-2025-25291
- CVE-2025-25292
- Penyerang dapat membuat SAML assertion sendiri dan login sebagai pengguna arbitrer jika memiliki satu tanda tangan valid yang dibuat dengan kunci yang digunakan untuk memverifikasi SAML response atau assertion milik organisasi target
- Sumber tanda tangan yang mungkin antara lain:
- assertion atau response bertanda tangan milik pengguna lain dengan hak rendah
- dalam beberapa kasus, metadata bertanda tangan dari SAML IdP yang dapat diakses publik
- Kerentanan ini pada akhirnya dapat digunakan untuk serangan pengambilalihan akun
- GitHub saat ini tidak menggunakan ruby-saml untuk autentikasi, tetapi mengevaluasi ruby-saml saat meninjau opsi untuk kembali memakai library open source untuk autentikasi SAML
- ruby-saml juga digunakan di proyek dan produk populer lain, dan GitHub menemukan instance yang dapat dieksploitasi di GitLab lalu memberi tahu tim keamanan GitLab
Mengapa GitHub meninjau ruby-saml lagi
- GitHub menggunakan ruby-saml hingga 2014, tetapi saat itu fitur yang dibutuhkan belum memadai sehingga beralih ke implementasi SAML internal
- Setelah itu, implementasi internalnya sendiri juga menerima laporan bug bounty seperti CVE-2024-9487, yaitu kerentanan terkait assertion terenkripsi, dan GitHub mulai meninjau kemungkinan memperkenalkan kembali ruby-saml
- Pada Oktober 2024, kerentanan bypass autentikasi ruby-saml CVE-2024-45409 yang ditemukan oleh ahacker1 dipublikasikan
- GitHub memulai bug bounty privat untuk mengevaluasi lebih cermat kemungkinan migrasi ke ruby-saml
- Para peneliti terpilih diberi akses ke lingkungan uji GitHub yang melakukan autentikasi SAML dengan ruby-saml
- GitHub Security Lab juga meninjau attack surface ruby-saml secara bersamaan
Ketidaksesuaian verifikasi yang dibuat dua parser XML
- Saat meninjau kode, ahacker1 dan GitHub Security Lab mengonfirmasi bahwa dua parser XML digunakan bersama pada jalur verifikasi tanda tangan ruby-saml
- REXML: parser XML yang diimplementasikan murni dalam Ruby
- Nokogiri: menyediakan API yang membungkus libxml2, libgumbo, Xerces untuk JRuby, dan lainnya, serta mendukung parsing XML dan HTML
- Jalur yang bermasalah adalah metode
validate_signaturedixml_security.rb - Metode ini membaca elemen
Signaturepertama danSignatureValueaktual dengan REXMLREXML::XPath.first(@working_copy, "//ds:Signature", {"ds"=>DSIG})
- Sebaliknya, dalam alur verifikasi yang sama,
SignaturedanSignedInfodiambil ulang dan dikanonicalisasi dengan Nokogiridocument.at_xpath('//ds:Signature', 'ds' => DSIG)noko_signed_info_element.canonicalize(canon_algorithm)
- Assertion diekstrak, dikanonicalisasi, dan di-hash dengan Nokogiri, tetapi
DigestValueyang dijadikan pembanding berasal dari REXML - Pada akhirnya, bahan verifikasi terpecah seperti berikut
- assertion diekstrak dan dikanonicalisasi dengan Nokogiri lalu di-hash
- hash pembanding berasal dari
DigestValueyang dibaca REXML SignedInfodiekstrak dan dikanonicalisasi dengan NokogiriSignatureValuediekstrak dengan REXML
Keterkaitan keamanan yang terputus dalam verifikasi tanda tangan SAML
- SAML response mengirimkan informasi pengguna yang login dari IdP ke SP dalam format XML
- Saat menggunakan HTTP POST binding, SAML response berpindah ke SP melalui browser pengguna, sehingga verifikasi tanda tangan diperlukan agar pengguna tidak bisa memodifikasi pesan
- Dalam SAML response yang disederhanakan, informasi penting biasanya berada di
SubjectdanNameIDdi dalamAssertion - Secara umum, yang dapat ditandatangani adalah assertion atau seluruh SAML response
- Jika assertion yang ditandatangani, verifikasi berlangsung dalam dua tahap
- assertion tanpa
Signaturedikanonicalisasi dan di-hash lalu dibandingkan denganDigestValue SignedInfodikanonicalisasi lalu tanda tangannya diverifikasi denganSignatureValue
- assertion tanpa
- Pada kerentanan ini, meskipun kedua tahap tersebut sama-sama lolos, tidak ada jaminan bahwa keduanya merujuk ke data yang sama
- hash bisa jadi merupakan hash dari assertion yang sebenarnya
- tanda tangan bisa jadi merupakan tanda tangan atas elemen
SignedInfoyang berbeda
- Sifat keamanan yang dibutuhkan adalah keterkaitan langsung antara konten yang di-hash, hash, dan tanda tangan, dan setelah verifikasi, informasi hanya boleh dibaca dari bagian yang benar-benar telah diverifikasi
Cara konstruksi eksploit nyata
- Syarat utamanya adalah membuat REXML dan Nokogiri melihat
Signatureyang berbeda dalam dokumen XML yang sama, dan hal itu memang memungkinkan - Selama berpartisipasi dalam bug bounty, ahacker1 lebih dulu membuat eksploit yang berfungsi dengan memanfaatkan perbedaan parser
- Terinspirasi dari XML roundtrips vulnerabilities yang dipublikasikan Juho Forsén dari Mattermost pada 2021
- GitHub Security Lab membuat eksploit berbasis perbedaan parser lain menggunakan fuzzer Ruby dari Trail of Bits, ruzzy
- Eksploit contoh menyisipkan
Signaturetambahan di dalam elemenStatusDetailyang hanya terlihat oleh Nokogiri - Alur verifikasinya terpecah sebagai berikut
SignedInfodari signature yang dilihat Nokogiri dikanonicalisasi- diverifikasi menggunakan
SignatureValueyang diekstrak dari signature yang dilihat REXML - assertion yang ditemukan Nokogiri berdasarkan ID dikanonicalisasi dan di-hash
- hash tersebut dibandingkan dengan
DigestValueyang dibaca REXML
- Akibatnya,
SignedInfoyang valid dan tanda tangan yang valid saling cocok, dan assertion yang telah dimanipulasi beserta digest yang dihitung darinya juga saling cocok, sehingga ruby-saml menerima assertion tersebut
Mitigasi dan keterbatasan deteksi
- Saat mem-parse SAML response dengan Nokogiri, memeriksa kesalahan parsing dapat mencegah sebagian eksploit privat yang saat ini diketahui
- Kesalahan parsing Nokogiri tidak muncul sebagai exception, sehingga anggota
errorspada dokumen hasil parsing harus diperiksa secara langsung - Kode contoh menggunakan opsi
Nokogiri::XML::ParseOptions::STRICT | Nokogiri::XML::ParseOptions::NONET, lalu menimbulkan error saatdoc.errors.any? - Pendekatan ini bukan perbaikan penuh, tetapi setidaknya membuat satu eksploit tidak dapat dijalankan
- Belum ada indikator kompromi yang tepercaya
- satu indikator potensial hanya berfungsi di lingkungan mirip debug
- indikator itu tidak dipublikasikan karena akan mengungkap terlalu banyak detail implementasi eksploit yang berfungsi
- Metode pemeriksaan yang direkomendasikan adalah mencari login mencurigakan seperti login SAML dari alamat IP yang tidak sesuai dengan lokasi yang diharapkan dari sisi SP
Arah perbaikan dan target pembaruan
- Perbaikan awal tidak menghapus salah satu parser XML karena masalah kompatibilitas API
- Masalah yang lebih mendasar adalah pemisahan antara verifikasi hash dan verifikasi tanda tangan, dan pemisahan ini menjadi dapat dieksploitasi melalui perbedaan parser
- Penghapusan salah satu parser XML sebenarnya sudah direncanakan karena alasan lain, dan bersama perbaikan tambahan kemungkinan akan dilakukan dalam rilis mayor
- Pengguna ruby-saml harus memperbarui ke 1.18.0 yang berisi perbaikan
- Library yang menggunakan ruby-saml juga harus diperiksa
- contoh: omniauth-saml
- library tersebut harus diperbarui ke versi yang merujuk ke versi ruby-saml yang sudah diperbaiki
- GitHub Security Lab berencana memublikasikan exploit proof-of-concept di repositori GitHub Security Lab di masa mendatang
Jadwal pengungkapan dan respons
- 2024-11-04: laporan bug bounty yang membuktikan bypass autentikasi diterima untuk lingkungan uji GitHub yang sedang mengevaluasi autentikasi SAML dengan ruby-saml
- 2024-11-04: pekerjaan untuk mengidentifikasi dan menguji mitigasi potensial dimulai
- 2024-11-12: bypass autentikasi kedua ditemukan yang meniadakan rencana mitigasi pertama
- 2024-11-13: kontak awal dilakukan dengan maintainer ruby-saml, Sixto Martín
- 2024-11-14: perbedaan dua parser dilaporkan ke ruby-saml dan maintainer segera merespons
- 2024-11-14: maintainer dan ahacker1 mulai mengerjakan patch potensial
- salah satu ide awal adalah menghapus salah satu parser XML, tetapi hal itu tidak memungkinkan tanpa merusak kompatibilitas mundur
- 2025-02-04: ahacker1 mengusulkan perbaikan yang tidak kompatibel ke belakang
- 2025-02-06: ahacker1 juga mengusulkan perbaikan yang kompatibel ke belakang
- 2025-02-12: tenggat 90 hari advisory GitHub Security Lab berakhir
- 2025-02-16: maintainer mulai mengerjakan arah perbaikan yang tetap menjaga kompatibilitas mundur dan mudah dipahami
- 2025-02-17: kontak awal dilakukan dengan GitLab untuk mengoordinasikan rilis ruby-saml dan rilis produk GitLab on-premises
- 2025-03-12: versi ruby-saml yang telah diperbaiki dirilis
1 komentar
Pendapat di Hacker News
Menurut saya implementasi SAML GitHub tidak berguna
Niat awalnya adalah membawa akun pribadi ke lingkungan enterprise untuk digunakan, dan di dalam situs GitHub itu cukup berfungsi, tetapi setelah aplikasi yang login lewat GitHub disetujui di tingkat organisasi, tidak ada yang mencegah aplikasi itu membaca keanggotaan organisasi
Sesi SAML hanya diperlukan saat aplikasi tersebut mengambil data dengan token yang diterimanya dari pengguna itu, dan dalam praktiknya alat-alat SAST hampir selalu memakai token instans aplikasi, sehingga cukup punya akun GitHub di dalam organisasi untuk bisa menampilkan kode
Tailscale memperbaikinya setelah diberi tahu, Sonarcloud meminta agar jangan memberi tahu siapa pun, dan GitHub beberapa minggu kemudian menjawab bahwa itu “perilaku yang sepenuhnya diharapkan”, tetapi tidak ada vendor yang diberi tahu memahaminya seperti itu dan dokumentasinya juga bertentangan dengan jawaban GitHub
Melaporkan bug keamanan, bahkan ketika menemukannya secara kebetulan, tidak terasa memuaskan, dan sulit membayangkan menjadikan ini sebagai pekerjaan
GitHub pernah sangat sesekali menggunakan alamat email pribadi sebagai default saat merge PR pekerjaan, jadi kalau ada yang bertanya, saya akan menyarankan agar tidak mencampur penggunaan pribadi dan pekerjaan dalam akun yang sama, baik di GitHub maupun di tempat lain
Saat membuat https://dev.log.xyz, alat analisis repositori/commit/PR, butuh upaya besar untuk memastikan “apa yang bisa dilihat di GitHub juga bisa dilihat di Devlog”, dan seluruh pengalamannya sangat membuat frustrasi
Pemilih izin OAuth GitHub juga terlalu membingungkan, sehingga sulit yakin informasi apa dari organisasi mana yang dibagikan saat “login dengan GitHub”
Meyakinkan developer muda yang terbiasa dengan JavaScript bahwa validasi sisi klien saja tidak cukup juga sulit, apalagi meyakinkan pelaku bisnis yang menentukan kebutuhan fitur dan anggaran
Bentuk penyimpanan kata sandi apa pun, bahkan penyimpanan fisik atau penggunaan ulang kata sandi sekalipun, pada akhirnya bisa jadi lebih aman
Pada akhirnya minimalisme menang lagi
Tertulis “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”
Baru-baru ini saya harus mengimplementasikan SAML, dan judul ini sama sekali tidak mengejutkan
Spesifikasi SAML sendiri cukup masuk akal, tetapi fondasinya, yaitu tanda tangan XML, dan lebih jauh lagi kanonisasi XML, benar-benar gila jika itu bisa disebut standar
Spesifikasi yang bengkok dan rusak seperti ini hanya bisa dibuat oleh komite; rasanya tidak mungkin satu orang mampu memegang dan menggabungkan gagasan-gagasan yang begitu kontradiktif di kepalanya
Kalau saja tanda tangannya dikirim out-of-band, SAML akan menjadi sesuatu yang menyenangkan untuk diimplementasikan
XML secara harfiah adalah eXtensible Markup Language, tetapi komite standardisasi SAML menciptakan lagi bahasa mekanisme ekstensi mereka sendiri di atasnya
Menumpuk protokol di atas protokol demi data yang sangat kecil dan tidak jauh berbeda dari informasi yang masuk ke cookie autentikasi adalah jenis kebodohan khusus yang hanya bisa dihasilkan oleh komite paling besar dan birokratis
Gagasan untuk login secara terpisah ke akun yang berbeda-beda tampaknya baik-baik saja
Struktur yang menghubungkan akun-akun satu sama lain sehingga semuanya bisa dibobol secara massal sekaligus pada dasarnya lebih berbahaya
SAML, dan secara lebih luas XML-DSIG, menurut saya secara harfiah adalah protokol keamanan terburuk yang banyak digunakan
Secara umum, orang harus beralih ke OAuth apa pun biayanya, dan setidaknya saya akan menolak meluncurkan produk baru ke pasar yang bergantung pada ini
Ini sangat berbahaya, dan kecuali ada terobosan dalam verifikasi format yang praktis, sulit membayangkan ini akan menjadi kerentanan DSIG terakhir atau yang terburuk
Bahkan tanpa menyentuh kriptografi, ini sudah merupakan puncak cara berpikir perangkat lunak enterprise
Seseorang perlu menggali dalam-dalam kekacauan mailing list dan badan standardisasi untuk hal-hal seperti WS-* dan OASIS/XACML
Benarkah begitu?
Ugh, kecuali tidak ada pilihan lain, tidak ada yang seharusnya memakai REXML
Ia dengan senang hati mem-parse XML yang tidak valid, sehingga menimbulkan tak terbatas masalah pada tahap berikutnya
Secara harfiah ia mem-parse XML dengan ekspresi reguler, dan ini contoh bagus yang menunjukkan kenapa itu tidak boleh dilakukan
Proyek-proyek mulai memakai Nokogiri bukan karena performa, melainkan karena kebenaran
Jangan mem-parse sesuatu yang bukan bahasa reguler dengan ekspresi reguler
Baru-baru ini saya menguji o3, dan setiap kali mencoba memperbaiki masalah yang tidak terkait dengan library pada blok kode tertentu, ia terus mengganti library yang dipakai blok itu
Saya tidak melihat gejala seperti itu pada Sonnet
Tampaknya masalah mudah menyusup ketika dalam proses perbaikan, kode diubah ke library/gem yang lebih inferior tetapi sudah ada di codebase atau standard library sehingga tes tetap lolos dan perubahan Gemfile juga tidak diperlukan
SAML secara desain tidak aman
Sejak dulu sudah ada tulisan-tulisan yang menjelaskannya dengan lebih baik, misalnya https://joonas.fi/2021/08/saml-is-insecure-by-design/
Kalimat yang paling saya ingat dari utas lama ini adalah “tandatangani byte, bukan makna”
Perbedaan antar-parser dapat diprediksi dan kadang tidak terhindarkan
Apa yang ingin Anda dapatkan dari respons yang ditandatangani itu sangat penting
Salah satu dilema TLS modern adalah kadang kita ingin memercayai satu CA internal, dan itu adalah jalur yang mudah, tetapi jika kita menerima sertifikat CA milik partner, dan partner-nya ada banyak, kita tidak bisa lagi hanya melihat sertifikat akhir; root dalam chain juga menjadi sama pentingnya dalam pengambilan keputusan
Karena itu, jika memungkinkan, saya juga menyarankan untuk menghindari algoritma tanda tangan AWS
V4 secara teori aman, tetapi AWS sudah dua kali gagal, dan SigV1 serta SigV3 tidak aman secara desain, namun entah bagaimana tetap lolos tinjauan desain dan dirilis ke publik
Tulisan yang sangat bagus
Seperti juga disebutkan di tulisan itu, ahacker1 patut mendapat tepuk tangan besar
Ia melakukan pekerjaan yang sangat canggih dan bernilai untuk membuat implementasi SAML menjadi aman, dan SSOReady juga sangat berterima kasih atas pekerjaannya
Awal pekan ini WorkOS juga menerbitkan tulisan bagus tentang kolaborasinya dengan ahacker1: https://workos.com/blog/samlstorm
Ada bagian yang berbunyi “kami menemukan kasus yang dapat dieksploitasi untuk kerentanan ini di GitLab dan memberitahu tim keamanannya”; bagi yang penasaran, GitLab sudah merilis perbaikan
https://about.gitlab.com/releases/2025/03/12/patch-release-g...
Sebagai tulisan terkait, ada artikel Latacora tahun 2019, How (not) to sign a JSON object[1]
Ringkasnya, menandatangani struktur pohon secara bertingkat itu sulit dan penuh jebakan
Lebih mudah jika envelope memuat pesan sebagai string mentah, lalu menandatangani string mentah tersebut
[1]: https://www.latacora.com/blog/2019/07/24/how-not-to/
Bukankah kesimpulan yang lebih sederhana di sini adalah mencari tanda tangan di lokasi yang memang seharusnya ada tanda tangan?
Jangan memakai XPath yang terlalu umum seperti “//ds:Signature” sehingga malah menemukan tanda tangan apa pun di lokasi yang tidak terduga
Bukan hanya mengangkat komponen berbahaya secara bedah; kita juga harus sedikit ikut membuang bayinya bersama air mandinya, memangkas besar-besaran, dan menanganinya seperti kemoterapi
Admin IT yang punya harga diri seharusnya mengecualikan SAML dari rencana ke depan
Gagasan SSO secara keseluruhan juga patut dicurigai, dan karena parsing XML sudah kena dua kali dalam seminggu, sebaiknya dihindari ke depannya
Apa masalahnya dengan kebijakan mengganti XML dengan JSON?
Itu harus berlaku sejak desain, protokol, hingga format data
Kebiasaan dan pertimbangan desain dalam pengembangan web umum tidak cocok dengan yang dibutuhkan untuk kode keamanan, dan sering kali bahkan berlawanan dengan yang diperlukan untuk menulis kode yang benar
Agak menjengkelkan bahwa tulisan blog itu menjelaskan kerentanannya tetapi justru melewatkan perbedaan parser yang menjadi masalah
Rasanya seperti menulis pembuka cerita lalu menghilangkan klimaksnya
Saat melakukan
(...//ds:DigestValue).firstChild.nodeValue, mereka tidak memeriksa apakah.firstChildadalah Node, dan dalam kasus bermasalah itu adalah CommentJadi sisi yang tidak dinormalisasi melihat tanda tangan yang “tersembunyi”, sedangkan sisi yang sudah diperbaiki dengan membuang komentar melihat Node, dan ketika dua implementasi menilai dokumen bertanda tangan secara berbeda, hal yang tidak lucu pun terjadi
Detail konkretnya mungkin akan segera muncul