首页 文章

.NET 4.5中的默认SecurityProtocol

提问于
浏览
207

与支持最多 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协议 .

Update: 查看 .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; 添加到所有应用程序的所有引导代码中 .

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

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

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

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

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

14 回答

  • 3

    创建一个扩展名为 .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://tls1test.salesforce.com/s/NET40-Enable-TLS-1_2.reg

    双击安装......

  • 2

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

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

  • 46

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

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

    值类型需要为DWORD且值大于0 . 更好使用1.
    Registry settings to get .Net 4.0 app use TLS 1.2 provided .Net 4.5 is installed in the machine.

  • 208

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

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

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

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

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

    System.Net.ServicePointManager.SecurityProtocol &= ~SecurityProtocolType.Ssl3;
    
  • 14

    .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 的环境中尝试攻击,您将获得异常:

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

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

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

    • 将所有应用程序升级到 .NET 4.5

    • 将以下内容添加到boostrapping代码以覆盖默认和将来的证明:

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

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

  • 9

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

    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
    

    有关详细信息,请参阅implementation of ServicePointManager .

  • 7

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

    • 修复程序

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

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

    通过添加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;
            }
        }
    
    • 更新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-and-server-2008-r2-sp1

  • 5

    以下代码将:

    • 打印启用的协议

    • 打印可用协议

    • 如果平台支持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
    
  • 2

    我对这些答案中的任何一个都很满意 . 正如我想要启用这些协议一样 . 在.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 状态一致,这意味着我赢了't have to re-visit this code in the future. I'强烈推荐采用这样的方法,而不是无条件地硬编码任何特定的安全协议状态,否则你必须在服务器上保持现有的不安全协议多年,这使你的组织成为攻击的目标 .

  • 175

    微软最近发布了围绕此的最佳实践 . https://docs.microsoft.com/en-us/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
    

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

  • 60

    为了完整起见,这是一个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"
    
  • -2

    如上所述,硬编码 ServicePointManager.SecurityProtocol 或显式 SchUseStrongCrypto 键的替代方法:
    您可以告诉.NET使用SystemDefaultTlsVersions键的默认SCHANNEL设置,
    例如 . :

    [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
    
  • 17

    解决此问题的最佳解决方案似乎是升级到至少.NET 4.6或更高版本,这将自动选择强协议以及强密码 .

    如果无法升级到.NET 4.6,请设置建议

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

    并使用注册表设置:

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

    导致使用TLS 1.0以外的其他内容和强密码 .

    在我的测试中,只有Wow6432Node中的设置有所不同,即使我的测试应用程序是为任何CPU构建的 .

  • 13

    对于密钥:HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft.NETFramework \ v4.0.30319值:SchUseStrongCrypto

    您必须将值设置为1 .

相关问题