SAML是一种使用非常广泛的单点登录协议,如果您运行SAML服务器并与许多其他站点集成,那么您几乎可以肯定使用了不安全的设置。SAML安全性的最大威胁不是奇怪的XML边缘案例或黑客窃取您的签名密钥,而是允许您的用户登录您认为他们无权访问的应用程序的低质量第三方实现。为确保SAML断言仅适用于正确的应用程序,请为每个应用程序或服务提供商使用唯一的签名密钥。这个问题不是SAML独有的,签名的JWT和SSO的其他用途(例如OIDC中的那些)也可能遇到类似的缺乏令牌验证的问题。SAML是如何工作的?在高层次上,SAML是一种使用两个系统之间的浏览器间通信来登录用户的方法,否则这两个系统将无法相互通信。当用户想要登录到他们最喜欢的SaaS时,SaaS应用程序(SP或服务提供商)会向您的IDP发送一些有关登录请求的数据。这包括唯一的请求ID和您尝试访问的原始页面等数据。理论上,身份验证请求可以指定IDP应该返回什么类型的用户名和名称等字段,但实际上这会被忽略。这些请求也可以签名,但大多数时候它实际上会在SP轮换其密钥时破坏一些东西。安全性没有什么好处,因为在任何现代系统中,SAML交换都是通过TLS进行的。一旦您的IDP收到身份验证请求,IDP将验证您是否已登录(可能是密码,可能是客户端证书),然后签署断言。断言是SP将验证并用于记录您的内容。然后您的IDP将此断言发送回SP。SP验证密码签名,验证断言应该发送给特定的SP,并提取相关的用户名和其他字段。现在,你可以看到所有你想要的图片!那个签名密钥听起来很吓人!您的直觉可能是不惜一切代价保护该密钥。密钥值得保护,但对您的SAMLIDP安全性的最大可信威胁不是拥有您的SAML服务器的攻击者。攻击SAML的方法攻击SAML的方法有很多种!虽然唯一的签名密钥可以解决其中的一些问题,但它不是灵丹妙药。观众限制问题这是我在这篇文章中关注的重点,稍后我将更详细地讨论它。不出所料,唯一的签名密钥解决了这类问题。被盗的IDP签名密钥:确实,有权访问您的IDP的人可以获得签名密钥的副本,并以任何人身份登录您与之集成的任何网站。如果那是您关心的威胁,那么仅提供签名预言的硬件支持密钥是正确的防御措施。XML和XML安全库:如果可以,您应该使用内存安全库。也就是说,它对第三方断言验证没有实际影响,如果您使用唯一的签名密钥,您的安全状况也不会改变。XML处理问题XML安全是一种内联签名格式,出现于2000年代初期,当时没有人要求它,而且需要它的人更少。但是随着越来越多的人使用它,问题就出现了。其中包括忽略用户名中的XML注释,签名格式本身忽略影响XML解析器的注释,以及不检查您验证的签名是否确实涵盖了您信任的签名。的所有数据。您可以通过使用唯一的签名密钥来减少这些问题的范围。你只需要关心单个应用程序的内部权限,而不是让用户登录你集成的任何服务(授权与否)。解决方案的核心问题是缺少受众限制验证,换句话说,SP不检查断言是否反对它。SAML的设计理念是您的IDP将只有一个签名密钥,您可以将其分发给与之集成的每个人。考虑到SAML的学术背景,它应该是一个协作协议,组织之间有密切的合作。现代企业SAML忽略了所有这些有趣的特性,因为它们是巨大的安全和配置噩梦。当您的IDP签署断言时,它包含两个供SP验证的字段:SP的实体ID和断言发送到的URL。SP可以默默地忽略这些字段,您对此无能为力。作为负责签名密钥的IDP,您如何保护自己免受不可避免的弱SP攻击?与依赖协议的某些部分相比,处理一堆签名密钥的唯一可扩展方法是强制您的断言仅在一个有效的SP上有效,并且每个SP都有一个唯一签名的密钥。这是可行的,因为几乎每个SAMLSP实现都由三部分组成。他们将从请求中提取用户名,验证断言中的签名,并拒绝无效的断言签名,其他一切都应该被认为是可选的。虽然SP可以忽略你的签名,但它非常容易测试,而且这种事情很容易被漏洞赏金报告者发现。与更深奥的观众限制测试不同,这里不涉及复杂性。你如何管理这么多钥匙?过去,我通过编写一堆Ruby来自动生成相关的XML来处理每个SP的唯一签名密钥,从而为Shibboleth管理了多个密钥。每次我遇到另一个错误处理断言的SP时,我都会感谢为减少我们不得不担心的这个问题所做的努力。在理想情况下,我们不会使用SAML。SAML是一种繁琐的协议,它允许您使用身份验证内联签名创建身份提供者的网状网络,其中XML中的空格决定签名是否有效。但SAML将与OAuth2.0和不完善的OIDC一起保留下来。鉴于SAML是事实上的企业单点登录协议,我们将忽略它。如果您的IDP不支持此功能(见下文),您应该向他们提出功能请求!这是您的IDP应该支持的重要安全控制。如果您的IDP确实支持此功能,请为您的新应用程序发布一个per-sp签名密钥。迁移具有旧证书的应用程序需要大量工作,但如果您有特别敏感的应用程序,则值得这样做。所有SaaSIDP都应该在没有任何用户干预的情况下生成每个应用程序的签名密钥,并且默认情况下,每个SP密钥被大量使用以悄悄地提高与这些提供商签订的每份合同的企业安全性。截至2020年3月,唯一拥有此权限的提供商是AzureAD。自托管IDP应确保他们支持每个SP签名密钥并具有启用此功能的文档。理想情况下,共享签名密钥的配置不太明显,因此管理员默认选择每个SP签名密钥。虽然最终由SSO管理员做出正确的SSO选择,但作为安全行业,我们有责任轻松做出正确的选择。IDP支持多个签名密钥没有实施指南,最佳实践也无济于事。以下是截至2020年3月我测试过的各种主要IDP(包括SaaS和自托管选项)的列表。如果您首选的IDP不在此列表中或输入错误,请联系我们。1.AzureAD-SaaSAAzureAD自动为每个“企业应用程序”生成一个新密钥,并且无法在控制台中的应用程序之间共享证书。您可以手动上传自己的证书和私钥,但这并不容易,我不鼓励这样做,AzureAD应该是所有其他SaaSIDP的模型。2.Shibboleth-Java(self-hosted)你必须写很多XML才能让它工作,如果你花几个小时绞尽脑汁配置SpringXML,你应该没有问题。我已经包括了基本需求。要点是您需要创建单独的签名凭据,将签名凭据包含在安全配置中,然后从单独的SP引用该安全配置。此外,我确实喜欢Shibboleth完全是java,即没有内存损坏!,在您自己的服务器上本地运行,并且具有非常符合标准的方法,减少了受奇怪的XML问题影响的可能性。conf/relying-party.xml的示例配置(Shibboleth文档):
...
