.NET 4.5中的默认SecurityProtocol

Luk*_*ton 238 .net security ssl

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

System.Net.ServicePointManager.SecurityProtocol = 
SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
Run Code Online (Sandbox Code Playgroud)

除了代码更改之外,有没有办法更改此默认值?

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

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

更新: 查看ServicePointManager该类,.NET 4.0我看到没有枚举值TLS 1.01.1.两者都是.NET 4.0/4.5默认值SecurityProtocolType.Tls|SecurityProtocolType.Ssl3.希望SSLv3在注册表中禁用此默认值不会中断.

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

这将使各种apis和服务的出站请求不降级,SSLv3并应选择最高级别TLS.

这种方法听起来合理还是矫枉过正?我有很多应用程序要更新,我希望将来证明它们,因为我听说甚至TLS 1.0可能在不久的将来被某些提供商弃用.

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

经过一些调查后,我相信注册表设置将不会有任何影响,因为它们适用于IIS(服务器子项)和浏览器(客户端子项).

对不起,这篇文章变成了多个问题,接着是"可能"的答案.

Sco*_*ott 246

一些留下评论的人注意到,设置System.Net.ServicePointManager.SecurityProtocol为特定值意味着您的应用程序将无法利用将来可能成为.NET未来更新中的默认值的TLS版本.您可以改为打开或关闭您知道和关心的协议,而不是指定任何其他协议,而不是指定固定的协议列表.

要在不影响其他协议的情况下打开TLS 1.1和1.2:

System.Net.ServicePointManager.SecurityProtocol |= 
    SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
Run Code Online (Sandbox Code Playgroud)

注意|=用于打开这些标志而不关闭其他标志.

要在不影响其他协议的情况下关闭SSL3:

