跳到主内容
@wquguru
精选90Hacker News Best(web_list)技巧与观点

Trail of Bits深度复盘:SAML为何是糟糕设计的分形

SAML: A fractal of bad design

原文
发到 X
推荐理由

做身份认证与安全的工程师必读,这篇来自Trail of Bits的深度复盘把SAML的底层设计缺陷和踩坑经验讲透了,对理解OIDC替代方案很有价值。

Page content

页面内容

Born out of academia and raised in corporate IT departments, the Security Assertion Markup Language (SAML) authentication protocol continues to be a staple in these organizations. However, it’s time for it to retire. With the rise of software-as-a-service (SaaS) companies in the late aughts, IT departments needed a way for users to authenticate to many new web services. SAML and the burgeoning single sign-on (SSO) industry fulfilled this need. However, SAML is being crushed under the weight of its own complexity. It’s time to deprecate it and move on to modern alternatives like OpenID Connect (OIDC). In this post, I will explore the design-by-committee origin of SAML, its progression through the ranks in academic and corporate environments, its slow disintegration at the hands of the security research community, and its (hopeful) deprecation in favor of newer protocols.

安全断言标记语言(SAML)身份验证协议诞生于学术界,并在企业 IT 部门中成长壮大,至今仍是这些组织中的核心组件。然而,它该退休了。随着 2000 年代末软件即服务(SaaS)公司的兴起,IT 部门需要一种让用户向众多新 Web 服务进行身份验证的方法。SAML 以及蓬勃发展的单点登录(SSO)行业满足了这一需求。然而,SAML 正因其自身的复杂性而不堪重负。是时候弃用它并转向 OpenID Connect(OIDC)等现代替代方案了。在本文中,我将探讨 SAML 的委员会式设计起源、它在学术和企业环境中的发展历程、它在安全研究社区手中的缓慢瓦解,以及它(希望如此地)被更新协议取代的过程。

SAML 101

SAML 入门

What’s insidious about SAML is that it really is mostly straightforward to understand, but it’s built on a foundation of sand, bone dust, and ash; it works … if you assume XML signature validation is reliable. But XML signature validation is deeply cursed, and is so complicated that most fielded SAML implementations are wrapping libxmlsec, a gnarly C codebase nobody reads.

SAML 的阴险之处在于,它实际上大多易于理解,但其基础却建立在流沙、骨粉和灰烬之上;它能工作……前提是你假设 XML 签名验证是可靠的。但 XML 签名验证深藏诅咒,且极其复杂,以至于大多数部署的 SAML 实现都在包装 libxmlsec——一个无人阅读的、结构混乱的 C 代码库。

— Thomas Ptacek, 2023

—— Thomas Ptacek, 2023

SAML and the birth of the SSO industry

SAML 与 SSO 行业的诞生

Wikipedia tells me that “SAML is an XML-based markup language for security assertions.” It was created in 2002 by the Organization for the Advancement of Structured Information Standards (OASIS) Security Services Technical Committee (SSTC). Okay, we’re not off to a great start by modern standards. XML, despite having some redeeming qualities, is quite complex compared to newer alternatives like JSON, but we’ll get more into that later. Further, a committee of subcommittees having meetings is a recipe for “kitchen-sink” protocol design (e.g., waterfall methodology, big design up front, etc.). And sure enough, we’ve now jammed four (!) XML-based security protocols into one:

维基百科告诉我:“SAML 是一种基于 XML 的安全断言标记语言。”它由结构化信息标准促进组织(OASIS)安全服务技术委员会(SSTC)于 2002 年创建。好吧,以现代标准来看,我们开局并不顺利。尽管 XML 有一些可取之处,但与 JSON 等较新的替代方案相比,它相当复杂,但我们稍后会深入探讨这一点。此外,由子委员会组成的委员会开会,往往是“大杂烩”式协议设计(例如瀑布式方法论、大型前置设计等)的温床。果然,我们现在将四个 (!) 基于 XML 的安全协议塞进了一个协议中:

… the following intellectual property was contributed to the SSTC:

……以下知识产权已贡献给 SSTC:

  • Security Services Markup Language (S2ML) from Netegrity
  • AuthXML from Securant
  • XML Trust Assertion Service Specification (X-TASS) from VeriSign
  • Information Technology Markup Language (ITML) from Jamcracker
  • 来自 Netegrity 的安全服务标记语言(S2ML)
  • 来自 Securant 的 AuthXML
  • 来自 VeriSign 的 XML 信任断言服务规范(X-TASS)
  • 来自 Jamcracker 的信息技术标记语言(ITML)

— SAML: History

—— SAML:历史

