1

.NET Core如何配置TLS Cipher(套件)?

 2 years ago
source link: https://www.cnblogs.com/CreateMyself/p/15643871.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
前不久我发表了一篇关于TLS协议配置被我钻了空子,经过第三方合作伙伴验证,针对此TLS协议存在不安全套件,急催速速解决,那么我们本篇开始继续整活!第三方合作伙伴对平台安全严苛要求,我们已连续发版十几次进行处理,在此过程中使得我对安全有了进一步认识,具体认识则是在技术解决方案和密码学盲点两方面。下面我们来了解两个方面,可能没有完全深入,至少对作为开发者的我们而言,应已基本足够

.NET Core Cipher(套件)配置

如果没有项目上的苛刻要求,我断然也就无法在此方面展开研究和实践。本文具以.NET 5为例,只不过针对.NET Core 3或3.1通过工具扫描出的协议套件结果略有所差异,但不影响我们对安全套件的配置,我们使用OpenSSL生成自签名证书,后续我会发表文章讲解OpenSSL自签名证书等等

webBuilder.ConfigureKestrel(serverOptions =>
{
    serverOptions.Listen(IPAddress.Any, 8000, listenOptions =>
    {
        listenOptions.UseHttps("ssl.pfx", "123456", adapterOptions =>
        {
          adapterOptions.SslProtocols = SslProtocols.Tls12;
        });
    });
});

HTTPS结合TLS 协议1.0或1.1不安全,所以TLS协议需使用1.2+,这里我们如上述代码使用版本1.2,接下来我们将其部署在Linux上,然后安装nmap,通过nmap工具扫描(至于nmap是什么,可自行了解)

通过nmap扫描指定端口号并枚举其支持TLS 套件需要注意一点,我们可能搜罗出来大多数文章的命令结果一扫,压根没有结果,其实nmap只对指定端口扫描才有效(比如443等等),比如使用如下命令无效果

nmap --script ssl-enum-ciphers localhost -p 8000

若是其他端口,可使用如下命令进行扫描

nmap --script +ssl-enum-ciphers localhost -p 8000

最终我们扫描出来的结果如下:

AES-CBC模式在中SSL或者TLS中存在一些已知的安全漏洞,如BEAST攻击、Lucky 13攻击等,虽然TLS1.1、TLS1.2未受到BEAST攻击的影响、Lucky 13(影响涉及到TLS1.1/1.2)攻击也在Openssl等知名加密算法库得到了修复,但这些漏洞均暴漏出CBC模式在SSL/TLS协议实现时容易引入安全漏洞,HTTP/2中也明确将CBC模式加密套件列为黑名单

上述是在.NET 5 TLS 1.2默认行为,但第三方规定禁止使用AES-CBC即使扫描出来的套件强度为A,并给定了其支持的安全套件

在上述配置通过路径读取文件和使用密码启用HTTPS重载方法中,如下

public static ListenOptions UseHttps(this ListenOptions listenOptions, string fileName, string password, Action<HttpsConnectionAdapterOptions> configureOptions);

最后可针对连接做配置,在该类中有如下属性

public Action<ConnectionContext, SslServerAuthenticationOptions> OnAuthenticate { get; set; }

该输入第二个类参数里面,有针对套件的配置,如下(我也是结合github找了老半天才翻到)

所以最终我们配置支持的安全套件如下(诸多套件,闻所未闻,不打紧,下面会归纳总结):