System.Net.ServicePointManager.SecurityProtocol &= ~SecurityProtocolType.Ssl3;
Run Code Online (Sandbox Code Playgroud)

  • 由于没有人在谈论放置此代码的位置,因此我成功将其放入Global.asax.cs的Application_Start中以用于我的ASP.NET MVC应用程序.我一直在寻找如何通过TLS1.2而不是TLS1.0发送我的SMTP请求.我还添加了&= ~SecurityProtocolType.Tls来关闭TLS 1.0 (12认同)
  • 这才是真正正确的答案.接受的答案将确保您的应用程序将始终关闭新的TLS版本,除非您返回并更新您的代码. (6认同)
  • @Gertsen不,这是一个按位或者,所以它只是在它们关闭时打开相应的位.如果这些位已经打开,则不会发生任何更改. (4认同)
  • 在PowerShell中,等效项是[Net.ServicePointManager] :: SecurityProtocol =([Net.ServicePointManager] :: SecurityProtocol -bor [Net.SecurityProtocolType] :: Tls11 -bor [Net.SecurityProtocolType] :: Tls12) RestMethod依赖于相同的基础.NET框架库。 (2认同)
  • 在VB中,等效项是“ Net.ServicePointManager.SecurityProtocol = Net.ServicePointManager.SecurityProtocol或Net.SecurityProtocolType.Tls12或Net.SecurityProtocolType.Tls12” (2认同)
  • 嗯,如果 SecurityProtocol 当前设置为 SecurityProtocolType.SystemDefault ,这是否有效? (2认同)
  • @Andrew,如果 SecurityProtocol 当前设置为 SecurityProtocolType.SystemDefault (这是 .Net 4.7 中的默认值),则设置 SecurityProtocol |= Tls11 | Tls12 将禁用 Tls13。所以“不影响其他协议”这句话在.Net 4.7中不再有效。 (2认同)
  • 否决是因为实际上你的代码使应用程序无法利用未来的协议,就像 @CoperNick 指出的那样。[Microsoft 建议不要对 System.Net.ServicePointManager.SecurityProtocol 的值进行硬编码](https://learn.microsoft.com/en-us/dotnet/framework/network-programming/tls)。 (2认同)

Luk*_*ton 182

System.Net.ServicePointManager.SecurityProtocol两个.NET中的默认值4.0/4.5都是SecurityProtocolType.Tls|SecurityProtocolType.Ssl3.

.NET 4.0以支持最高TLS 1.0同时.NET 4.5支持最多TLS 1.2

但是,应用程序目标.NET 4.0仍然可以支持多达TLS 1.2如果.NET 4.5安装在同一个环境中..NET 4.5安装在上面.NET 4.0,替换System.dll.

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

ServicePointManager.SecurityProtocol = (SecurityProtocolType)192 |
(SecurityProtocolType)768 | (SecurityProtocolType)3072;
Run Code Online (Sandbox Code Playgroud)

参考:

namespace System.Net
{
    [System.Flags]
    public enum SecurityProtocolType
    {
       Ssl3 = 48,
       Tls = 192,
       Tls11 = 768,
       Tls12 = 3072,
    }
}
Run Code Online (Sandbox Code Playgroud)

如果您在仅.NET 4.0安装的环境中尝试攻击,您将获得异常:

未处理的异常:System.NotSupportedException:不支持请求的安全协议.在System.Net.ServicePointManager.set_SecurityProtocol(SecurityProtocolType v alue)

但是,我不推荐这种"黑客",因为未来的补丁等可能会破坏它.*

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

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

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

*有人纠正我,如果这个黑客是错误的,但初步测试我认为它有效

  • 我不会低估这个答案,因为它确实提供了许多有用的信息,但实现硬编码协议版本并不是一个好主意,因为它会限制应用程序使用最佳可用加密,并可能导致安全问题.注册表更改以更改.Net的默认行为以实际支持现代协议是非常可取的.(但值得注意的是,注册表更改还会禁用SSL v3.) (15认同)
  • 我一直看到有人声称`.NET 4.5'默认为Tls12 - 但是你已经把它放在这里,但事实并非如此.它为您提供了将它用于`SecurityProtocol`的选项 (12认同)
  • 请参阅https://www.imperialviolet.org/2014/12/08/poodleagain.html"这似乎是一个很好的时刻,重申一切都不如TLS 1.2与AEAD密码套件密码破解." (6认同)
  • 在FW 4.6和4.7上,默认值为`SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12`根据https://support.microsoft.com/en-us/help/3069494/cannot-connect-to-a-server-by-using-the-servicepointmanager-or-sslstre (6认同)
  • @Mathew,通过查看"ServicePointManager.cs"的源代码,请参阅http://referencesource.microsoft.com/#System/net/System/Net/ServicePointManager.cs,d22ab7c467e5a788,references (3认同)
  • @AJHenderson如果.NET理智并且可以自动协商最高协议版本,则没有必要对其进行硬编码.在我的测试中,似乎没有 - 与.NET 4.5支持TLS1.1 +的服务器的连接使用默认设置失败. (2认同)
  • 这个正确的答案有一些重要的缺失,那就是在.NET 4.5+中,您需要在任何WebRequest调用之前设置SecurityProtocol如下所示.在此之前:`(HttpWebRequest)WebRequest.Create(url);` (2认同)

Jir*_*res 65

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

Key  : HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v4.0.30319 
Value: SchUseStrongCrypto
Type: REG_DWORD
Data : 1
Run Code Online (Sandbox Code Playgroud)

Key  : HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\.NETFramework\v4.0.30319
Value: SchUseStrongCrypto
Type: REG_DWORD
Data : 1
Run Code Online (Sandbox Code Playgroud)

有关详细信息,请参阅实施ServicePointManager.

  • @MikhailG恰恰相反.注册表更改是更好的方法.SChannel提供了底层协商的抽象,您希望应用程序使用支持的最高安全级别.在新协议发布且您的软件无法使用时,在软件中人为限制它会导致未来出现问题.如果有一个选项可以说只使用比软件中的给定协议更好,那将是很好的,但没有选项,但也没有阻止未来的版本工作.尽管如此,确实禁用了SSL v3. (12认同)
  • 命令行:`reg add HKLM\SOFTWARE\Microsoft\.NETFramework\v4.0.30319/v SchUseStrongCrypto/t REG_DWORD/d 1/reg:64`(和/或`/ reg:32`) (12认同)
  • 更改注册表看起来不是一个好的解决方案.如果应用程序想要支持TLS1,那么应用程序应该关注它.不是运行环境.否则,它可能会损害其他应用程序,或者因部署和升级您的应用程序而下台. (6认同)
  • @MikhailG:设置注册表不会阻止应用程序支持旧协议.它只更改默认值(包括截至目前的tls 1.0).此外,.Net 4.6+中的默认行为是使用强加密; 在这种情况下,此注册表项仅用作禁用强加密的方法. (6认同)

dan*_*ana 48

创建一个.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
Run Code Online (Sandbox Code Playgroud)

或者从以下来源下载它:

https://tls1test.salesforce.com/s/NET40-Enable-TLS-1_2.reg

双击安装......

  • 您提供的链接似乎有SSL证书问题. (3认同)
  • 最近应用的补丁https://support.microsoft.com/en-us/help/4019114/security-and-quality-rollup-for-the-net-framework-3-5-service-pack-1-4服务器导致我们的.net 4.5.2应用程序在https REST请求上失败.这些键解决了我们的问题. (2认同)

小智 19

我发现,当我只指定TLS 1.2时,它仍会向下协商到1.1. System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

我已经在我的.net 4.5 web应用程序的Global.asax启动方法中指定了这个.

  • Upvoted,因为这是唯一的答案,说明WHERE放置作为解决方案的代码行. (10认同)
  • 服务器上支持的安全协议是什么?我相信这也是因素,可能是1.1是服务器上的最新版本.www.passionatecoder.ca (2认同)

Joy*_*uru 14

经过斗争后,注册表更改机制对我有用.实际上我的应用程序运行为32位.所以我不得不改变路径下的值.

HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft.NETFramework\v4.0.30319
Run Code Online (Sandbox Code Playgroud)

值类型需要为DWORD且值大于0.请使用1.用于获取.Net 4.0应用程序的注册表设置使用TLS 1.2提供的.Net 4.5安装在机器中.


ger*_*ras 14

以下代码将:

  • 打印启用的协议
  • 打印可用协议
  • 如果平台支持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);
Run Code Online (Sandbox Code Playgroud)

产量

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
Run Code Online (Sandbox Code Playgroud)


Hie*_*ieu 13

当我的客户将TLS从1.0升级到1.2时,我遇到了问题.我的应用程序使用.net framework 3.5并在服务器上运行.所以我通过这种方式修复它:

  1. 修复程序

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

ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls | SecurityProtocolTypeExtensions.Tls11 | SecurityProtocolTypeExtensions.Tls12;
Run Code Online (Sandbox Code Playgroud)

通过添加2个新类扩展2个DLL:System.Net和System.Security.Authentication

    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;
        }
    } 
Run Code Online (Sandbox Code Playgroud)
  1. 更新Microsoft批处理

下载批次:

  • 对于Windows 2008 R2:windows6.1-kb3154518-x64.msu
  • 对于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和服务器-2008-R2-SP1


Rog*_*ers 9

我在.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;
}
Run Code Online (Sandbox Code Playgroud)

此代码将检测何时启用已知的不安全协议,在这种情况下,我们将删除这些不安全的协议.如果没有其他显式协议,我们将强制启用TLS 1.2,作为.NET此时唯一已知的安全协议.这段代码是向前兼容的,因为它将考虑将来不知道将要添加的新协议类型,并且它也将与SystemDefault.NET 4.7中的新状态一致,这意味着我不需要重新编写代码 - 将来访问此代码.我强烈建议采用这样的方法,而不是无条件地对任何特定的安全协议状态进行硬编码,否则你将不得不重新编译并用新版本替换你的客户端,以便在TLS 1.2时升级到新的安全协议不可避免地会被打破,或者更有可能你不得不在服务器上打开现有的不安全协议多年,使你的组织成为攻击的目标.

  • 这个答案似乎是最深思熟虑的,但是,除非我遗漏了什么,否则我不确定每当 TLS 1.2 不可避免地崩溃时它是否会向前兼容。从我在 .NET 4.7.2 应用程序中看到的内容来看,`SecurityProtocolType.SystemDefault` 标志的计算结果为 `0`,因此使用 TLS 1.2 的按位包含或标志检查 `if (securityProtocols == 0)` 将始终包括 TLS 1.2,即使在它“中断”之后,对吗?这里不是锐利的射击。我真诚地试图找到最好的前进道路。 (2认同)

qbi*_*bik 6

为了完整起见,这里是一个设置上述注册表项的 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"
Run Code Online (Sandbox Code Playgroud)


Joh*_*van 5

Microsoft最近发布了有关此问题的最佳实践。 https://docs.microsoft.com/zh-cn/dotnet/framework/network-programming/tls

摘要

目标.Net Framework 4.7,删除所有设置SecurityProtocol的代码,因此操作系统将确保您使用最安全的解决方案。

注意:您还需要确保操作系统上支持并启用了最新版本的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://docs.microsoft.com/en-us/windows-server/security/tls/tls-registry-settings#tls-12 

    Path: HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS1.2\Server

        Property: Enabled
        Type: REG_DWORD
        Value: 1

        Property: DisabledByDefault 
        Type: REG_DWORD
        Value: 0

    Path: HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS1.2\Client

        Property: Enabled
        Type: REG_DWORD
        Value: 1

        Property: DisabledByDefault 
        Type: REG_DWORD
        Value: 0
Run Code Online (Sandbox Code Playgroud)

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

  • 问题是,如果您遵循准则(保持SecurityProtocolType.SystemDefault),则tls 1.1和tls 1.2在Windows 7和Server 2008上将无法运行,因为在未更改注册表的情况下,这些os中未对它们进行“启用”(无论如何)。这实际上使SystemDefault被设计破坏了。微软真的搞砸了这一件事。 (3认同)