安全断言标记语言 (SAML) 是一种用于在各方之间交换身份验证和授权数据的开放标准。 SAML 通常用于单点登录(“使用 Google 登录”、“使用 Twitter 登录”等)。这意味着当您要登录 example.com 时,example.com 可以信任并使用外部身份验证提供程序为您断言用户的身份。 SAML 是关于跨组织边界(网络域)传达这些身份验证和身份详细信息。 SAML 最近出现了具有非常大影响的灾难性漏洞。例如,如果我理解正确(我可能理解,因为安全研究人员转发了我的反应)芬兰税务机关、大多数政府服务和健康记录系统都是脆弱的,以至于攻击者本可以继续窥探人们的纳税申报表、健康记录以及基本上任何在线可用的政府相关信息。它在很大程度上被媒体忽略了,也许是因为这些漏洞没有被利用(或者没有检测到这样的实例)。 SAML 使用基于计算值的签名。这种做法本质上是不安全的,因此 SAML 作为设计是不安全的。总而言之:一旦您将安全性基于某些计算属性,您现在就可以利用此计算中的任何缺陷、差异或歧义。计算越复杂,就越危险。SAML 签名计算非常复杂。但是让我们继续解释这个概念。让我们拿一个伪身份文件(尽管实际 SAML 是 XML):
现在,如果我们稍微更改文件(我在 { 之前添加了空格)。我们注意到签名发生了变化:这是一个非常好的属性,因为理想情况下,我们希望对安全性进行任何更改(即使是那些在 JSON 级别被认为毫无意义的更改)-关键文档(SAML 是)以生成不同的签名。可以在不破碎的情况下塑造成其他东西的东西的质量,例如粘土的延展性。我们将文档签名为原始字节 blob 使得这种不可延展性,即它不能在不破坏它的情况下成形。这是信息安全领域的理想行为。为了通过示例进行解释,让我们回到 JSON 示例。我们将使用 jq(一个 JSON 转换实用程序)从我们的文档内部计算一些东西:注意通过 jq 管道文件是如何删除空间的?那是因为在 JSON 级别空间并不重要。乍一看,这似乎并不有趣,但我们正在快速前往危险区域。即使文件仍然有空格修改,签名现在与原始签名匹配(来自没有添加空格的文件)。
$ cat assertion.json{ "signed_in_user": "EvilAttacker", "signed_in_user": "Joonas"}$ cat assertion.json | .jq | sha1sume58dc03a7491f9e5fb2ed664b23d826489c42cc5#上面是因为:$ cat assertion.json | jq .{ "signed_in_user": "Joonas"} 签名仍然与原始文件匹配。这是因为重复的密钥是有效的 JSON,在处理时被删除,并且大多数 JSON 实现让最后一个密钥获胜。现在,如果您有两段不同的代码来处理 SAML 文档,并且它们对 JSON 重复键(= 消息语义内容)有不同的解释/解析器行为,会发生什么?攻击者要求身份提供者为他签署断言,但由于 SAML 的可延展性,他能够攻击解析器差异并篡改文档,使其对签名验证仍然有效,但可以访问其他用户的数据。现在我希望解释了延展性和基于计算/解释内容的签名是多么危险。这些 SAML 漏洞发生的事情并不像我们的 JSON 示例那么简单,但这说明了这些漏洞的原理及其根本原因:对计算值和延展性进行签名。最新的漏洞是由于 XML 往返不稳定性造成的(请参阅标题“XML 往返漏洞是什么样的”)。
总之,漏洞产生于解析 XML -> 编写 XML 产生语义不同的文档,即编码(解码(xmlDocument))!= xmlDocument)。我不是 100 % 确定,但我认为由于 SAML 签名验证需要一个 XML 写入步骤,它是这样的:如果 SAML 待签名内容是不可延展的,则上述内容不会成为攻击向量,即身份提供者签署文档后的任何更改都将被检测为签名违规。让我们真诚地假设 SAML 设计者知道不可延展性是一个很好的属性,让我们试着猜测为什么他们最终仍然采用可延展性设计。所以,让我们签署一些东西。当一个人签署某物时,得到一个签名作为输出:sign(contentToSign,signingKey) -> 签名。为了使签名有用,您需要将签名与 contentToSign 一起传输,以便在消费者读取 contentToSign 时,他们可以使用签名对其进行验证。但是缺少签名。 SAML 设计人员可能不想单独传输 SAML 文档及其签名(签名可能在 HTTP 标头或 URL 参数中),因此为了方便起见,他们希望将其嵌入到同一个 XML 文档中:
从技术上讲,它会得到更多的 YOLO。签名存储在 contentToSign 下,因此在验证过程中,签名需要被忽略(同样是更危险的复杂性),以不将其真正包含在 contentToSign 中,这将使其成为不可能的递归问题:但让我们想象一下之前签名是没有存储在 contentToSign 中,如果我们可以基于字节进行签名验证,请回到问题上来!问题是从 XML 消息内部提取属于 contentToSign 的字节真的很困难。据我所知,XML 解析器 API 不支持此用例。即使有些人愿意,为了使 SAML 有用,他们也必须迎合大多数 XML 解析器实现支持的内容。 => 当你有 samlDocument 并且你想访问它的子树 contentToSign 时,你只能在那里获得 XML 级别的访问权限,所以 SAML 设计者可能没有考虑太多,去🤷♂️ 说“让我们签署 XML-然后水平数据”。对 XML 解析器的输出进行签名真的很难,因为您试图从 XML 解析输出中保持签名输入稳定,XML 解析输出在 XML 库与库之间以及语言与语言之间存在解析器差异。所以这就是为什么我们有 XML dsig 的原因,它具有例如排序 XML 的规则属性在一些 clusterfuck order 中,以便 SAML 实现就验证签名的字节序列达成某种稳定的共识。最后,无论如何我们总是需要匹配字节。这种疯狂被称为规范化,它转换了这样的东西:(这只是我发明的一个例子,我不确定哪些规则确实存在,但这里有一些例子。)总结:XML 子树很难签名/验证,并且有一些可怕的事情来实现这一点,正如经验证据所示,这是一个安全噩梦。
我愿意记录在案并说使用此类方法的所有内容都已损坏,应该被视为不安全。由于 Go 的漏洞,他们不得不修复 Go 的 XML 堆栈中的往返不稳定性,并且作为安全预防措施,包括在实际处理 XML 之前进行往返稳定性验证。概括地说,不是从一堆字节验证签名,对于 SAML 签名验证,我们需要: XML 规范化(XML dsig,它再次编码但具有特定的复杂规则和转换)如果这对您来说听起来很复杂,那是因为它确实如此。事情越复杂,就越有可能出现错误和安全问题。我是一个业余爱好者,所以请对我的想法持保留态度,但让我们尝试一下。 (注意:这篇文章都是伪代码——它不是真正的 SAML。如果你有兴趣,这里有一个真实的例子。)
取 <Assertion> 并将其子树序列化为字节并将其存储为 base64 或类似格式,因此我们可以将其作为字节传输,并且只有在签名得到验证后才对其进行 XML 解析:我对 XML 了解不多,所以有可能是传输字符串或字节数据的更漂亮的方法,但这应该足以说明问题。通过这种方式,他们可以将所有内容的属性都保留在一个 XML 文档中 - 但您只需要进行两次 XML 解析:当然,纯粹主义者可能会争辩说,将 XML 作为字符串或字节存储在 XML 中是丑陋的(我同意你的看法) ),但看看我们取得了什么.. 权衡是值得的 - SAMLContentToSign 中的所有内容现在都是不可延展的,您无需在验证来自受信任的来源之前解析安全关键数据。而且我们不需要“XML dsig”这样的呕吐物。 SAML 要求您支持 XML 文档的根未签名的用例,即您只对断言元素进行签名。允许攻击者控制数据的目的是什么?在这些情况下,您需要额外的代码来丢弃不安全的数据,因为如果您最终使用它,那将是一场灾难。我不知道。我不知道更好的标准 - 尽管我不太了解空间。 OAuth2 存在但旨在获得对资源的授权,因此它本身不是身份验证/身份协议。更多关于差异。
我的猜测也是,一旦标准获得牵引力,即使有可用的选项也很难迁移到更好的选项,因为前一个选项已经具有临界质量(想想 Whatsapp 与 Signal)。让我们摆脱 SAML。 🗑️ 一些专家似乎推荐 OAuth2 或 OpenID Connect:根据我的经验,您对任何主题了解得越多,您就越意识到所有这些都是由泡泡糖和胶带粘在一起的。老实说,这很容易引起焦虑。当我研究这个主题时,我还注意到芬兰政府网站的安全性依赖于一个用 JavaScript 实现的单点登录组件(甚至不是 TypeScript),它: 这只是一个被遗忘的从灾难性的流控制错误中返回,执行意外流尽管签名验证错误处理ValidlySignedPostRequest。但这就是当您使用一种语言实现安全关键软件时得到的结果,其中流控制不是一种语言功能,而是一种构建在该语言之上的库功能。 TypeScript 至少会提供适当的异步/等待流控制,编译器会注意到大多数错误。更新:好消息,Finnishgov't fork 所基于的上游项目最近已迁移到 TypeScript。 🎉
https://www.imperialviolet.org/2014/09/26/pkcs1.html - PKCS#1 有很多问题,因为首先解析过于灵活的结构,然后根据计算结果验证事物。 “解析是危险的”。 sha1sum 根本不是一个好的签名功能,但它可以证明原理。 ↩︎ 保持更新我的博客文章和项目 - 注册我的时事通讯。 🚀