ChatGPT解决这个技术问题 Extra ChatGPT

禁用 SSL 回退并仅将 TLS 用于 .NET 中的出站连接? (贵宾犬缓解)

我正在尝试减轻我们对 Poodle SSL 3.0 Fallback 攻击的脆弱性。我们的管理员已经开始禁用 SSL 以支持 TLS 用于与我们服务器的入站连接。我们还建议我们的团队在他们的网络浏览器中禁用 SSL。我现在正在查看我们的 .NET 代码库,它通过 System.Net.HttpWebRequest 启动与各种服务的 HTTPS 连接。我相信如果这些连接允许从 TLS 回退到 SSL,它们可能容易受到 MITM 攻击。这是我到目前为止所确定的。有人可以仔细检查一下以确认我是对的吗?这个漏洞是全新的,所以我还没有看到微软关于如何在 .NET 中缓解它的任何指导:

System.Net.Security.SslStream 类的允许协议支持 .NET 中的安全通信,通过 System.Net.ServicePointManager.SecurityProtocol 属性为每个 AppDomain 全局设置。 .NET 4.5 中此属性的默认值为 Ssl3 | Tls(虽然我找不到支持它的文档。) SecurityProtocolType 是一个带有 Flags 属性的枚举,所以它是这两个值的按位或。您可以使用以下代码行在您的环境中进行检查: Console.WriteLine(System.Net.ServicePointManager.SecurityProtocol.ToString());在您在应用程序中启动任何连接之前,这应该更改为 Tls,或者可能是 Tls12:System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Tls;重要提示:由于该属性支持多个按位标志,我假设 SslStream 在握手期间不会自动回退到其他未指定的协议。否则,支持多个标志的意义何在?

TLS 1.0 与 1.1/1.2 的更新:

根据 Google 安全专家 Adam Langley TLS 1.0 was later found to be vulnerable to POODLE if not implemented correctly 的说法,因此您应该考虑完全迁移到 TLS 1.2。

.NET Framework 4.7 及更高版本的更新:

正如下面 Prof Von Lemongargle 所提到的,从 .NET Framework 4.7 版开始,无需使用此 hack,因为默认设置将允许操作系统选择最安全的 TLS 协议版本。有关详细信息,请参阅 Transport Layer Security (TLS) best practices with the .NET Framework

关于上述第 2 点:请参阅 referencesource.microsoft.com/#System/net/System/Net/… SslProtocols " Default = Ssl3 | Tls"
@Dai Bok 现在默认是 SystemDefault 选项 docs.microsoft.com/en-us/dotnet/api/…
@MarwaAhmad 如果是这种情况,我链接中的源代码参考不反映默认 (48 | 192) 。如果设置为 none ( 0 ) ,它应该恢复为系统默认值。这对我来说很臭,我可能会在进行更改之前对其进行测试,因为它可能会导致配置错误......并关闭错误的 .net 框架上的协议......

B
Brad C

我们正在做同样的事情。要仅支持 TLS 1.2 而不支持 SSL 协议,您可以这样做:

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

SecurityProtocolType.Tls 只是 TLS 1.0,不是所有的 TLS 版本。

顺便说一句:如果您想检查您的站点是否允许 SSL 连接,您可以在这里进行(我认为这不会受到上述设置的影响,我们必须编辑注册表以强制 IIS 使用 TLS对于传入连接):https://www.ssllabs.com/ssltest/index.html

要在 IIS 中禁用 SSL 2.0 和 3.0,请参阅此页面:https://www.sslshopper.com/article-how-to-disable-ssl-2.0-in-iis-7.html


