.NET 4.5中的默认安全协议

与支持最多TLS 1.2的服务器通信的默认安全协议是什么?默认情况下,.NET将选择服务器端支持的最高安全协议,还是我必须显式地添加这行代码:

System.Net.ServicePointManager.SecurityProtocol =
SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;

除了代码更改之外,是否有方法更改此默认值?

最后,.NET 4.0是否只支持到TLS 1.0?例如,我必须将客户端项目升级到4.5以支持TLS 1.2

我的动机是在客户端删除对SSLv3的支持,即使服务器支持它(我已经有一个powershell脚本在机器注册表中禁用它),并支持服务器支持的最高TLS协议。

< >强更新: 查看.NET 4.0中的ServicePointManager类,我没有看到TLS 1.01.1的枚举值。在这两个.NET 4.0/4.5中,默认值是SecurityProtocolType.Tls|SecurityProtocolType.Ssl3。希望这个默认值不会因为禁用注册表中的SSLv3而被破坏

然而,我已经决定必须将所有应用程序升级到.NET 4.5,并显式地将SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;添加到所有应用程序的所有引导代码中。

这将使对各种api和服务的出站请求不降级到SSLv3,并且应该选择TLS的最高级别。

这种方法听起来合理还是过份?我有许多应用程序要更新,我想在未来证明它们,因为我听说甚至TLS 1.0可能在不久的将来被一些提供者弃用。

作为一个向api发出出站请求的客户端,在注册表中禁用SSL3会对.NET框架产生影响吗?我看到默认情况下,TLS 1.1和1.2没有启用,我们必须通过注册表启用它吗?http://support.microsoft.com/kb/245030

经过一番研究,我相信注册表设置不会有任何影响,因为它们适用于IIS(服务器子密钥)和浏览器(客户端子密钥)。

对不起,这篇文章变成了多个问题,然后是“可能”的答案。

424713 次浏览

这两个。net 4.0/4.5中的默认System.Net.ServicePointManager.SecurityProtocolSecurityProtocolType.Tls|SecurityProtocolType.Ssl3

.NET 4.0支持最多TLS 1.0,而.NET 4.5支持最多TLS 1.2

然而,如果在相同的环境中安装了.NET 4.5,针对.NET 4.0的应用程序仍然可以支持最多TLS 1.2.NET 4.5安装在.NET 4.0之上,取代System.dll

我已经通过观察在fiddler4流量中设置的正确安全协议,并手动设置.NET 4.0项目中的枚举值来验证这一点:

ServicePointManager.SecurityProtocol = (SecurityProtocolType)192 |
(SecurityProtocolType)768 | (SecurityProtocolType)3072;

参考:

namespace System.Net
{
[System.Flags]
public enum SecurityProtocolType
{
Ssl3 = 48,
Tls = 192,
Tls11 = 768,
Tls12 = 3072,
}
}

如果你试图在只安装了.NET 4.0的环境上进行黑客攻击,你会得到异常:

Unhandled Exception:系统异常。NotSupportedException:请求的安全协议不支持。 在System.Net.ServicePointManager。set_SecurityProtocol (SecurityProtocolType v 价值)< / p >

然而,我不建议这个“黑客”,因为未来的补丁等可能会打破它

因此,我决定删除对SSLv3的支持的最佳途径是:

  1. 将所有应用程序升级到.NET 4.5
  2. 在boostrapping代码中添加以下内容以覆盖默认值并在未来证明它:

    < p > <代码> System.Net.ServicePointManager。SecurityProtocol = SecurityProtocolType。Tls |安全协议类型。Tls11 | SecurityProtocolType.Tls12;

  3. . tls12

*如果这个黑客是错误的,有人纠正我,但初步测试我看到它工作

您可以覆盖以下注册表的默认行为:

Key  : HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v4.0.30319
Value: SchUseStrongCrypto
Type: REG_DWORD
Data : 1

而且

Key  : HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\.NETFramework\v4.0.30319
Value: SchUseStrongCrypto
Type: REG_DWORD
Data : 1

有关详细信息,请参见ServicePointManager的实现

For Key: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft.NETFramework\v4.0.30319 取值范围:SchUseStrongCrypto

您必须将该值设置为1。

在经历了一番挣扎之后,注册表更改机制为我工作了。实际上,我的应用程序是32位的。所以我必须改变路径下的值。

HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft.NETFramework\v4.0.30319

值类型需要为DWORD且值大于0。最好使用1。注册表设置以获得。net 4.0应用程序使用TLS 1.2,前提是机器中安装了。net 4.5。