However, the desire for such a protocol was undeniable. As the internet shifted from Web 1.0 in the 90s to Web 2.0 in the early aughts, users and organizations needed an easy way to authenticate to many new web services. Academia was the biggest driver of this movement, although not the only one: Central Authentication Service (CAS) in 2002 at Yale, Shibboleth IdP in 2003 by Internet2, a consortium of research universities (including my alma mater), ADFS in 2003 by Microsoft, and simpleSAMLphp around 2007 by Uninett, a state-owned Norwegian company with close ties to academia. All these authentication projects eventually supported SAML in one way or another. Like ARPANET before it, universities were at the forefront of internet development and were the earliest consumers of web services. Once this base layer of protocol availability and nascent academic proving ground was established, the commercial industry took it and ran toward a multibillion dollar industry.

然而,对这种协议的渴望是显而易见的。随着互联网从 90 年代的 Web 1.0 转向新世纪初的 Web 2.0,用户和组织需要一种简单的方式来向众多新的网络服务进行身份验证。学术界是推动这一运动的主要力量,尽管并非唯一:耶鲁大学于 2002 年推出的中央认证服务(CAS),由包括我母校在内的研究型大学联盟 Internet2 于 2003 年推出的 Shibboleth IdP,微软于 2003 年推出的 ADFS,以及拥有紧密学术联系挪威国有公司 Uninett 在 2007 年左右推出的 simpleSAMLphp。所有这些身份验证项目最终都以某种方式支持了 SAML。就像此前的 ARPANET 一样,大学处于互联网发展的前沿,也是网络服务的早期消费者。一旦建立起这一协议可用性的基础层和初步的学术试验场,商业行业便接手并推动其发展成为一个价值数十亿美元的产业。

The SSO, identity, and authentication provider industry was also starting up in the early aughts, but really came to fruition a few years later: Ping Identity (2002), OneLogin (2009), Okta (2009), and Duo Security (2010). These companies were essentially built on the SAML protocol with the exception of Duo, who would introduce their first SSO product in 2015, which is where I come into the story. I worked on Duo’s first on-premises Access Gateway product (DAG), which was built on simpleSAMLphp and, obviously, the SAML protocol. It’s where I became intimately familiar with the SAML protocol and spent many years of my life digesting its lengthy specifications. I was there when Kelby Ludwig found the XML comment bypass, but we will get into various attacks and SAML deficiencies later. Suffice it to say, the SSO and authentication provider industry was booming, and much of it was built on the SAML protocol.

单点登录(SSO)、身份和身份验证提供商行业也在新世纪初起步,但真正取得成果是在几年后:Ping Identity(2002)、OneLogin(2009)、Okta(2009)和 Duo Security(2010)。除了 Duo 之外,这些公司基本上都是建立在 SAML 协议之上的,Duo 直到 2015 年才推出其第一个 SSO 产品,这也是我进入这个故事的地方。我参与了 Duo 的第一个本地部署访问网关产品(DAG)的开发,该产品基于 simpleSAMLphp 和显然的 SAML 协议构建。正是在这里,我对 SAML 协议变得非常熟悉,并花费了我生命中许多年的时间来研读其冗长的规范。当 Kelby Ludwig 发现 XML 注释绕过漏洞时我就在那里,但我们稍后会深入探讨各种攻击和 SAML 的缺陷。 suffice it to say(可以说),SSO 和身份验证提供商行业蓬勃发展,其中很大一部分是基于 SAML 协议构建的。

A crack in the armor

盔甲上的裂痕

XML signature wrapping (XSW) attacks are the proverbial arrow to SAML’s heel. While there was earlier security research into both signature wrapping (2005, 2008, and 2009) and SAML (2008), I consider the godfather of it all to be “On Breaking SAML: Be Whoever You Want to Be” (2012). It tested theory against practice and resulted in an automated way to check for XSW attacks. This was our north star when implementing the DAG. It was the reason we chose simpleSAMLphp as our building block. PHP, especially at the time, was not exactly known for its security track record, but simpleSAMLphp’s spoke for itself. simpleSAMLphp was resilient to XSW at a time when nobody really knew what that was:

XML签名包装(XSW)攻击是SAML的致命弱点。虽然早在2005年、2008年和2009年就有关于签名包装的安全研究,以及2008年关于SAML的研究,但我认为这一切的鼻祖是《On Breaking SAML: Be Whoever You Want to Be》(2012)。该研究将理论与实践相对照,并产生了一种自动检测XSW攻击的方法。这是我们实现DAG时的指路明灯,也是我们要选择simpleSAMLphp作为构建模块的原因。PHP在当时并不以安全记录著称,但simpleSAMLphp却表现突出。在大家还不太了解XSW为何物时,simpleSAMLphp就具备了对抗XSW的韧性:

simpleSAMLphp’s security track record (credit: On Breaking SAML)

simpleSAMLphp的安全记录(来源:On Breaking SAML)

Despite being front and center in this 2012 paper, XSW is still present today. If we know the bug class, then why can’t we fix it? But before we get into SAML’s flaws we first have to consider the shaky ground it was built upon: XML.

尽管这篇2012年的论文重点讨论了XSW,但它至今仍然存在。既然我们已经知道这类漏洞,为什么不能修复它呢?但在深入探讨SAML的缺陷之前,我们首先必须考虑其赖以建立的脆弱基础:XML。

