Статья Атаки на SAML аутентификацию: XML Signature Wrapping, Golden SAML и обход федеративного SSO

Разобранная материнская плата на чёрном мате рядом с монитором, отображающим XML с выделенным красным узлом SAML. Холодный криминалистический свет, десатурированная палитра.


На одном из последних red team-проектов мы перехватили SAMLResponse в Burp, переместили подписанный Assertion в другую ветку DOM-дерева, вставили поддельный с NameID=admin@company.local на его место - и SP пустил нас как доменного администратора.
SAMLResponse - это XML-сообщение с цифровой подписью, отправляемое поставщиком идентификационных данных (IdP) поставщику услуг (SP) во время входа в систему с использованием единого входа (SSO).

Подписанный Assertion - это защищенный криптографической подписью документ или пакет данных, удостоверяющий личность пользователя, его права доступа или подтверждающий определенные факты.

SP - приложение
Подпись осталась валидной: валидатор проверил оригинальный элемент, а приложение обработало подложный. Три правки в XML, ноль взаимодействия с IdP. Это XML Signature Wrapping, и он работает - от самописных SP до GitLab EE. Дальше разберу три вектора атак на SAML аутентификацию: XSW, Golden SAML и эксплуатацию свежих CVE в популярных библиотеках. Каждый - с позицией в kill chain, предусловиями и конкретными инструментами.

SAML-флоу глазами атакующего​

Для пентестера SAML - цепочка доверия между тремя участниками: браузером пользователя (User Agent), Service Provider (SP) и Identity Provider (IdP). SP-initiated flow - самый распространённый вариант: Подробнее - в нашем материале про атаки на аутентификацию.
  1. Пользователь заходит на SP, SP генерирует AuthnRequest и отправляет редирект на IdP
  2. IdP аутентифицирует пользователя (логин, пароль, MFA)
  3. IdP формирует SAMLResponse - XML-документ с Assertion, подписанным закрытым ключом IdP - и через браузер отправляет его обратно на SP
  4. SP валидирует подпись, извлекает атрибуты из Assertion (NameID, роли, группы) и предоставляет доступ
Критическая точка - шаг 4. SP должен убедиться, что подпись принадлежит доверенному IdP, что подписан именно тот Assertion, который обрабатывается, и что данные не модифицированы. Согласно OWASP A07:2021 - Identification and Authentication Failures, ошибки в реализации проверки аутентификации входят в десятку наиболее критичных рисков веб-приложений. Атаки на SAML бьют именно в разрыв между тем, что проверяет валидатор подписи, и тем, что обрабатывает бизнес-логика.

XML Signature Wrapping - подмена Assertion при валидной подписи​

1780308399321.webp

Механика XSW-атаки​

XML Signature Wrapping (XSW) - класс атак, эксплуатирующий разницу между двумя фазами обработки SAML: валидацией подписи и извлечением данных. По данным IBM, атакующий вставляет поддельные элементы в XML-документ, не ломая валидность цифровой подписи. Валидатор проверяет одну часть документа, приложение обрабатывает другую.