webBuilder.ConfigureKestrel(serverOptions =>
{
  serverOptions.Listen(IPAddress.Any, 8000, listenOptions =>
  {
    listenOptions.UseHttps("ssl.pfx", "123456", adapterOptions =>
    {
      adapterOptions.SslProtocols = SslProtocols.Tls12;

      adapterOptions.OnAuthenticate = (connectionContext, authenticationOptions) =>
      {
        var ciphers = new List<TlsCipherSuite>()
        {
          TlsCipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
          TlsCipherSuite.TLS_DHE_RSA_WITH_AES_256_GCM_SHA384,
          TlsCipherSuite.TLS_DHE_DSS_WITH_AES_128_GCM_SHA256,
          TlsCipherSuite.TLS_DHE_DSS_WITH_AES_256_GCM_SHA384,
          TlsCipherSuite.TLS_PSK_WITH_AES_128_GCM_SHA256,
          TlsCipherSuite.TLS_PSK_WITH_AES_256_GCM_SHA384,
          TlsCipherSuite.TLS_DHE_PSK_WITH_AES_128_GCM_SHA256,
          TlsCipherSuite.TLS_DHE_PSK_WITH_AES_256_GCM_SHA384,
          TlsCipherSuite.TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256,
          TlsCipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
          TlsCipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
          TlsCipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
          TlsCipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
          TlsCipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
          TlsCipherSuite.TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256,
          TlsCipherSuite.TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256,
          TlsCipherSuite.TLS_ECDHE_PSK_WITH_AES_256_GCM_SHA384,
          TlsCipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CCM_SHA256,
          TlsCipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM,
          TlsCipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM,
          TlsCipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM_8,
          TlsCipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM_8,
          TlsCipherSuite.TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
          TlsCipherSuite.TLS_PSK_WITH_AES_128_CCM,
          TlsCipherSuite.TLS_PSK_WITH_AES_256_CCM,
          TlsCipherSuite.TLS_DHE_PSK_WITH_AES_128_CCM,
          TlsCipherSuite.TLS_DHE_PSK_WITH_AES_256_CCM,
          TlsCipherSuite.TLS_PSK_WITH_AES_128_CCM_8,
          TlsCipherSuite.TLS_PSK_WITH_AES_256_CCM_8,
          TlsCipherSuite.TLS_PSK_DHE_WITH_AES_128_CCM_8,
          TlsCipherSuite.TLS_PSK_DHE_WITH_AES_256_CCM_8,
          TlsCipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM,
          TlsCipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CCM,
          TlsCipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8,
          TlsCipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8,
          TlsCipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
        };

        authenticationOptions.EnabledSslProtocols = SslProtocols.Tls12;
        authenticationOptions.CipherSuitesPolicy = new CipherSuitesPolicy(ciphers);
      };
    });
  });
});

咳咳,到这里为止,我们满心欢喜,是不是就这样愉快结束了?接触到一个新的点时,一定一定要先看下解释,别一顿操作后不好使,耗费时间和劳力而全是无用功,最终才发现问题症结点所在,这也是我最近才有深刻体会

据我初步的了解应该是在.NET Core 3.0+才开始支持配置OpenSSL的套件,且版本必须是1.1.1+,但不支持Windows,仅支持Linux或OSX!同时在.NET Core 3.1以下版本默认协议是1.1或1.2,但在.NET 5默认协议变更为了1.3,其支持套件配置也与OpenSSL配置也有了一定关联。见链接《https://docs.microsoft.com/en-us/dotnet/core/whats-new/dotnet-core-3-0

当接触到某一知识点时(比如TLS),我认为稍微看下更高版本对此方面是否有变更很有必要,假设我们不知道.NET 5+默认变更为了1.3,当进行版本升级过后,如果第三方对接此前使用的是TLS 1.2,那么数据对接就会断层,业务必将受影响。仅我个人建议,至于其他我就管不到了~~~基于上述所述,若是在Windows开发环境,势必要在对应基础上判断操作系统

if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) || RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
  ......
}

最终我们扫描结果如下,已将AES-CBC不安全套件给去除,完全满足安全要求

 密码学基础

密码套件所用到的算法大致有四种:对称加密算法、非对称密钥交换算法、数字签名算法(DSA)、可选的基于散列的消息身份验证代码(HMAC)

说白了,密码学套件就是一组算法,开启HTTPS和TLS并协同使用密码学套件,才能使得传输更加安全

我们知道算法都是公开的,唯一不同的是算法依赖于密钥,只有对接双方知道,从而保护加密过后的密文而不能被窥探,那么接下来我们拆分讲解上述几种算法

非对称加密算法,说白了就是一方拥有公钥,另一方拥有私钥,它是浏览器和服务器开始时通过TLS握手时协商作为加密套件使用,至于HTTPS的其余部分可使用商定的密码套件进行使用

最初通过TLS握手时所使用的最主要的三种算法是:

DHE:Diffie-Hellman Ephemeral (密钥交换算法)

RSA:以其发明者Rivest-Shamir-Adleman的名字而命名

ECDHE:Elliptic-curve Diffie–Hellman(椭圆曲线交换:翻译而来)

对称算法,说白了就是双方都知道的单一密钥,相比较非对称加密算法而言,它的计算速度更快,但并不适用于作为Web证书,因为浏览器和服务器不知道也完全不信任彼此,因此无法共享密钥,然而,在进行初始握手协议之后,再使用对称加密算法非常合适即创建一个共享的密钥以在HTTPS通信的其他期间使用

最常见的四种对称加密算法是:

AES:Advanced Encryption Standard

AES-GCM:AES Galois/Counter

AES-CCM:AES Counter with CBC-MAC(密码块链接消息认证码)

ChaCha20:又名Salsa20

密码强度是一种安全度量,加密文本在遭受攻击时有多安全?算法的强度与密钥的长度相关,所以更长的密钥更强大,密钥长度表示为位数,常用的值为128 和 256,对称算法由它们的首字母缩略词和它们的密钥长度来标识,比如像 AES128 或 AES256。

