CVE-2025-25291 is a newly disclosed vulnerability affecting the popular ruby-saml library for Ruby, which enables developers to integrate SAML Single Sign-On (SSO) capabilities into their Ruby applications. This security issue affects versions of ruby-saml prior to 1.12.4 and 1.18. and opens the door to a serious authentication bypass through a parser differential exploit, specifically a *Signature Wrapping* attack. In this post, we’ll break down what this vulnerability is, how it works, and how attackers can exploit it—with a simple code snippet and original references.
What is ruby-saml?
Before going into the exploit, it’s helpful to know ruby-saml makes it easy for developers to support SAML 2. authentication workflows. It’s widely used in the Ruby world to enable secure SSO across enterprise and web applications.
How does CVE-2025-25291 work?
This vulnerability is caused by a subtle parser differential issue between two XML parsing libraries: REXML and Nokogiri. While ruby-saml supports both parsers, they interpret malformed or edge-case XML structures differently. This behavior can be abused by a SAML attacker to fool signature validation logic—a method known as a Signature Wrapping attack.
Signature Validation: SAML assertions are digitally signed to ensure they’re legit.
- XML Structure: An attacker can craft XML so that signature validation targets one element while authentication code reads data from another, unsigned element.
- Parser Differential: Slightly malformed or tricky XML will produce different DOM trees in REXML and Nokogiri. This can be exploited so that one parser sees what the attacker intends, while the other does not, bypassing authentication.
Step 1: Understand the Flow
When a SAML response is received, ruby-saml parses the XML and checks the signature on a <Assertion> element. The vulnerability occurs if the XML has *two* <Assertion> elements: one signed (benign) and one unsigned (malicious). Then, the parser differential lets you trick the program:
Look at this deliberately malformed SAML response
<Response>
<Assertion ID="good">
<!-- Legit, Signed Assertion -->
<Subject>
<NameID>victim@example.com</NameID>
</Subject>
<!-- Signature over this assertion -->
<ds:Signature>...</ds:Signature>
</Assertion>
<Assertion ID="evil">
<!-- Attacker’s assertion, no signature -->
<Subject>
<NameID>attacker@evil.com</NameID>
</Subject>
</Assertion>
</Response>
The attacker can generate an XML response accepted by Nokogiri but parsed differently by REXML, so that the signature is validated against the "good" assertion—while SSO logic authenticates the "evil" assertion.
A practical exploit with ruby-saml (prior to version 1.12.4 or 1.18.)
- Forge SAML XML: Craft a SAML response where the signed assertion looks legitimate, but the assertion with attacker’s credentials is not signed.
- Abuse Parser Differences: Use XML edge cases (namespace, special attributes, or even uncommon characters) so that Nokogiri and REXML choose different assertions as the "first" <Assertion>, letting the unsigned assertion slip through.
- Authenticate as Anyone: The app ends up authenticating the attacker as any user (for example, administrator) in the target system.
Proof of Concept (Simplified Ruby Script)
require 'ruby-saml'
settings = OneLogin::RubySaml::Settings.new
saml_response = File.read('malicious-saml-response.xml')
response = OneLogin::RubySaml::Response.new(saml_response, settings: settings)
puts response.name_id # This could return 'attacker@evil.com' if exploited
Official Fix
Upgrading ruby-saml to version 1.12.4 (for the 1.12.x branch) or 1.18. (for the 1.18.x branch) solves the issue. The maintainers patched the code to ensure:
Only the signed assertion is used during authentication.
- XML parsing and data extraction are now consistently performed on the same, verified content regardless of the parser.
Recommendations
- Upgrade Immediately: If you use ruby-saml, ensure you’re running 1.12.4/1.18. or later.
- Check Your Dependencies: Know which XML parser your app uses, and its interaction with your SAML library.
- Review SAML Response Handling: Only process data strictly from signed assertions; any deviation can be exploited.
References
- GHSA-pnmm-q5hw-gc73 (GitHub Advisory)
- ruby-saml Changelog
- Onelogin Security Advisory
- CWE-20: Improper Input Validation
- Signature Wrapping Attack Explanation
Conclusion
CVE-2025-25291 is a powerful example of how the complexity of XML and subtle differences between parsers can lead to dangerous authentication vulnerabilities—even in widely used security libraries. Don’t take SSO on faith: Validate your dependencies, upgrade promptly, and be aware of parser behaviors. If you’re running ruby-saml, patch right now!
*This write-up is exclusive: simple, clear, and focused on giving you the facts and the flows—and helping you defend your app today.*
Timeline
Published on: 03/12/2025 21:15:42 UTC
Last modified on: 03/20/2025 14:15:24 UTC