正确的。支持更新的 TLS 版本的好主意:面向未来。
为了他人的利益,您提到的注册表编辑也可以通过以下步骤完成:serverfault.com/a/637263/98656。在 Windows Server 2003 到 2012 R2 中,协议由 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\Schannel\Protocols 中的标志控制。要禁用 SSLv3,请在上述位置创建一个名为“SSL 3.0”的子项,在该位置下创建一个名为“Server”的子项,并在该位置下创建一个名为“Enabled”的 DWORD 值,设置为 0。您还应该禁用 SSL 2.0以同样的方式。
@ScotterMonkey 如果您从 .NET 代码启动出站连接,您只需要设置 System.Net.ServicePointManager.SecurityProtocol,例如从服务器上运行的自定义代码连接到 Web 服务或 API。如果您只运行一个简单的网站,并且只接受来自浏览器的传入连接,那么注册表修复就足够了。
注意:似乎 SecurityProtocolType.Tls11SecurityProtocolType.Tls12 枚举值仅在 ASP.net 4.5 及更高版本中可用。如果 TLS 1.0 被搁置,我们不确定对于在 2.0 上运行的旧代码库要做什么。
@AnishV您将该行代码放在应用程序的初始化中,然后再启动出站 SSL/TLS 连接的任何代码。
P
Prof Von Lemongargle

@Eddie Loeffen 的答案似乎是这个问题最受欢迎的答案,但它有一些不好的长期影响。如果您查看 System.Net.ServicePointManager.SecurityProtocol here 的文档页面,备注部分暗示协商阶段应该解决这个问题(并且强制协议是不好的做法,因为将来,TLS 1.2 也会受到损害) .但是,如果确实如此,我们就不会寻找这个答案。

研究,似乎需要 ALPN 协商协议才能在协商阶段到达 TLS1.2。我们以此为出发点,并尝试了较新版本的 .Net 框架,以了解支持的起点。我们发现 .Net 4.5.2 不支持与 TLS 1.2 的协商,但 .Net 4.6 支持。

因此,即使现在强制 TLS1.2 可以完成工作,我还是建议您升级到 .Net 4.6。由于这是 2016 年 6 月的 PCI DSS 问题,因此窗口很短,但新框架是一个更好的答案。

更新:根据评论,我构建了这个:

ServicePointManager.SecurityProtocol = 0;    
foreach (SecurityProtocolType protocol in SecurityProtocolType.GetValues(typeof(SecurityProtocolType)))
    {
        switch (protocol)
        {
            case SecurityProtocolType.Ssl3:
            case SecurityProtocolType.Tls:
            case SecurityProtocolType.Tls11:
                break;
            default:
                ServicePointManager.SecurityProtocol |= protocol;
            break;
        }
    }

为了验证这个概念,我将 SSL3 和 TLS1.2 组合在一起,并针对仅支持 TLS 1.0 和 TLS 1.2(1.1 已禁用)的服务器运行代码。使用 or'd 协议,它似乎可以正常连接。如果我更改为 SSL3 和 TLS 1.1,则无法连接。我的验证使用 System.Net 中的 HttpWebRequest 并且只调用 GetResponse()。例如,我试过这个并失败了:

        HttpWebRequest request = WebRequest.Create("https://www.contoso.com/my/web/resource") as HttpWebRequest;
        ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls11;
        request.GetResponse();

虽然这有效:

        HttpWebRequest request = WebRequest.Create("https://www.contoso.com/my/web/resource") as HttpWebRequest;
        ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls12;
        request.GetResponse();

与强制 TLS 1.2 相比,这具有一个优势,因为如果升级 .Net 框架以使 Enum 中有更多条目,则代码将按原样支持它们。与仅使用 .Net 4.6 相比,它有一个缺点,因为 4.6 使用 ALPN,如果未指定限制,则应支持新协议。

2019 年 4 月 29 日编辑 - Microsoft 去年 10 月发布了 this article。它很好地概括了他们关于如何在各种版本的 .net 框架中完成这项工作的建议。