创建一个扩展名为.reg的文本文件,内容如下:

Windows Registry Editor Version 5.00


[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v4.0.30319]
"SchUseStrongCrypto"=dword:00000001


[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\.NETFramework\v4.0.30319]
"SchUseStrongCrypto"=dword:00000001

或从以下来源下载:

https://gist.githubusercontent.com/dana-n/174759ce95e04fa1a8fd691f633ccbd3/raw/NET40-Enable-TLS-1_2.reg

双击安装…

我发现,当我只指定TLS 1.2时,它仍然会协商到1.1。 System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; < / p >

我已经在全局中指定了这一点。我的。net 4.5 web应用程序的Asax启动方法。

一些在其他答案上留下评论的人注意到,将System.Net.ServicePointManager.SecurityProtocol设置为特定的值意味着你的应用程序将无法利用未来的TLS版本,这些TLS版本可能在未来的。net更新中成为默认值。与其指定一个固定的协议列表,不如执行以下操作:

适用于。net 4.7或更高版本,不设置System.Net.ServicePointManager.SecurityProtocol。默认值(SecurityProtocolType.SystemDefault)将允许操作系统使用它所知道的和已配置的任何版本,包括应用程序创建时可能不存在的任何新版本。

对于。net框架的早期版本,你可以打开或关闭你知道和关心的协议,让任何其他协议保持原样。

启用TLS 1.1和TLS 1.2而不影响其他协议:

System.Net.ServicePointManager.SecurityProtocol |=
SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;

注意使用|=来打开这些标志而不关闭其他标志。

关闭SSL3而不影响其他协议。

System.Net.ServicePointManager.SecurityProtocol &= ~SecurityProtocolType.Ssl3;
如上所述,硬编码ServicePointManager.SecurityProtocol或显式SchUseStrongCrypto键的替代方法 您可以告诉.NET使用SystemDefaultTlsVersions键
来使用默认的channnel设置 例如:< / p >
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v4.0.30319] "SystemDefaultTlsVersions"=dword:00000001
[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\.NETFramework\v4.0.30319] "SystemDefaultTlsVersions"=dword:00000001

为了完整起见,这里有一个Powershell脚本来设置前面提到的注册表项:

new-itemproperty -path "HKLM:\SOFTWARE\Microsoft\.NETFramework\v4.0.30319" -name "SchUseStrongCrypto" -Value 1 -PropertyType "DWord";
new-itemproperty -path "HKLM:\SOFTWARE\Wow6432Node\Microsoft\.NETFramework\v4.0.30319" -name "SchUseStrongCrypto" -Value 1 -PropertyType "DWord"
当我的客户将TLS从1.0升级到1.2时,我遇到了问题。 我的应用程序使用。net framework 3.5和运行在服务器上。所以我用这种方式来修复它:

  1. 修复程序

在调用HttpWebRequest.GetResponse()之前添加以下命令:

ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls | SecurityProtocolTypeExtensions.Tls11 | SecurityProtocolTypeExtensions.Tls12;

通过添加2个新类扩展2个dll: System。网络和系统。安全性。身份验证

    namespace System.Net
{
using System.Security.Authentication;
public static class SecurityProtocolTypeExtensions
{
public const SecurityProtocolType Tls12 = (SecurityProtocolType)SslProtocolsExtensions.Tls12;
public const SecurityProtocolType Tls11 = (SecurityProtocolType)SslProtocolsExtensions.Tls11;
public const SecurityProtocolType SystemDefault = (SecurityProtocolType)0;
}
}


namespace System.Security.Authentication
{
public static class SslProtocolsExtensions
{
public const SslProtocols Tls12 = (SslProtocols)0x00000C00;
public const SslProtocols Tls11 = (SslProtocols)0x00000300;
}
}
  1. 更新Microsoft批处理

批量下载:

  • windows 2008 R2操作系统:windows6.1-kb3154518-x64.msu
  • For windows 2012 李R2: windows8.1-kb3154520-x64.msu < / >

下载批量和更多细节,你可以在这里看到:

https://support.microsoft.com/en-us/help/3154518/support-for-tls-system-default-versions-included-in-the-.net-framework-3.5.1-on-windows-7-sp1-and-server-2008-r2-sp1

这个问题的最佳解决方案似乎是至少升级到。net 4.6或更高版本,它将自动选择强协议和强密码。

如果你不能升级到。net 4.6,建议设置