说了这么一大堆,好像就了解到几个算法名称,要是脱离本文的内容确实仅在脑后留下些许印象,那么接下来我们结合配置的密码套件来进行实践理解,我们拿上述配置的第一个密码套件来进行阐述,其余同理,如下

 TlsCipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256

上述TlsCipherSuite是一个枚举,我们仅看枚举内容,将TLS去掉剩余则是DHE_RSA_WITH_AES_128_GCM_SHA256

我们再结合上述阐述的非对称和对称加密算法将其拆分,则是DHE、RSA、AES-128-GCM

从最终拆分的结果来看,实际上HTTPS使用了一对算法而非单一算法,其中一种非对称加密DHE和RSA用于初始期间TLS握手,而另一种对称加密算法AES-128-GCM用于数据传输期间的加密和解密!如此一来对于HTTPS使用对称和非对称加密算法则形成多种组合

但简单地选择一对非对称/对称算法不足以完全识别密码套件,所以还需要指定用于确保身份验证和完整性的规则。比如通过LetsEncrypt证书机构来颁发证书。更深层次的密码学东东这里就不再展开了,我也就探究于此

.NET Core中配置的密码套件与OpenSSL所支持套件吻合,如下截图一部分:

那么问题来了,上述我们配置了多种套件,结果通过工具扫描时有三种被支持的套件被扫描出,浏览器和服务器初次进行TLS握手时,到底选择哪一种呢?那么我们接下来通过访问并查看Web证书能否找到蛛丝马迹,事先声明:以下部分内容为我个人推测,至于理论上是否如真如我所言未可知

通过查看证书反推,我们通过OpenSSL创建自签名证书所使用的是RSA加sha256算法,然后再看如下图可知所使用最终套件

结合这二者是不是就可以说明所使用的密码套件对应OpenSSL配置则是:ECDHE-RSA-AES128-GCM-SHA256,也就是对应通过nmap工具扫描出来支持的三种套件中的第一个

ECDHE-RSA-AES128-GCM-SHA256结论由上述证书和安全查看而言,因为是sha256RSA所以密码套件最后则是SHA256,果真是如此,我能否自圆其说?要是我们将SHA256套件删除,是不是页面就不支持,Web页面无法访问呢?

经过上述修改和通过nmap扫描出结果如下:

看来与证书上所言算法无关,最终回到我通过自创建证书命令

openssl genrsa -out ca-key.key 3072

只能匹配到所使用RSA非对称加密算法,OpenSSL可指定加密方式

但当我指定aes128或其他位时,其模式其实是CBC而非GCM

最终查看是否支持GCM

openssl aes-256-gcm

其实OpenSSL支持GCM,只不过不能用过命令行来进行操作,具体原因官方有解释。分析了这么多,貌似没啥用,目前大致能确定的是:密码套件的支持还是需要浏览器和服务器来进行握手协商

比如在谷歌浏览器中就可设置是否启用TLS 1.3

到目前为止,我们大致知道了HTTPS所使用的是一组算法,握手期间用非对称加密算法,数据传输期间用对称加密算法!那么整个期间,猜测是结合生成的证书,然后遍历配置套件进行握手,握手成功后再进行数据传输

大致握手和数据传输过程,简单描述如下:

客户端向服务端发送消息,我使用TLS 1.2中的ECDHE-RSA-AES128-GCM-SHA256以及还有其他套件,你能处理吗?服务端向客户端回复消息,ECDHE-RSA-AES128-GCM-SHA256能处理,然后向客户端发出公钥证书。客户端向服务端回复消息,证书是合法的,客户端生成密钥6p7vUjFz紧接着使用服务端的公钥证书进行加密,通知服务端以后数据传输用指定的密钥即共享密钥

当自定义配置所支持套件时,需要额外注意一点的是,千万别同时指定TLS 1.2和TLS 1.3

啊,又到了总结的地方,貌似没啥可总结的,具体相关了解到的或体会到的已在文中有阐述,我们下节再会

scan.gif
为了方便大家在移动端也能看到我分享的博文,现已注册个人公众号,扫描上方左边二维码即可,欢迎大家关注,有时间会及时分享相关技术博文。

感谢花时间阅读此篇文章,如果您觉得这篇文章你学到了东西也是为了犒劳下博主的码字不易不妨打赏一下吧,让楼主能喝上一杯咖啡,在此谢过了!
如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写作动力!
本文版权归作者和博客园共有,来源网址:http://www.cnblogs.com/CreateMyself)/欢迎各位转载,但是未经作者本人同意,转载文章之后必须在文章页面明显位置给出作者和原文连接,否则保留追究法律责任的权利。

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK