【问题标题】:How SAML Assertion/verification works with X509 public keySAML 断言/验证如何与 X509 公钥一起使用
【发布时间】:2016-08-03 14:54:40
【问题描述】:

在我的 asp.net MVC 网站中,我实现了 SSO,其中 IDP/ADFS 发送 SAML 响应并验证 SAML 令牌以允许用户访问该网站。我正在使用自定义代码(使用 System.IdentityModel.dll 和 System.IdentityModel.Services.dll 库来验证 SAML 响应和令牌,而不是让 .net 框架使用 web.config 设置进行检查)。

到目前为止,代码似乎运行良好,但由于我是该域的新手,因此担心黑客能够通过正确构建的 SAML 响应绕过验证。最近尝试了SAML令牌生成部分,发现智能生成令牌可以绕过我的令牌验证码。

在高层次上,这是我验证令牌所做的:

  1. 从请求中提取安全令牌。
  2. 通过使用提供的 X509 公钥(存在于 SAML 响应中)检查摘要值来验证令牌是否有效且未被触及
    1. 提取用户的声明/身份并允许访问。

我担心的是,如果黑客创建 SAML 令牌(如我自己的令牌生成器代码)并在响应中添加公钥并将其发布到我的网站,我的网站将成功验证响应,因为响应本身格式正确并签字。这是一个有效的担忧吗?我缺少一些基本验证来处理这种情况? 我可以考虑以下选项来降低风险:

  1. 检查 URLReferrer 并确保 SAML 响应是从预期实体发布的。我不确定是否有办法操纵 URLReferrer。

  2. 避免使用响应中存在的公钥来验证摘要值。我可以将 X509 证书存储在我的一端并使用它来验证响应。黑客将无法使用相同的证书签署响应,因为他没有私钥。如果这是正确的方法,有人可以建议我如何指示“tokenhandler”忽略响应中存在的公钥并使用显式公钥吗?

  3. 有没有一种方法可以让我对 IDP 进行后端调用,可以进行 Web 服务调用,并检查我的网站收到的令牌是否确实由 IDP 生成?

由于我是新手,我可能会错过基本的 SAML 验证概念。因此,请让我知道我的担忧是否合理。 这是我用来验证响应的示例代码。

public ActionResult SAMLAssert()
    {
        var fam = new WSFederationAuthenticationModule();
        var request = this.HttpContext.Request;

        // Get the security token from the SAML response
        var securityToken = fam.GetSecurityToken(request);

        var config = new SecurityTokenHandlerConfiguration
        {
            CertificateValidator = X509CertificateValidator.None,
            IssuerNameRegistry = new CustomIssuerNameRegistry(),

        };
        config.AudienceRestriction.AudienceMode = AudienceUriMode.Never;

        var tokenHandler = new Saml2SecurityTokenHandler
        {
            CertificateValidator = X509CertificateValidator.None,
            Configuration = config,

        };

        //// validate the token and get the ClaimsIdentity out of it
        var identity = tokenHandler.ValidateToken(securityToken);
        bool isSuccess = identity[0].IsAuthenticated;

        // Code to retrieve the claims/user information from the token
        //....
        return View();
    }

这是自定义的“IssuerNameRegistry”。

public class CustomIssuerNameRegistry : IssuerNameRegistry
    {
        public override string GetIssuerName(SecurityToken securityToken)
        {
            X509SecurityToken x509Token = securityToken as X509SecurityToken;

            return x509Token.Certificate.Subject;
        }


    }

我怀疑自定义类是有问题的部分,因为它没有进行任何验证。

【问题讨论】:

    标签: c# saml-2.0 adfs x509certificate2 ws-federation


    【解决方案1】:
    1. 我认为您不应该检查引荐来源网址值。它很容易被欺骗。

    2. IdP 使用其私钥对发送给您的响应进行签名。攻击者只是无权访问此私钥。因此,如果攻击者想要欺骗签名,他将需要使用自己的证书并将他的公钥放入令牌中。虽然您是对的,验证代码使用嵌入式公钥来验证签名,但 AFAICT 它还做了一件事:检查我们的机器是否信任公钥。可以通过将公钥添加到您的 Windows 证书存储区 -> TrustedPeople 来建立此处的信任。我没有所有代码来验证这一点,但它应该以这种方式工作,或者它应该为您提供一种方法来做到这一点。 如果您可以完全控制 IdP,替代嵌入式公钥(又名 X509Data),您可以仅使用密钥名称、主题名称、指纹。但是它们提供了多少安全性以及如何实施不在这个问题的范围内。

    3. 不,SAML 协议并非旨在以这种方式工作。最接近这一点的是使用 Artifact 流,其中 IdP 仅向您的应用程序返回一个 Artifact,并且它需要向 IdP 发出 ArtifactResolve 请求以获取实际响应。见What is the purpose of a SAML Artifact?。但是你仍然需要验证收到的响应的签名。

    【讨论】:

      猜你喜欢
      • 2018-09-07
      • 1970-01-01
      • 2018-08-22
      • 1970-01-01
      • 2016-02-03
      • 2019-05-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多