Технически это работает так: подписанный Assertion ссылается на элемент по ID через атрибут URI="#_id1234" в блоке Reference. Атакующий перемещает подписанный Assertion в другую часть DOM-дерева, а на его место ставит поддельный с произвольным NameID. Если SP ищет Assertion по XPath (например, //saml:Assertion) и берёт первый найденный - он обработает поддельный, хотя валидатор подписи корректно проверил оригинальный.

Предусловия. Работает если:
  1. Есть хотя бы один легитимный SAMLResponse от IdP (перехват через Burp или собственная учётка на SP).
  2. SP использует уязвимую реализацию проверки подписей.
Не работает если:
  1. SP привязывает Assertion к конкретной сессии и строго проверяет InResponseTo.
  2. SP верифицирует, что обрабатываемый элемент - тот самый, на который указывает Reference URI.

Применимость: внешний пентест (SP доступен через интернет, использует SAML SSO), внутренний пентест (доступ к корпоративному SSO-порталу). Категория MITRE ATT&CK: T1212 (Exploitation for Credential Access) при initial access или T1550.001 (Application Access Token) при lateral movement к другим SP.

Варианты XSW и практика с SAML Raider​

По данным HackTricks и исследования Juraj Somorovsky "On Breaking SAML", задокументировано восемь основных вариантов XSW. На практике три работают чаще остальных:

ВариантСтратегияКогда применять
XSW #1Новый корневой элемент оборачивает подпись, поддельный Response на верхнем уровнеSP использует //Assertion без привязки к конкретному родителю
XSW #3Поддельный Assertion на том же уровне, что оригинальныйSP берёт первый Assertion в документе
XSW #7Поддельный Assertion внутри элемента ExtensionsОбход schema validation в OpenSAML и аналогах с нестрогой проверкой
XSW #4-#6Варианты с вложением оригинального Assertion в поддельныйАгрессивное изменение структуры, работает против парсеров с permissive XPath
XSW #8Оригинальный Assertion вложен в менее строгий XML-элементОбход schema validation в библиотеках, не проверяющих типы вложенных элементов

На пентесте я обычно начинаю с XSW #1 и #3 - они срабатывают на наибольшем количестве реализаций. Если не прокатывает, перехожу к #7 (Extensions), потом к #4-#6.

Требования к окружению для работы с SAML Raider:
  • ОС: любая (Burp Suite кроссплатформенный)
  • Burp Suite Professional или Community Edition (проверено на 2024.x и 2025.x)
  • SAML Raider - установка через BApp Store в Burp
  • Браузер, настроенный на проксирование через Burp
  • Перехваченный SAMLResponse от целевого IdP (собственная учётка или перехват)
Порядок работы: перехватить POST-запрос с SAMLResponse на ACS-эндпоинт SP через Intercept, в SAML Raider Tab нажать "Parse SAML" - расширение декодирует Base64 и покажет XML-структуру. Выбрать вариант XSW из списка, указать целевой NameID, нажать "Apply XSW" и форвардить запрос. Расширение само перестраивает DOM-дерево, перемещая подписанный Assertion и вставляя поддельный.

Ограничения. SAML Raider покрывает стандартные XSW #1-#8. Продвинутые техники - namespace confusion, Void Canonicalization (описаны в исследовании PortSwigger от декабря 2025) - требуют ручной модификации XML. Исследователи показали, что вместо поиска подписанного SAML Assertion можно переиспользовать любой XML-документ, подписанный закрытым ключом IdP, - а это уже совсем другая поверхность атаки.

Parser differentials: почему библиотеки ломаются снова и снова​

Исследования PortSwigger вскрыли фундаментальную причину живучести XSW-уязвимостей: многие SAML-библиотеки используют два разных XML-парсера - один для валидации подписи, другой для извлечения данных. В Ruby-SAML, например, один парсер (REXML) извлекает DigestValue и SignatureValue, а другой (Nokogiri, обёртка над libxml2) выполняет каноникализацию и хеширование. Различия в обработке namespaces, комментариев и DTD между парсерами создают эксплуатируемые расхождения.

В Ruby-SAML оба парсера искали Signature по XPath //ds:Signature, возвращая первое вхождение. Дополнительная логика на REXML проверяла, что родительский элемент Signature - это Assertion. Но если атакующий помещал поддельный Assertion с вложенной Signature так, что оба парсера "видели" разные элементы - валидация проходила, а приложение обрабатывало поддельные данные. Два парсера в одном приложении - это как два замка на одной двери, каждый из которых открывается своим ключом.

Golden SAML - подделка токенов через ключ подписи IdP​

1780308769575.webp

Цепочка эксплуатации​

Если XSW обманывает SP через структуру XML, то Golden SAML - это полная компрометация доверия. Атакующий, завладевший закрытым ключом Token Signing Certificate из IdP, генерирует криптографически валидные SAML Assertion для любого пользователя, к любому SP, с любыми атрибутами. В терминологии MITRE ATT&CK - T1606.002 (Forge Web Credentials: SAML Tokens).

Microsoft характеризует Golden SAML как редкую, но высокоэффективную технику постэксплуатации. Редкость компенсируется масштабом: один украденный ключ компрометирует все учётные записи организации. Организации подключают десятки приложений к одному SSO, и один форжированный токен потенциально открывает доступ ко всем.

Предусловия. Работает если:
  1. Получены привилегии Domain Admin или локального администратора на ADFS-хосте.
  2. Извлечён Token Signing Certificate (закрытый ключ).
  3. Известны идентификаторы целевых SP (Issuer URI, Audience).
Не работает:
  1. Без предварительной компрометации on-prem инфраструктуры. Golden SAML - не initial access, это lateral movement после глубокого проникновения.

Kill chain:
  1. Компрометация ADFS-сервера - privilege escalation до Domain Admin или локального администратора на ADFS-хосте (T1556.007, Modify Authentication Process: Hybrid Identity)
  2. Извлечение закрытого ключа из Windows Internal Database (WID) или SQL Server, где ADFS хранит конфигурацию (T1552.004, Unsecured Credentials: Private Keys). Инструмент: ADFSDump для экспорта конфигурации и ключей
  3. Генерация поддельного Assertion с произвольными атрибутами - NameID, роли, группы. Инструмент: shimit (Python) для создания SAML Response с указанным ключом и параметрами целевого SP
  4. Доставка токена - подставить сгенерированный SAMLResponse в POST-запрос на ACS-эндпоинт SP через браузер
Атака SolarWinds (2020) показала Golden SAML в полный рост: после компрометации через supply chain атакующие вытянули SAML signing certificates из on-prem ADFS-серверов и форжили токены для доступа к Microsoft 365, Azure AD и другим облачным приложениям - без единого обращения к IdP.

Silver SAML - облегчённый вариант для Entra ID​

Semperis раскрыла технику Silver SAML, работающую с Microsoft Entra ID (ранее Azure AD) без компрометации ADFS. Если организация использует externally imported signing certificate в Entra ID (а не самоподписанный сертификат Entra), атакующий с доступом к этому сертификату может генерировать поддельные SAML Response. Semperis выложила PoC-инструмент SilverSAMLForger. Microsoft квалифицировала проблему как не соответствующую критериям немедленного решения, но рекомендовала использовать только самоподписанные сертификаты Entra ID. Типичная позиция - «это не баг, это фича» (но сертификат лучше поменяйте).

CVE в SAML-библиотеках: что эксплуатируется прямо сейчас​

Многие обходы SAML аутентификации бьют не в архитектуру протокола, а в баги конкретных библиотек. Три свежих CVE - все с CWE-347 (Improper Verification of Cryptographic Signature) - показывают масштаб проблемы.

CVE-2024-45409: Ruby-SAML - CVSS 10.0 (Critical)​

Уязвимые версии:
📚 Часть контента скрыта. Этот материал доступен участникам сообщества с рангом One Level или выше
Получить доступ просто — достаточно зарегистрироваться и проявить активность на форуме

Применимость: external pentest, если целевой SP работает на Rails-стеке с ruby-saml (GitLab CE/EE, приложения на OmniAuth). Fingerprinting: Rails-сессия в cookies, характерные HTTP-заголовки. Исправлено: версии 1.17.0 и 1.12.3.

CVE-2025-47949: samlify - CVSS 9.9 (Critical)​

Уязвимая версия: samlify < 2.10.0 (Node.js). Классический Signature Wrapping: атакующий, имея любой подписанный IdP XML-документ, подделывает SAML Response и аутентифицируется как произвольный пользователь. Вектор: CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N - максимальная доступность. По данным Obsidian Security, приложения на уязвимых версиях принимали неподписанные или некорректно подписанные Assertion как валидные. Исправлено: версия 2.10.0. Fingerprinting: Express-сессия в cookies, Node.js-стек.

CVE-2025-23369: GitHub Enterprise Server - CVSS 7.6 (High)​

Уязвимые версии: GHES < 3.12.14, < 3.13.10, < 3.14.7, < 3.15.2, < 3.16.0. Improper verification of cryptographic signature, позволяющая spoofing подписи для внутренних пользователей. Эксплуатация требует: GHES использует SAML SSO, атакующий уже является существующим пользователем (PR:L). Вектор: CVSS:4.0 с AC:H и ATP - высокая сложность, дополнительные предусловия. Severity - High (7.6), не Critical. Это privilege escalation для аутентифицированного пользователя, не полный bypass. Обнаружена через GitHub Bug Bounty. По данным PortSwigger, уязвимость связана с особенностями обработки namespaces в libxml2 - опять parser differential между компонентами валидации.

Историческая серия: XML Comment Injection (2017-2018)​

Ранний массовый вектор - вставка XML-комментариев в NameID для обрезки строки:
XML:
<NameID>admin@target.com<!--
-->.evil.com</NameID>
XML-парсер возвращал admin@target.com вместо полной строки admin@target.com.evil.com. Затронуты: OneLogin PythonSAML (CVE-2017-11427), Ruby-SAML (CVE-2017-11428), Clever saml2-js (CVE-2017-11429), OmniAuth-SAML (CVE-2017-11430) - все CWE-287 (Improper Authentication); Shibboleth (CVE-2018-0489, CWE-347); Duo Network Gateway (CVE-2018-7340, CVSS 7.5 High, CWE-287/CWE-347). Актуальные версии библиотек пропатчены, но на legacy-инфраструктуре вектор по-прежнему живой.

Выбор вектора: decision tree для атак на SAML аутентификацию​

УсловиеВекторИнструментKill chain этап
Есть SAMLResponse, SP на уязвимой библиотекеXSW #1-#8SAML Raider (Burp)Initial Access
SP на ruby-saml <= 1.16.0CVE-2024-45409Synacktiv PoCInitial Access
SP на samlify < 2.10.0CVE-2025-47949Ручная модификация XMLInitial Access
Скомпрометирован ADFS, нужен доступ к облачным SPGolden SAMLADFSDump + shimitLateral Movement
Доступ к external signing cert в Entra IDSilver SAMLSilverSAMLForgerLateral Movement
Legacy SP, библиотеки 2017-2018 без обновленийComment InjectionРучная правка XMLInitial Access

Fingerprinting SP перед атакой - обязательный первый шаг. Определить стек по HTTP-заголовкам, cookies (Rails-сессия -> ruby-saml, Express-сессия -> samlify), страницам ошибок, метатегам. Без знания библиотеки и версии выбор XSW-варианта превращается в слепой перебор. По формулам всё красиво, а на практике decay ощущается только когда сам прогоняешь сабмишены на реальном SSO-стенде. Если хочется потренироваться в контролируемой среде - на HackerLab.pro (https://hackerlab.pro) есть задачи в категории web, построенные на схожих примитивах с манипуляцией аутентификационных токенов.

Что видит защита и где слепые зоны SIEM при SAML-атаках

XSW и эксплуатация CVE​

SP-side: если SP логирует raw SAML Assertion (многие SP в дефолтной конфигурации этого не делают - пишут только NameID и результат), аномалии в XML-структуре теоретически детектируемы. На практике при успешном XSW лог выглядит как легитимный вход целевого пользователя.

IdP-side: XSW не затрагивает IdP. В журналах IdP будет легитимная аутентификация пользователя-атакующего (от чьего имени получен оригинальный SAMLResponse). Аномалию можно поймать корреляцией: один пользователь аутентифицируется в IdP, а в SP фиксируется вход другого. Но для этого нужна интеграция логов обеих систем - а это на практике встречается редко.

Golden SAML​

По данным Microsoft, Golden SAML создаёт ноль событий аутентификации в IdP. IdP в атаке не участвует вообще. Мониторинг failed logins, impossible travel, MFA failures - бесполезен. Стандартные SIEM-корреляции пропускают атаку полностью.

Детекция возможна через: поведенческий анализ post-authentication (нетипичные SP, время, объёмы); мониторинг изменений ADFS-конфигурации - Event ID 307 (ротация Token Signing Certificate) в ADFS Audit Log; мониторинг изменений PreferredTokenSigningKeyThumbprint в журналах Entra ID ApplicationManagement; Microsoft Defender for Identity (содержит алерты для Golden SAML).

Главная слепая зона: если ADFS Audit Log не интегрирован в SIEM (а это нередкая ситуация - организации не трогают настройки ADFS годами), компрометация ключа подписи останется невидимой, пока behavioral analytics не зацепит аномальные паттерны доступа. А может и не зацепит.

Чеклист для blue team​

  1. Интегрировать ADFS Audit Log в SIEM
  2. Настроить алерт на Event ID 307 (изменение signing certificate) в ADFS
  3. Мониторить PreferredTokenSigningKeyThumbprint в Entra ID Audit
  4. Использовать только самоподписанные сертификаты Entra ID (митигация Silver SAML)
  5. Корреляция SP и IdP: NameID в SP должен соответствовать аутентифицированному пользователю в IdP
  6. Обновить SAML-библиотеки: ruby-saml >= 1.17.0, samlify >= 2.10.0, GHES до актуальных версий
  7. Проверить, что SP привязывает Reference URI к конкретному обрабатываемому элементу - не к первому найденному Assertion по XPath
Я работаю с SAML-инфраструктурами на пентестах уже несколько лет и вижу устойчивую закономерность: SAML ломают не через криптографию, а через парсеры. Каждый год появляется CVE с CVSS 9+ в очередной библиотеке - и каждый раз корень один: два разных парсера в одном приложении, один для валидации подписи, другой для извлечения данных.

Проблема глубже отдельных CVE. SAML 2.0 - стандарт 2005 года, построенный на XML. Спецификация XML-подписи допускает десятки способов размещения подписи относительно подписанных данных: enveloped, enveloping, detached. Каждая библиотека интерпретирует допустимые размещения по-своему, каждая интерпретация - потенциальный XSW-вектор. Исследователи продолжают находить новые классы атак на каноникализацию XML, и конца этому не видно.

Golden SAML - другая история. Тут проблема не в коде, а в архитектуре: организации годами тянут ADFS как мост между on-prem AD и облаком, и этот мост становится single point of compromise. Microsoft прямо рекомендует переход на чисто облачную идентификацию, но для многих это проект на годы.

Мой прогноз: в ближайший год мы увидим ещё несколько критических CVE в SAML-библиотеках - исследование parser differentials набирает обороты. Для пентестера это означает одно: fingerprinting SAML-стека SP - не опциональный шаг, а первый. Знать, какая библиотека, какой версии, какие парсеры под капотом - разница между «получил DA за час» и «потратил день на слепой перебор XSW-вариантов».
 
Последнее редактирование модератором:
Мы в соцсетях:

Взломай свой первый сервер и прокачай скилл — Начни игру на HackerLab

Похожие темы

🚀 Первый раз на Codeby?
Гайд для новичков: что делать в первые 15 минут, ключевые разделы, правила
Начать здесь →
🔴 Свежие CVE, 0-day и инциденты
То, о чём ChatGPT ещё не знает — обсуждаем в реальном времени
Threat Intel →
💼 Вакансии и заказы в ИБ
Pentest, SOC, DevSecOps, bug bounty — работа и проекты от проверенных компаний
Карьера в ИБ →

HackerLab