【问题标题】:Can SAMLCredential.getRemoteEntityID() be trusted?SAMLCredential.getRemoteEntityID() 可以信任吗?
【发布时间】:2016-10-24 04:21:44
【问题描述】:

我正在一个配置有多个身份提供者的应用程序中实现 Spring SAML。我的 IdP 元数据配置有多个 ExtendedMetadataDelegate,每个 IdP 都有一个 HTTPMetadataProvider 和别名。该应用通过扩展SAMLContextProvider 来选择使用哪个提供程序,方法与this 类似。

当 IdP 发送授权时,我的应用需要知道它来自哪个 IdP(不同的提供商有不同的安全授权)。我按照docs 的建议执行此操作,并使用自定义SAMLUserDetailsServiceSAMLCredential.getRemoteEntityID() 来确定哪个IdP 提出了请求。

我的问题是,我可以依靠 remoteEntityID 来识别提供者吗?如果一个 IdP 提供商更新其元数据以包含不同的 entityID 甚至“伪造的”与另一个提供商相同的 entityID 怎么办?使用我们定义的 peer 别名不是更好吗?

我是 SAML 的新手,所以我对某些基本概念的理解很可能不正确,我只是想确保我没有使用此配置打开安全漏洞。

【问题讨论】:

    标签: spring spring-security spring-saml


    【解决方案1】:

    这是个好问题。我不知道答案,所以我试了一下。

    我在我的测试环境中有一个 MS ADFS 和 SpringSAML 项目的实例,其中配置了服务提供者和身份提供者(用于 ADFS)。在我的自定义 SAMLUserDetailsService 中,我使用 SAMLCredential.getRemoteEntityID() 来确定请求来自哪个 IDP。

    我成功登录,然后更改了 ADFS EntityID 的名称,然后再次尝试登录。这导致日志中出现 AuthNResponse;SUCCESS;127.0.0.1 消息,但浏览器中出现错误。我在 UserDetailService 中启用调试的情况下再次运行它,发现请求在到达 UserDetailService 之前在某处失败,但是,我在日志中没有看到任何错误消息。

    为了回答您的问题(也许其他人可以更明确地回答),SpringSAML 会适当地处理这种情况,因为它会出错。它不是在日志中没有错误消息。我认为这是因为这是一个不寻常的场景,或者只是一个错误。

    至于伪造另一个身份提供者的实体 ID,SAML 请求是经过签名的,因此任何试图伪造和 IDP 消息的人也必须有权访问他们的私钥。

    最后,别名不在请求中,因此不能用于区分 IDP。

    【讨论】:

    • 测试的好主意。很高兴知道它给出了一个错误。您是否使用 HTTPMetadataProvider 加载您的 IdP 元数据?'
    • 我仍然认为在这种(可能非常不寻常的)场景下仍然可以伪造请求。鉴于我们信任多个 IdP(可能彼此敌对),如果一个人试图通过更改他们自己的元数据(由 HTTPMetadataProvider 在我这边重新加载)来伪造另一个提供商的 entityID,那么我们将有多个元数据条目相同的 entityID(也许不可能?)。来自任一 IdP 的请求仍会被签署和接受,因为我们都信任它们。唯一确定的方法就是尝试一下!
    • 对我来说,根据提供者定义的 id(即 entityID)做出授权决策似乎是不安全的,因为我们可以通过基于我们定义的 id(即别名)的决策轻松消除任何风险。
    • 我已经实现了一个自定义 AbstractReloadingMetadataProvider 从数据库加载元数据,这样我就可以动态添加/删除 IDP。不能使用别名。 SAML 规范不包括 SAML 请求的内部定义的别名,因此根据设计,唯一的选择是实体 ID。请求的签名确保它不能被伪造,并且请求将在到达详细服务之前失败。上面提到的测试模拟了某人将他们的实体 ID 更改为另一个 IDP,并且在足够远的工作之前失败了。希望这会有所帮助。
    猜你喜欢
    • 2011-08-15
    • 1970-01-01
    • 2012-07-20
    • 1970-01-01
    • 2016-09-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-14
    相关资源
    最近更新 更多