The Daily Newsstand · Free, Always
Friday, September 25, 2026

[Перевод] Почему SAML ломают снова и снова: пять фатальных изъянов протокола аутентификации

Translate

SAML больше двадцати лет обеспечивает единый вход (SSO) в корпоративной и академической среде. Но протокол прогибается под тяжестью собственной сложности, и ему пора на пенсию. Разбираемся, как SAML появился, почему его раз за разом ломают исследователи безопасности и почему на смену ему должен прийти OpenID Connect (OIDC).

Коварство SAML в том, что он в основном прост для понимания, но стоит на фундаменте из песка, костной пыли и пепла. Он работает… если считать, что проверке XML-подписей можно доверять. Но проверка XML-подписей проклята, и большинство реализаций SAML — обёртки над libxmlsec, жуткой кодовой базой на C, которую никто не читает.

— Томас Птачек (Thomas Ptacek), 2023

Как появился SAML

SAML (Security Assertion Markup Language) создал в 2002 году технический комитет SSTC организации OASIS. Уже здесь два тревожных сигнала. Во-первых, XML: у него есть достоинства, но по сравнению с JSON он весьма сложен. Во-вторых, комитет из подкомитетов — верный признак протокола по принципу «всё и сразу» (kitchen-sink). Так и вышло: в SAML втиснули сразу четыре XML-протокола безопасности:

  • Security Services Markup Language (S2ML) от Netegrity;

  • AuthXML от Securant;

  • XML Trust Assertion Service Specification (X-TASS) от VeriSign;

  • Information Technology Markup Language (ITML) от Jamcracker.

При этом потребность в таком протоколе была бесспорной. С переходом к Web 2.0 пользователям понадобился простой способ входить во множество новых веб-сервисов. Двигателем стали университеты: CAS (Йель, 2002), Shibboleth IdP (консорциум Internet2, 2003), а также ADFS от Microsoft (2003) и simpleSAMLphp от норвежской Uninett (около 2007). Все они со временем стали поддерживать SAML. Академическая среда обкатала протокол, а коммерческая индустрия превратила его в рынок на миллиарды долларов: Ping Identity (2002), OneLogin (2009), Okta (2009), Duo Security (2010).

Почти все эти компании строились на SAML. Duo выпустила свой первый SSO-продукт в 2015 году, и тут в историю вступаю я: я работал над Duo Access Gateway (DAG) — локальным (on-premises) решением на базе simpleSAMLphp. Там я годами переваривал спецификации SAML и был рядом, когда Келби Людвиг (Kelby Ludwig) нашёл обход через XML-комментарии.

Трещина в броне: атаки XSW

Ахиллесова пята SAML — атаки с обёртыванием XML-подписи (XML signature wrapping, XSW). Их исследовали с 2005 года, но ключевой я считаю работу «On Breaking SAML: Be Whoever You Want to Be» (2012): авторы проверили теорию на практике и предложили автоматический способ поиска XSW. При создании DAG она была нашей путеводной звездой. Из-за неё мы и выбрали simpleSAMLphp: PHP тогда безопасностью не славился, но simpleSAMLphp был устойчив к XSW, когда почти никто не знал, что это такое.

Послужной список simpleSAMLphp в плане безопасности (источник: On Breaking SAML)

Послужной список simpleSAMLphp в плане безопасности (источник: On Breaking SAML)

Прошло больше десяти лет, а XSW по-прежнему актуальны. Почему известный класс ошибок не удаётся искоренить? Чтобы ответить, нужно взглянуть на фундамент SAML — XML.

По части (не)безопасности у XML богатая история: XXE, раскрытие сущностей («billion laughs»), загрузка DTD (SSRF), инъекции в XPath/XQuery/XInclude/XSLT/CDATA. Библиотека для SAML должна закрыть всё это ещё до того, как дойдёт до собственно SAML. Плюс сама сложность формата: в XML есть теги, элементы, атрибуты, комментарии, пространства имён, схемы, CDATA, DOCTYPE и многое другое, а в JSON — ключи, значения, объекты и списки. Сложность — враг безопасности.

Пять фатальных изъянов SAML

Эти изъяны, на мой взгляд, ставят крест на будущем SAML. Их полезно учитывать и при проектировании новых протоколов: либо обходить, либо закладывать противоположные свойства.

1. Построен на XML

Комитет тут не виноват: XML был под рукой, им все пользовались. JSON «открыли» в 2001 году, как раз когда заседал комитет, и вряд ли кто-то стал бы строить протокол аутентификации на экспериментальном формате, заточенном под JavaScript, — особенно если сам пишешь в основном на Java. Количественно сравнить сложность XML и JSON (или SAML и JWT/OIDC) — тема для отдельной статьи, но то, что XML значительно сложнее, очевидно.

2. Канонизация

Канонизация (canonicalization, C14N) нужна, чтобы из хаотичного XML получать стабильный хеш. Если SP и IdP не договорятся о единообразном представлении данных, байты не совпадут, подпись не сойдётся, и аутентификация провалится. Сделать это правильно очень непросто.

Именно ошибки канонизации позволили Келби в 2018 году обойти проверку через XML-комментарии.

Канонизация XML (источник: Identity Theft)

Канонизация XML (источник: Identity Theft)

Они же открывают дорогу багам расхождения парсеров (parser differential) и ошибкам «туда-обратно» (round-trip), на которых строится большинство современных атак на SAML:

3. Вложенные подписи

Близкий родственник предыдущей проблемы. Если вставлять подпись внутрь тех самых данных, которые подписываешь, ничего хорошего не выйдет.

Подписи в JWT и SAML (источник: jwt.io и samltool.io)

Подписи в JWT и SAML (источник: jwt.io и samltool.io)

В JWT подпись отделена от JSON-данных точкой («.»). В SAML элемент Signature вложен (enveloped) внутрь элемента Assertion. Получить побайтно совпадающее, канонически эквивалентное представление данных, одновременно их изменяя, очень трудно, а со сложными правилами канонизации XML — тем более.

4. Всё и сразу

Здесь уместен принцип YAGNI (you aren’t gonna need it — «вам это не понадобится»). Набор реально используемых частей SAML за 20 лет менялся (прощайте, SOAP и artifact binding), но сегодня 99% реализаций используют почти одинаковую структуру данных и одно и то же подмножество спецификации. Типичная SAML-аутентификация не задействует 90% стандарта, а сложность ради неиспользуемых функций никуда не девается.

Если бы я добавлял поддержку SAML во что-то новое, то помимо стандартных проверок подумал бы о том, чтобы отклонять любое сообщение, по структуре не похожее на то, что генерируют Okta, OneLogin, Google или Shib.

— Томас Птачек, 2021

5. Окостенение

SAML проектировался под другую эпоху и так и не получил нужных обновлений. Проблемы здесь скорее практические:

  • Независимость от транспорта. OIDC рассчитан на HTTP, а SAML нет. HTTP-привязки (bindings) для SAML есть и используются чаще всего, но они не обязательны. Гибкость нужно описать, реализовать и отладить. OIDC же перекладывает шифрование и доверенный канал на HTTPS.

  • Отсутствие прямой связи между сторонами. Основной поток OIDC (authorization code) предполагает, что провайдер OpenID (OP) и проверяющая сторона (RP) — аналоги IdP и SP — общаются напрямую. Тогда ответ на аутентификацию не обязан содержать всё необходимое для решения об аутентификации и авторизации: остальное можно передать по отдельному серверному каналу (backchannel). Это уменьшает размер и сложность ответа. В OIDC есть неявный поток (implicit flow) с form post, а в SAML — artifact binding для прямой связи, но оба сегодня встречаются редко.

  • Проектирование заранее. OIDC — это десятки спецификаций и RFC, которые появлялись постепенно под конкретные задачи, как в agile. Хронология развития OIDC (неполная):

    • OpenID Connect 1.0 (2014);

    • стек JOSE для JW{S,E,K,A,T}, RFC 7515–7519 (2015);

    • PKCE, RFC 7636 (2015);

    • PKCE для мобильных и нативных приложений, RFC 8252 (2017);

    • Device authorization grant для IoT, RFC 8628 (2019);

    • DPoP (Demonstrating Proof of Possession) для сценариев с MFA, RFC 9449 (2023);

    • PKCE для SPA, RFC 10017 (2026).

Интересен и исторический контекст. SAML взрослел в эпоху VPN и сегментированных сетей: если IdP или SP стоял за корпоративным файрволом и не мог связаться с другой стороной, внедрение срывалось, а вендор терял сделку. В 2014 году BeyondCorp от Google и концепция нулевого доверия (zero trust) перевернули этот подход. К тому же SAML не предвидел революцию мобильных устройств, SPA и IoT, и ответа на них у него не нашлось. Всё это положило начало медленному упадку протокола. Гибкость и слабая связанность позволяют быстро адаптироваться к меняющейся ИТ-среде.

Все дороги ведут в OIDC

Идеальных протоколов не бывает, но решение очевидно. Насколько я могу судить, единственный сценарий, где SAML выигрывал, — сети, в которых SP и IdP не могут связаться напрямую. Неявный поток OIDC с form post закрывает и его. Это один из самых чистых планов миграции, какие я встречал.

Если вы поставщик услуг (SP) — просто поддерживайте OIDC и откажитесь от SAML. Fly.io и Tailscale, судя по всему, уже так делают:

Пока нам удаётся держаться только OIDC. Tailscale тоже. Если это получается у Tailscale — с учётом того, кому они продают, — думаю, получится и у большинства компаний. Постарайтесь обойтись без SAML. Как вендор вы часто конкурируете с компаниями, у которых вообще нет полноценной интеграции с SSO.

— Томас Птачек, 2024

Если вы провайдер идентификации (IdP) — путь может оказаться долгим, в зависимости от числа клиентов. Но дорога давно протоптана:

  1. Составьте план отказа от SAML и сообщите о нём клиентам.

  2. Перестаньте подключать новых клиентов через SAML.

  3. Предложите существующим клиентам эквивалентные конфигурации OIDC.

  4. Назначьте дату отключения — и за работу.

Итоги

SAML достойно прослужил 25 лет: породил индустрию SSO, защитил бессчётное число аутентификаций, упростил вход в десятки сервисов и принёс миллиарды долларов экономического эффекта. Его создателям стоит сказать спасибо. Но сегодня SAML — прежде всего отличный учебный пример того, как проектируются и развиваются протоколы.

View the original on Хабр →

KioskNews shows a cleaned-up reading view extracted from the publisher’s page — the original always lives on their site, not ours.