有趣的。看起来文档页面随着 MSDN 迁移到“.NET Framework(当前版本)”而更新,现在解释说“故意没有为此属性列出默认值”。也许接受答案的更具前瞻性的版本是首先查询属性以检索允许的协议列表,然后删除您的应用程序认为不安全的协议(即低于 TLS 1.2 的协议),而不是仅显式添加你认为安全的那些。这不会排除将来的新版本。
能够让程序从系统生成的列表中删除协议会很好,但我在当前的 API 中看不到这样做的方法。唯一的选择似乎是强制执行特定协议,我不明白为什么有人愿意这样做。不幸的是,如果没有 ALPN 支持,这似乎是使 TLS1.2 连接正常工作的唯一方法。
应该可以遍历所有 SecurityProtocolType 枚举,查看 ServicePointManager.SecurityProtocol flags 枚举中存在哪些(这是所有设置标志的逻辑 OR,因此您可以使用 AND 测试每个),然后构建一个新的将它们与您不想删除的列表一起列出。然后将它们组合成一个枚举并用它设置属性。
我只是在重新阅读您的枚举/循环代码,我认为这是不正确的。 |= 逻辑运算符将导致属性包括最初在属性中设置的任何默认值,而不是仅包括 Tls12 及更高版本。要修复它,您必须初始化一个值为 0 的 SecurityProtocolType 枚举变量,对该变量执行 |= 循环,然后将其分配给 ServicePointManager.SecurityProtocol 属性。
有没有人觉得 .NET 不能自动协商它能够处理的最高协议版本这很疯狂?!
C
CZahrobsky

我不得不转换整数等价物来解决我仍在使用 .NET 4.0 的事实

System.Net.ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072;
/* Note the property type  
   [System.Flags]
   public enum SecurityProtocolType
   {
     Ssl3 = 48,
     Tls = 192,
     Tls11 = 768,
     Tls12 = 3072,
   } 
*/

这可行,但 .NET 4.0 不支持 TLS 1.2,但 .NET 4.5 及更高版本支持 TLS 1.2。因此,您可以将此代码(或添加按位 OR 以添加对 TLS 1.2 协商的支持)添加到您的 .NET 4.0 应用程序并构建它,但您需要在 .NET 4.5 或更高版本上部署代码。 blogs.perficient.com/microsoft/2016/04/tsl-1-2-and-net-support
另请参阅此,.NET 4.0 代码将在更高版本的 .NET 上正常工作,包括 .NET 4.5 和 .NET 4.6 stackoverflow.com/questions/33378902/…
整数转换适用于发送 TLS 1.2。 .NET 4.0 中不存在 Tls12 枚举值
两个不同的点。看我的评论。您可以输入该值,但如果您的运行时网络版本是 4.0,它将失败。您可以使用此标志进行编译,但您的运行时 .NET 版本需要为 4.5 或更高版本,因为 .NET 4.0 上的基本组件不支持 TLS 1.2 所需的密码(请参阅链接)
较早的 .NET 运行时版本有几个修补程序以添加 TLS 1.2 支持。例如 support.microsoft.com/en-us/help/3154518/…,CZahrobsky 也可以在 Win10 秋季创建者更新中使用它,该更新还包括修补程序。
D
DirtyHowi

@沃森

在 Windows 窗体上它是可用的,放在类的顶部

  static void Main(string[] args)
    {
        ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
       //other stuff here
    }

因为windows是单线程的,所以你只需要它,如果它是一个服务,你需要把它放在对服务的调用之上(因为不知道你会在哪个线程上)。

using System.Security.Principal 

也是需要的。


C
Colonel Panic

如果您对 .NET 支持哪些协议感到好奇,可以在 https://www.howsmyssl.com/ 上试用 HttpClient

// set proxy if you need to
// WebRequest.DefaultWebProxy = new WebProxy("http://localhost:3128");

File.WriteAllText("howsmyssl-httpclient.html", new HttpClient().GetStringAsync("https://www.howsmyssl.com").Result);

// alternative using WebClient for older framework versions
// new WebClient().DownloadFile("https://www.howsmyssl.com/", "howsmyssl-webclient.html");

结果很惨:

您的客户端使用的是非常旧的 TLS 1.0,可能容易受到 BEAST 攻击,并且没有可用的最佳密码套件。 TLS 1.0 客户端以及更多现代密码套件无法使用 AES-GCM 和 SHA256 等替代 MD5-SHA-1 的附加功能。

