收到的 WCF 服务器证书的部分链验证失败

Posted

技术标签:

【中文标题】收到的 WCF 服务器证书的部分链验证失败【英文标题】:Partial Chain validation failure of received WCF server certificate 【发布时间】:2020-02-24 15:57:43 【问题描述】:

我们正在集成一项服务,该服务使用客户端证书来验证我们与供应商服务器之间的 https 连接。我们生成了一个 CSR,供应商向我们提供了一个 p7b 文件,其中包含 2 个中间证书和一个受信任的根证书。然后,我们使用来自 CSR 的私钥创建了一个 pfx 二进制文件(我们可以匹配证书和密钥,因此我们知道从那个角度来看它们是正确的)。

我们使用 Vault 来存储我们的相互身份验证证书,因此 pfx 没有安装到 Windows Server 2012r2 上。

在我们的客户端代码中,我们执行以下操作:

var myBinding = new WSHttpBinding();
myBinding.Security.Mode = SecurityMode.Transport;
myBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;

var client = new ServiceClient(myBinding, new EndpointAddress("https://example.org"));
client.ClientCredentials.ClientCertificate.Certificate = new X509Certificate2("cert.pfx", "****");
client.create(new model());

通过上述设置,我们会产生以下影响:

Windows 10 开发机器 - TLS 连接成功 Windows Server 2012r2 - TLS 连接失败

然后我们添加了一个验证回调:

ServicePointManager.ServerCertificateValidationCallback += ValidateServerCertificate;

private static bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)

   // ...

此时sslPolicyErrorsSystem.Net.Security.SslPolicyErrors.RemoteCertificateChainErrors

如果我们尝试构建自己的 SSL 链:

using (var chain = new X509Chain())

  var flag = X509VerificationFlags.NoFlag;
  chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;
  chain.ChainPolicy.VerificationFlags = flag;

  var primaryCert = new X509Certificate2(certificate);

  var n = chain.Build(primaryCert);
  Console.WriteLine($"Flag: flag - string.Join(",", chain.ChainStatus.Select(x => $"x.StatusInformation.Trim() (x.Status)"))");

  return n;

我们得到了打印 - Flag: NoFlag - A certificate chain could not be built to a trusted root authority. (PartialChain)

所以我们将标志更改为X509VerificationFlags.AllowUnknownCertificateAuthority

这样做会导致证书链得到正确验证。

我们的问题是:

    我们在不同的机器上会产生不同的影响,因此我们的结论是 Win 10 对其检查没有那么严格。 Server 2012r2有什么理由拒绝这个链吗?

    如果我们使用验证标志X509VerificationFlags.AllowUnknownCertificateAuthority会不会有安全问题?

    我们可以在客户端的设置中设置这个标志,还是它必须是验证回调的一部分?

【问题讨论】:

【参考方案1】:

所以我们的结论是 Win 10 的检查没有那么严格

这是不正确的。 Windows 客户端和 Windows Server 操作系统共享相同的加密代码 (CAPI2) 和配置。

如果我们使用验证标志X509VerificationFlags.AllowUnknownCertificateAuthority?会不会有任何安全问题

是的,这个标志为MITM 攻击打开了大门。

我们可以在客户端的设置中设置这个标志,还是它必须是验证回调的一部分?

您真正需要的是解决问题。该错误表明服务器证书不是由受信任的 CA 颁发的。此 CA(服务器 TLS 证书的颁发者)被开发机器信任,因为开发者信任此 CA(管理员已在受信任的根存储中安装了开发 CA 证书)。

如果您从供应商处收到 CA 证书,则它们也必须安装在 Windows Server 2012 盒子上。这将自动解决问题。

【讨论】:

开发和服务器机器运行相同的组策略,因此它们都具有相同的根证书。我们找不到它们之间的任何区别。有没有办法找到可能导致问题的证书? 根证书(来自供应商)很可能是在 Windows 10 机器上手动安装的。在两台机器上运行 cermgr.msc 并比较受信任的根 CA 存储中的证书。 我们的服务器似乎没有该实用程序 - 我们使用 mmc 进行比较。颁发者来自 DigiCert - 服务器和开发者在受信任的根 CA 存储中拥有所有相同的 DigiCert 证书。 对不起,有一个错字。正确的是certmgr.msc。我会仔细检查从 TLS 握手收到的证书是否是预期的(来自 DigiCert)。我怀疑您端的配置错误或从服务器收到的证书错误。 然后 Windows Server 2012 框中缺少一个或多个 DigiCert 中间 CA 证书。根没问题。您可以在 Windows 10 盒子上的 Intermediate CAs 证书存储中找到它们。你一定会发现不一样的。

以上是关于收到的 WCF 服务器证书的部分链验证失败的主要内容,如果未能解决你的问题,请参考以下文章

WCF 服务中的自定义客户端证书和用户名验证

WCF 客户端证书验证 + Windows 身份验证

证书申请失败-26

WCF与相互身份验证

WCF、安全和证书

WCF Rest 自托管证书安全服务返回 401 未经授权