diff --git a/src/pentesting-web/saml-attacks/README.md b/src/pentesting-web/saml-attacks/README.md index 860d32b0632..8d99403dad8 100644 --- a/src/pentesting-web/saml-attacks/README.md +++ b/src/pentesting-web/saml-attacks/README.md @@ -56,12 +56,37 @@ For more information about the vulnerability and how to abuse it:[[1]](#ref - [https://mattermost.com/blog/securing-xml-implementations-across-the-web/](https://mattermost.com/blog/securing-xml-implementations-across-the-web/)[[1]](#references) - [https://joonas.fi/2021/08/saml-is-insecure-by-design/](https://joonas.fi/2021/08/saml-is-insecure-by-design/)[[2]](#references) +### Canonicalization-versus-application text differentials + +Do not assume that a valid digest authenticates the string later used for account lookup. Build a legitimately signed baseline, inject **processing instructions**, **comments**, split text nodes, CDATA and mixed content at every position in `NameID` and identity-bearing attributes, and compare these four outputs: the referenced node, its canonical bytes, the signature library's verified-node output and the final application string.[[16]](#references)[[17]](#references)[[22]](#references) + +For example, a vulnerable `xml-crypto` integration treated processing-instruction data as text while canonicalizing, but the application's XML accessor ignored it:[[16]](#references)[[22]](#references) + +```xml +admin@example.com +``` + +The signature layer therefore reconstructed the previously signed value `not-an-admin@example.com`, while authorization consumed `admin@example.com`. XML comments can create the inverse or a truncation differential when one layer joins text around the comment and another returns only one side; this becomes account takeover when the resulting value is used to link an external identity to an existing username or email.[[17]](#references)[[22]](#references) + +Useful mutations include:[[16]](#references)[[17]](#references)[[22]](#references) + +- Insert `` and `` before, inside and after every security-sensitive text value. +- Vary empty comments, adjacent comments, multiple text nodes, CDATA boundaries and whitespace. +- Test both the original DOM and any parse-serialize-parse path. +- Reject the result if verification and business logic do not consume the **same returned node and exact text representation**. + ## XML Signature Wrapping Attacks In **XML Signature Wrapping attacks (XSW)**, adversaries exploit a vulnerability arising when XML documents are processed through two distinct phases: **signature validation** and **function invocation**. These attacks involve altering the XML document structure. Specifically, the attacker **injects forged elements** that do not compromise the XML Signature's validity. This manipulation aims to create a discrepancy between the elements analyzed by the **application logic** and those checked by the **signature verification module**. As a result, while the XML Signature remains technically valid and passes verification, the application logic processes the **fraudulent elements**. Consequently, the attacker effectively bypasses the XML Signature's **integrity protection** and **origin authentication**, enabling the **injection of arbitrary content** without detection. The following attacks are based on [**this methodology**](https://epi052.gitlab.io/notes-to-self/blog/2019-03-13-how-to-test-saml-a-methodology-part-two/) and [**this paper**](https://www.usenix.org/system/files/conference/usenixsecurity12/sec12-final91.pdf). Consult them for further details.[[3]](#references)[[4]](#references) +### Verified-node binding and alternate protocol paths + +After signature verification, trace the object returned by the verifier into status validation, assertion selection and identity extraction. If application code reparses the document or runs an independent XPath/DOM search, mutate duplicate IDs, repeated `Response`/`Assertion` nodes, element order, unexpected nesting and signed objects of the wrong type until the verifier and business logic select different nodes. A robust implementation rejects ambiguity and only exposes the exact verified element to the caller.[[18]](#references)[[19]](#references)[[22]](#references) + +Exercise **success and error responses separately**. A genuinely signed error `Response` must not authorize an assertion discovered elsewhere in the document; require `StatusCode=Success` on the same verified response and bind the accepted assertion to that response before consuming `NameID` or attributes.[[18]](#references)[[22]](#references) + ### XSW #1 - **Strategy**: A new root element containing the signature is added. @@ -122,6 +147,10 @@ The following attacks are based on [**this methodology**](https://epi052.gitlab. You can use the Burp extension [**SAML Raider**](https://portswigger.net/bappstore/c61cfa893bb14db4b01775554f7b802e) to parse the request, apply any XSW attack you choose, and launch it. +### Test every signed SAML message handler + +Repeat verified-node and wrapping tests against `AuthnRequest`, `AttributeQuery` and `LogoutRequest`, not only login responses. A handler may validate a captured signed element nested inside an attacker-controlled outer request and then process the outer issuer, `NameID`, session index or query subject. Depending on the handler, this can disclose attributes or terminate another user's session.[[19]](#references)[[22]](#references) + ## Ruby-SAML signature verification bypass (CVE-2024-45409) **Impact**: If the Service Provider uses vulnerable Ruby-SAML (ex. GitLab SAML SSO), an attacker who can obtain **any IdP-signed SAMLResponse** can **forge a new assertion** and authenticate as arbitrary users.[[5]](#references) @@ -213,6 +242,32 @@ You can also use the Burp extension [**SAML Raider**](https://portswigger.net/ba The talk linked in the Tools section also demonstrates XSLT-oriented SAML testing. +### Pre-authentication XSLT transform bombs + +If the implementation forwards attacker-selected `ds:Transform` algorithms to `libxmlsec1`, an invalid or self-signed message can request XSLT during digest calculation. The following transform fragment recursively emits two branches per level, so depth `n` produces `2^n` leaf nodes; `n=27` attempts to create 134,217,728 nodes before signature rejection.[[20]](#references)[[22]](#references) + +```xml + + + + + + + + + + + + + +``` + +### Scaling tests for XML-signature DoS + +Record peak RSS, CPU and latency while independently increasing request size, XML depth, `SignedInfo` depth, node count, references and transform recursion. Superlinear growth is exploitable because parsing and reference transforms happen before authentication. One canonicalization flaw deep-copied a subtree at each nested node, producing `O(depth^2)` allocation; an approximately 60 KB invalid SAML request could drive the process to multiple gigabytes of heap.[[21]](#references)[[22]](#references) + +Defensive controls should reject XSLT and allowlist the required canonicalization, digest and transform algorithms; limit HTTP body size, XML depth/nodes and reference count; and enforce worker CPU, memory and execution-time limits. Apply limits before or inside canonicalization rather than only after signature verification.[[20]](#references)[[21]](#references)[[22]](#references) + ## XML Signature Exclusion **XML Signature Exclusion** tests how a SAML implementation behaves when the `Signature` element is absent. A vulnerable service may skip signature validation and accept altered assertion content.[[8]](#references) @@ -497,5 +552,12 @@ The same parser weakness that gives an overread can also crash the SAML processi - [13] [Pwn2Own Ireland 2025: Bypassing Authentication via Synology DS925+ SAML SSO](https://chanzep.github.io/posts/pwn2own-ireland-2025-bypassing-authentication-via-synology-ds925-saml-sso) - [14] [How to test SAML: a methodology (part one)](https://epi052.gitlab.io/notes-to-self/blog/2019-03-07-how-to-test-saml-a-methodology/) - [15] [youtube.com - Watch](https://www.youtube.com/watch?v=WHn-6xHL7mI) +- [16] [OneUptime issue #2988 - XML processing instruction can modify SAML NameID](https://github.com/OneUptime/oneuptime/issues/2988) +- [17] [authentik advisory - Account Takeover via SAML NameID Comment Truncation](https://github.com/goauthentik/authentik/security/advisories/GHSA-35v6-hv2g-6992) +- [18] [OneUptime issue #2981 - SAML signature bypass via signed error response](https://github.com/OneUptime/oneuptime/issues/2981) +- [19] [samlify issue #634 - Signature wrapping bypass for LogoutRequest and AuthnRequest](https://github.com/tngan/samlify/issues/634) +- [20] [python3-saml issue #447 - DoS via XSLT transform](https://github.com/SAML-Toolkits/python3-saml/issues/447) +- [21] [goxmldsig advisory - Quadratic memory amplification in SignedInfo canonicalization](https://github.com/russellhaering/goxmldsig/security/advisories/GHSA-qhrp-hfff-vphr) +- [22] [Hacking SAML with Claude Code](https://oblique.security/blog/hacking-saml/) {{#include ../../banners/hacktricks-training.md}}