System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType。Tls11 | SecurityProtocolType.Tls12;

使用注册表设置:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft.NETFramework\v4.0.30319 - SchUseStrongCrypto = DWORD的1 HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft.NETFramework\v4.0.30319 - SchUseStrongCrypto = DWORD of 1

导致使用TLS 1.0和强密码以外的东西。

在我的测试中,只有Wow6432Node中的设置有任何不同,尽管我的测试应用程序是为任何CPU构建的。

以下代码将:

  • 打印启用的协议
  • 打印可用协议
  • 如果平台支持TLS1.2,则启用TLS1.2,如果一开始没有启用TLS1.2
  • 如果启用了SSL3,则禁用它
  • 打印最终结果

常量:

  • 48是SSL3
  • 192是TLS1
  • 768是TLS1.1
  • 3072是TLS1.2

其他协议不受影响。这使得它与未来的协议(Tls1.3等)兼容。

代码

// print initial status
Console.WriteLine("Runtime: " + System.Diagnostics.FileVersionInfo.GetVersionInfo(typeof(int).Assembly.Location).ProductVersion);
Console.WriteLine("Enabled protocols:   " + ServicePointManager.SecurityProtocol);
Console.WriteLine("Available protocols: ");
Boolean platformSupportsTls12 = false;
foreach (SecurityProtocolType protocol in Enum.GetValues(typeof(SecurityProtocolType))) {
Console.WriteLine(protocol.GetHashCode());
if (protocol.GetHashCode() == 3072){
platformSupportsTls12 = true;
}
}
Console.WriteLine("Is Tls12 enabled: " + ServicePointManager.SecurityProtocol.HasFlag((SecurityProtocolType)3072));




// enable Tls12, if possible
if (!ServicePointManager.SecurityProtocol.HasFlag((SecurityProtocolType)3072)){
if (platformSupportsTls12){
Console.WriteLine("Platform supports Tls12, but it is not enabled. Enabling it now.");
ServicePointManager.SecurityProtocol |= (SecurityProtocolType)3072;
} else {
Console.WriteLine("Platform does not supports Tls12.");
}
}


// disable ssl3
if (ServicePointManager.SecurityProtocol.HasFlag(SecurityProtocolType.Ssl3)) {
Console.WriteLine("Ssl3SSL3 is enabled. Disabling it now.");
// disable SSL3. Has no negative impact if SSL3 is already disabled. The enclosing "if" if just for illustration.
System.Net.ServicePointManager.SecurityProtocol &= ~SecurityProtocolType.Ssl3;
}
Console.WriteLine("Enabled protocols:   " + ServicePointManager.SecurityProtocol);

输出

Runtime: 4.7.2114.0
Enabled protocols:   Ssl3, Tls
Available protocols:
0
48
192
768
3072
Is Tls12 enabled: False
Platform supports Tls12, but it is not enabled. Enabling it now.
Ssl3 is enabled. Disabling it now.
Enabled protocols:   Tls, Tls12

我在. net 4.5.2下运行,我对这些答案都不满意。由于我正在谈论的是一个支持TLS 1.2的系统,并且看到SSL3、TLS 1.0和TLS 1.1都已损坏,使用起来不安全,所以我不想启用这些协议。在. net 4.5.2下,SSL3和TLS 1.0协议在默认情况下都是启用的,我可以通过检查ServicePointManager.SecurityProtocol在代码中看到。在。net 4.7中,有新的SystemDefault协议模式,它显式地将协议的选择交给操作系统,我认为依赖注册表或其他系统配置设置将是合适的。然而,. net 4.5.2似乎不支持这一点。为了编写向前兼容的代码,即使将来TLS 1.2不可避免地被破坏,或者当我升级到。net 4.7+并将更多的责任交给操作系统选择适当的协议时,也能做出正确的决定,我采用了以下代码:

SecurityProtocolType securityProtocols = ServicePointManager.SecurityProtocol;
if (securityProtocols.HasFlag(SecurityProtocolType.Ssl3) || securityProtocols.HasFlag(SecurityProtocolType.Tls) || securityProtocols.HasFlag(SecurityProtocolType.Tls11))
{
securityProtocols &= ~(SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls | SecurityProtocolType.Tls11);
if (securityProtocols == 0)
{
securityProtocols |= SecurityProtocolType.Tls12;
}
ServicePointManager.SecurityProtocol = securityProtocols;
}