XML is no slouch when it comes to a (lack of) security track record. These bug classes would have been more familiar to a developer in the 90s, but nonetheless are still present in XML today: XXE, entity expansion (“billion laughs”), DTD retrieval (SSRF), XPath/XQuery/XInclude/XSLT/CDATA injection, and more. A SAML library needs to handle all these bug classes before even getting to the actual SAML functionality.

XML在(缺乏)安全记录方面绝非等闲之辈。这些漏洞类别对于90年代的开发者来说可能更为熟悉,但它们至今仍存在于XML中:XXE、实体扩展(“十亿次笑声”)、DTD检索(SSRF)、XPath/XQuery/XInclude/XSLT/CDATA注入等。一个SAML库在处理实际的SAML功能之前,需要先应对所有这些漏洞类别。

In addition to security bug classes, there’s also the sheer complexity of XML when compared against something like JSON. In XML you have tags, elements, attributes, comments, namespaces, markup versus content, schemas, CDATA, DOCTYPEs, and more. In JSON, you essentially have keys, values, objects, and lists. Complexity is generally at odds with security, and this is one reason I consider SAML to be a fractal of bad design.

除了安全漏洞类别之外,与JSON相比,XML本身的复杂性也是一大挑战。在XML中,你有标签、元素、属性、注释、命名空间、标记与内容的区别、模式、CDATA、DOCTYPE等。而在JSON中,你基本上只有键、值、对象和列表。复杂性通常与安全背道而驰,这也是我认为SAML是糟糕设计的分形结构的原因之一。

A fractal of bad design

糟糕设计的分形结构

SAML provides ample opportunity to learn about protocol design. In this section, I will cover five flaws that I consider to be fatal to the long-term viability of SAML as an authentication protocol. These flaws can also be used when designing new authentication protocols. That is, you can either sidestep the flaw, or take its inverse and attempt to bake that into the protocol.

SAML为学习协议设计提供了充足的机会。在本节中,我将介绍五个我认为对SAML作为身份验证协议的长期生存能力具有致命影响的缺陷。在设计新的身份验证协议时,也可以借鉴这些缺陷。也就是说,你可以避开这些缺陷,或者取其反面并尝试将其融入协议中。

Built on XML

基于XML构建

As mentioned above, SAML is built on XML, and XML is complex, but it’s not the committee’s fault. XML is what they had at the time, and it’s what people used. JSON was “discovered” in 2001, but this was right around the time the SAML committee was meeting, and they’d be unlikely to design an authentication protocol around an experimental new format. Especially when it caters to JavaScript and you write a lot of Java.

如上所述,SAML 基于 XML 构建,而 XML 很复杂,但这并非委员会的过错。XML 是当时他们拥有的技术,也是人们所使用的技术。JSON 在 2001 年被“发现”,但这正好处于 SAML 委员会开会的时间段,他们不太可能围绕一种实验性的新格式来设计身份验证协议。尤其是当该格式迎合 JavaScript 而你却编写大量 Java 代码时。

One could design a quantitative complexity measurement for XML versus JSON or SAML versus JWT/OIDC (e.g., spec/RFC word count, spec/RFC normative word count, etc.), but that would require a blog post or paper all to itself. In the interest of staying on topic, I will refrain from doing that here, and suffice to say that XML is significantly more complex than something like JSON.

人们可以为 XML 与 JSON 或 SAML 与 JWT/OIDC 设计定量的复杂度度量标准(例如规范/RFC 字数、规范/RFC 规范性字数等),但这需要一篇专门的博客文章或论文。为了保持主题集中,我将在此处避免这样做,只需说明 XML 比 JSON 之类的东西要复杂得多。

Canonicalization

规范化

Canonicalization (C14N) is what you do when you want to take the wild mess that is XML, compute a hash of it, and get consistent results. In other words, if the SP and IdP cannot agree on a consistent representation of the XML data, then the bytes won’t line up, the signatures won’t match, and your authentication fails. However, this is easier said than done.

规范化(C14N)是指当你想要处理 XML 这一混乱局面,计算其哈希值并获得一致结果时所进行的操作。换句话说,如果 SP(服务提供方)和 IdP(身份提供方)无法就 XML 数据的一致表示达成一致,那么字节流将无法对齐,签名将不匹配,从而导致身份验证失败。然而,这说起来容易做起来难。

Canonicalization bugs enabled Kelby’s XML comment bypass in 2018:

规范化漏洞导致了 2018 年 Kelby 的 XML 注释绕过攻击:

XML canonicalization (credit: Identity Theft)

XML 规范化(图片来源:Identity Theft)

Canonicalization is often a precursor to parser differential and/or “round-trip” bugs, which are what most modern SAML attacks use:

规范化通常是解析器差异和/或“往返”漏洞的前奏,而这些正是大多数现代 SAML 攻击所利用的:

更进一步:量化金融体系

看懂新闻只是起点——沿量化金融路径,把它变成能交付的工程能力

进入量化体系 →

相似阅读

关联信息,但可能不是同一事件