Full Report
SAML is a common protocol for exchanging authentication and authorization data between IdPs and Service Providers (SPs). SAML is written in the markup language XML. In SAML, the core element is the Assertion. This holds information about user details in most cases. To ensure it hasn't been tampered, the assertion is hashed then verified with a digital signature. The Signature value is passed inside the SignatureValue element. The hashed data is in the SignedInfo block. This contains a DigestValue and a Reference URI pointing to the assertion. To verify the signature a service provider receives the SAML response then performs two checks: digest verification and signature verification. The digest verification calculates that the Assertion data hashed matches the DigestValue in the SignedInfo block to prevent tampering. Next, it validates the digital signature over the top of the hash. The Ruby-SAML library has several validations before the signature validation. In XPATH, used for finding elements in an XML document, / will select the root of the document and // will select any node from the document that it can find. Finally, on to the vulnerability! When getting the DigestValue via XPATH, the query was //ds:DigestValue. This will find the first instance of the DigestValue in the document! This allows an attacker to smuggle in the value into the document. Finally, on to the vulnerability! When getting the DigestValue via XPATH, the query was //ds:DigestValue. This will find the first instance of the DigestValue in the document! This allows an attacker to smuggle in the value into the document. This is bad! In the SAML validation, we can bypass the verification with the following flow: Insert a DigestValue into an unsigned element with a modified Assertion block. XPATH will extract the smuggled value instead of the one from the SignedInfo block. This bypasses the first step above of checking that the DigestValue is correct. Signature verification occurs on the DigestValue from the SignedInfo block. From previous verification, it was assumed that the actual hash and the one in this block must match. The author includes an XML document that is super interesting to look at from a security perspective. An awesome find in a technology that I'm not super familiar with but enjoyable none-the-less.
Analysis Summary
# Vulnerability: Ruby-SAML / GitLab Authentication Bypass
## CVE Details
- **CVE ID:** CVE-2024-45409
- **CVSS Score:** 10.0 (Critical)
- **CWE:** CWE-347: Improper Verification of Cryptographic Signature
## Affected Systems
- **Products:**
- Ruby-SAML (library)
- OmniAuth-SAML (library)
- GitLab (Community Edition/Enterprise Edition)
- **Versions:**
- Ruby-SAML: <= 1.15.0
- OmniAuth-SAML: <= 1.2.1
- GitLab: Multiple versions including 17.3.3, 17.2.7, 17.1.8, 17.0.8, and 16.11.10.
- **Configurations:** Systems utilizing SAML for authentication where the Service Provider (SP) relies on these libraries for processing SAML assertions.
## Vulnerability Description
The vulnerability exists due to an incorrect XPath implementation during the SAML message verification process. Specifically, the library used the XPath expression `//ds:DigestValue` to fetch the message digest.
In XPath, the `//` shorthand searches the entire document for the first instance of a node. An attacker can "smuggle" a malicious, unsigned element containing a forged `DigestValue` earlier in the XML document than the legitimate `SignedInfo` block. The library extracts this smuggled value and compares it against a modified (malicious) assertion. Because the library assumes the extracted digest is the one protected by the digital signature, it validates the tampered assertion as legitimate, effectively bypassing the integrity and authenticity checks.
## Exploitation
- **Status:** PoC available (Nuclei template released).
- **Complexity:** Low to Medium (requires ability to capture and modify a SAMLResponse).
- **Attack Vector:** Network.
## Impact
- **Confidentiality:** High (Full account takeover).
- **Integrity:** High (Ability to impersonate any user).
- **Availability:** High (Potential for administrative access and system disruption).
## Remediation
### Patches
- **Ruby-SAML:** Upgrade to version **1.16.0** or later.
- **OmniAuth-SAML:** Upgrade to version **2.2.1** or later.
- **GitLab:** Upgrade to versions **17.3.3, 17.2.7, 17.1.8, 17.0.8, 16.11.10** or later.
### Workarounds
- There are no reliable software workarounds other than upgrading the affected libraries. Disabling SAML authentication or enforcing mandatory Multi-Factor Authentication (MFA) through a non-SAML provider may mitigate risk until patching.
## Detection
- **Indicators of Compromise:** Unusual XML structures in SAML responses, specifically messages containing multiple `<ds:DigestValue>` elements or unexpected unsigned elements.
- **Detection methods and tools:**
- **Nuclei:** Use the template `CVE-2024-45409.yaml` to test for vulnerability.
- **Log Analysis:** Audit GitLab or application logs for successful SAML logins originating from unexpected IP addresses or anomalous user behavior.
## References
- **Vendor Advisory:** [https://github.com/SAML-Toolkits/ruby-saml/security/advisories/GHSA-jw9c-mfg7-9rx2]
- **GitLab Security Release:** [https://about.gitlab.com/releases/2024/09/17/patch-release-gitlab-17-3-3-released/]
- **ProjectDiscovery Analysis:** [https://projectdiscovery.io/blog/ruby-saml-gitlab-auth-bypass]