正如 Eddie 上面解释的那样,您可以手动启用更好的协议:

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

我不知道为什么它使用开箱即用的坏协议。这似乎是一个糟糕的设置选择,相当于一个重大的安全漏洞(我敢打赌,很多应用程序都不会更改默认设置)。我们如何举报?


R
Raman

我发现最简单的解决方案是添加两个注册表项,如下所示(在具有管理员权限的命令提示符下运行):

reg add HKLM\SOFTWARE\Microsoft\.NETFramework\v4.0.30319 /v SchUseStrongCrypto /t REG_DWORD /d 1 /reg:32

reg add HKLM\SOFTWARE\Microsoft\.NETFramework\v4.0.30319 /v SchUseStrongCrypto /t REG_DWORD /d 1 /reg:64

这些条目似乎会影响 .NET CLR 在作为客户端建立安全连接时如何选择协议。

这里有关于这个注册表项的更多信息:

https://docs.microsoft.com/en-us/security-updates/SecurityAdvisories/2015/2960358#suggested-actions

这不仅更简单,而且假设它适用于您的案例,比基于代码的解决方案更强大,后者需要开发人员跟踪协议和开发并更新所有相关代码。希望可以为 TLS 1.3 及更高版本进行类似的环境更改,只要 .NET 保持足够笨拙,不会自动选择最高可用协议。

注意:尽管根据上面的文章,这只是应该禁用 RC4,并且人们不会认为这会改变 .NET 客户端是否被允许使用 TLS1.2+,由于某种原因它确实有这个影响。

注意:正如@Jordan Rieger 在评论中所指出的,这不是 POODLE 的解决方案,因为它不会禁用旧协议 a - 它仅允许客户端使用较新的协议,例如,当修补的服务器禁用较旧的协议时协议。但是,对于 MITM 攻击,很明显,受感染的服务器会为客户端提供旧协议,然后客户端会愉快地使用该协议。

TODO:尝试使用这些注册表项禁用客户端对 TLS1.0 和 TLS1.1 的使用,但是我不知道 .NET http 客户端库是否尊重这些设置:

https://docs.microsoft.com/en-us/windows-server/security/tls/tls-registry-settings#tls-10

https://docs.microsoft.com/en-us/windows-server/security/tls/tls-registry-settings#tls-11


注册表设置作为代码的替代方案会很棒,但是这些设置是否实际上禁用了 TLS 1.0 和 1.1,而只允许使用 TLS 1.2 及更高版本的客户端连接?根据链接,它似乎只在 TLS 中禁用 RC4。我认为贵宾犬的攻击范围比这更广泛。
@JordanRieger 这些注册表项允许 .NET 客户端连接到禁用旧协议以缓解 POODLE 的服务器。没有这些,客户端将抛出错误,因为 .NET 客户端愚蠢地坚持使用旧协议,即使服务器要求使用新协议。如果您的服务器仍然允许使用旧协议进行连接,那么所有的赌注都将被取消。理论上旧的协议应该被禁用。我想知道允许在服务器上禁用这些的相同注册表项(例如 nartac.com/Products/IISCrypto)是否也适用于客户端?
在 nartac 操作的注册表项中,(作为)客户端和(作为)服务器有单独的设置。我不记得他们的界面是否有区别。你知道什么版本的 .net 支持这个注册表黑客吗?
不过,@Raman 我的问题的重点是在您的客户端连接到您无法控制的服务器时减轻 POODLE 漏洞。该漏洞将允许 MITM 攻击者将协议降级到可以被黑客入侵的旧 TLS 或 SSL 版本。仅仅禁用 RC4 是不够的。这些注册表设置可能对某些情况有用,但在我的问题中没有用。
@JordanRieger 同意。我用一些额外的观察和想法更新了文本。

关注公众号,不定期副业成功案例分享
关注公众号

不定期副业成功案例分享

领先一步获取最新的外包任务吗?

立即订阅