1 poin oleh GN⁺ 2025-03-16 | 1 komentar | Bagikan ke WhatsApp
  • 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 Signature yang berbeda dari dokumen XML yang sama
  • Saat SignedInfo, SignatureValue, hash assertion, dan DigestValue digabungkan 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-saml juga 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_signature di xml_security.rb
  • Metode ini membaca elemen Signature pertama dan SignatureValue aktual dengan REXML
    • REXML::XPath.first(@working_copy, "//ds:Signature", {"ds"=>DSIG})
  • Sebaliknya, dalam alur verifikasi yang sama, Signature dan SignedInfo diambil ulang dan dikanonicalisasi dengan Nokogiri
    • document.at_xpath('//ds:Signature', 'ds' => DSIG)
    • noko_signed_info_element.canonicalize(canon_algorithm)
  • Assertion diekstrak, dikanonicalisasi, dan di-hash dengan Nokogiri, tetapi DigestValue yang 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 DigestValue yang dibaca REXML
    • SignedInfo diekstrak dan dikanonicalisasi dengan Nokogiri
    • SignatureValue diekstrak 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 Subject dan NameID di dalam Assertion
  • Secara umum, yang dapat ditandatangani adalah assertion atau seluruh SAML response
  • Jika assertion yang ditandatangani, verifikasi berlangsung dalam dua tahap
    • assertion tanpa Signature dikanonicalisasi dan di-hash lalu dibandingkan dengan DigestValue
    • SignedInfo dikanonicalisasi lalu tanda tangannya diverifikasi dengan SignatureValue
  • 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 SignedInfo yang 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 Signature yang 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
  • GitHub Security Lab membuat eksploit berbasis perbedaan parser lain menggunakan fuzzer Ruby dari Trail of Bits, ruzzy
  • Eksploit contoh menyisipkan Signature tambahan di dalam elemen StatusDetail yang hanya terlihat oleh Nokogiri
  • Alur verifikasinya terpecah sebagai berikut
    • SignedInfo dari signature yang dilihat Nokogiri dikanonicalisasi
    • diverifikasi menggunakan SignatureValue yang diekstrak dari signature yang dilihat REXML
    • assertion yang ditemukan Nokogiri berdasarkan ID dikanonicalisasi dan di-hash
    • hash tersebut dibandingkan dengan DigestValue yang dibaca REXML
  • Akibatnya, SignedInfo yang 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 errors pada dokumen hasil parsing harus diperiksa secara langsung
  • Kode contoh menggunakan opsi Nokogiri::XML::ParseOptions::STRICT | Nokogiri::XML::ParseOptions::NONET, lalu menimbulkan error saat doc.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

 
GN⁺ 2025-03-16
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

    • Pendekatan “membawa akun pribadi ke enterprise” juga menimbulkan masalah di luar otorisasi
      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
    • Dari sisi vendor, sampai batas tertentu bisa dimengerti, karena GitHub membuat implementasi yang benar di sini menjadi sangat sulit
      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”
    • Pola operasi seperti ini berulang di semua lapisan
      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
    • Premis bahwa kemudahan dari kredensial bersama dan SSO dapat meningkatkan keamanan runtuh hanya karena satu kerentanan seperti ini
      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
    • Bagi yang mencoba menghubungkan hal di atas dengan riset kerentanan ini, tampaknya ini tidak terkait
      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

    • Kenyataannya jauh lebih buruk daripada yang disebutkan
      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
    • Saya tidak tahu apakah SSO sejak awal memang masih bisa diselamatkan
      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

    • Suatu saat saya akan menulis semua hal luar biasa bodoh yang dilakukan XML DSig
      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
    • Sepertinya akan menarik melihat bagaimana Security Cryptography Whatever membahas kekacauan SAML minggu ini
    • Kalau pemahaman saya benar, SAML masih punya pembeda bahwa penyedia SSO bisa membatalkan sesi
      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

    • Bukankah ini contoh textbook?
      Jangan mem-parse sesuatu yang bukan bahasa reguler dengan ekspresi reguler
    • Salah satu risiko asisten kode AI adalah ia tidak selalu melihat konteks yang lebih luas dari library yang digunakan dalam codebase besar
      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

    • Respons terhadap kerentanan biasanya terasa terlalu longgar
      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?
    • Kalau mau sedikit ekstrem, kesimpulannya adalah kita perlu membawa pentungan besar dan memastikan para pengembang web tidak menyentuh area dekat kode yang sensitif keamanan
      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

    • Tulisan blog di komentar saudara <https://news.ycombinator.com/item?id=43374972> memuat detail terkait
      Saat melakukan (...//ds:DigestValue).firstChild.nodeValue, mereka tidak memeriksa apakah .firstChild adalah Node, dan dalam kasus bermasalah itu adalah Comment
      Jadi 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
    • Sepertinya mereka tidak ingin bertanggung jawab karena mempublikasikan langsung zero-day yang memungkinkan bypass otorisasi di banyak sekali sistem di seluruh dunia sebelum penanggung jawab sistem-sistem tersebut sempat memperbaikinya
      Detail konkretnya mungkin akan segera muncul