这段代码将检测何时启用了已知的不安全协议,在本例中,我们将删除这些不安全协议。如果没有其他明确的协议,我们将强制启用TLS 1.2,这是目前。net支持的唯一已知安全协议。这段代码是向前兼容的,因为它将考虑未来添加的它不知道的新协议类型,并且它还将与。net 4.7中的新SystemDefault状态很好地配合,这意味着我将来不必重新访问这段代码。我强烈建议采用这样的方法,而不是无条件地硬编码任何特定的安全协议状态,否则当TLS 1.2不可避免地被破坏时,您将不得不重新编译并用新版本替换客户端,以便升级到新的安全协议,或者更有可能的是,您将不得不让现有的不安全协议在您的服务器上打开数年,使您的组织成为攻击的目标。

微软最近发布了相关的最佳实践。https://learn.microsoft.com/en-us/dotnet/framework/network-programming/tls

总结

目标。net Framework 4.7,删除任何设置安全协议的代码,这样操作系统将确保您使用最安全的解决方案。

注意:您还需要确保支持TLS的最新版本&在操作系统上启用。

OS                          TLS 1.2 support


Windows 10                  \_ Supported, and enabled by default.
Windows Server 2016         /
Windows 8.1                 \_ Supported, and enabled by default.
Windows Server 2012 R2      /
Windows 8.0                 \_ Supported, and enabled by default.
Windows Server 2012         /
Windows 7 SP1               \_ Supported, but not enabled by default*.
Windows Server 2008 R2 SP1  /
Windows Server 2008         -  Support for TLS 1.2 and TLS 1.1 requires an update. See Update to add support for TLS 1.1 and TLS 1.2 in Windows Server 2008 SP2.
Windows Vista               -  Not supported.


* To enable TLS1.2 via the registry see https://learn.microsoft.com/en-us/windows-server/security/tls/tls-registry-settings#tls-12


Path: HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Server


Property: Enabled
Type: REG_DWORD
Value: 1


Property: DisabledByDefault
Type: REG_DWORD
Value: 0


Path: HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Client


Property: Enabled
Type: REG_DWORD
Value: 1


Property: DisabledByDefault
Type: REG_DWORD
Value: 0

有关更多信息和旧框架,请参考MS链接。

根据.NET框架的传输层安全(TLS)最佳实践: 为了确保. net Framework应用程序保持安全,TLS版本应该硬编码。相反,设置注册表项:SystemDefaultTlsVersions 而且 SchUseStrongCrypto:

Windows Registry Editor Version 5.00


[HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\.NETFramework\v2.0.50727]
"SystemDefaultTlsVersions"=dword:00000001
"SchUseStrongCrypto"=dword:00000001


[HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\.NETFramework\v4.0.30319]
"SystemDefaultTlsVersions"=dword:00000001
"SchUseStrongCrypto"=dword:00000001


[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v2.0.50727]
"SystemDefaultTlsVersions"=dword:00000001
"SchUseStrongCrypto"=dword:00000001


[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v4.0.30319]
"SystemDefaultTlsVersions"=dword:00000001
"SchUseStrongCrypto"=dword:00000001
如果您可以使用。net 4.7.1或更新版本,它将使用TLS 1.2作为基于操作系统功能的最低协议。 根据微软的建议:

To ensure .NET Framework applications remain secure, the TLS version should not be hardcoded. .NET Framework applications should use the TLS version the operating system (OS) supports.

有两种可能的情况,

  1. 如果你的应用程序运行在。net framework 4.5或更低版本上,你可以很容易地将新代码部署到产品中,那么你可以使用下面的解决方案。

    你可以在调用api之前添加下面的代码行,

    ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; // .NET 4.5

  2. 如果您不能部署新代码,并且希望使用产品中存在的相同代码进行解析,那么您有两个选择。

选项1:

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v4.0.30319]
"SchUseStrongCrypto"=dword:00000001


[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\.NETFramework\v4.0.30319]
"SchUseStrongCrypto"=dword:00000001




然后创建一个扩展名为.reg的文件并安装。

注意:此设置将应用于注册表级别,适用于该机器上的所有应用程序,如果你想限制为单个应用程序,则可以使用Option 2

选项2:这可以通过改变配置文件中的一些配置设置来实现。 你可以在你的配置文件中添加其中任何一个

<runtime>
<AppContextSwitchOverrides value="Switch.System.Net.DontEnableSchUseStrongCrypto=false"/>
</runtime>

<runtime>
<AppContextSwitchOverrides value="Switch.System.Net.DontEnableSystemDefaultTlsVersions=false"
</runtime>