使用 openssl 命令,我如何判断它是否使用 TLS 1.0?

信息安全 tls openssl 雄猫
2021-09-03 07:25:39

由于安全扫描,我被告知不要使用 TLS1.0。我找到了一个链接,它给了我用于检查是否使用/启用了特定协议的命令。我运行的命令(输出是)

(禁用 TLS1.0 的输出)

$ openssl s_client -connect localhost:8443 -tls1
CONNECTED(00000003)
139874418423624:error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure:s3_pkt.c:1275:SSL alert number 40
139874418423624:error:1409E0E5:SSL routines:SSL3_WRITE_BYTES:ssl handshake failure:s3_pkt.c:598:
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 7 bytes and written 0 bytes
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
SSL-Session:
    Protocol  : TLSv1
    Cipher    : 0000
    Session-ID: 
    Session-ID-ctx: 
    Master-Key: 
    Key-Arg   : None
    Krb5 Principal: None
    PSK identity: None
    PSK identity hint: None
    Start Time: 1505770082
    Timeout   : 7200 (sec)
    Verify return code: 0 (ok)
---

该链接表示如果启用了协议,它将显示“已连接”,否则会显示“握手失败”。但是,正如您在上面看到的消息,即使我将 Tomcat 配置为使用 TLS1.2,它也会显示两者。

我在 server.xml 文件中的配置:

<Connector port="8443" protocol="HTTP/1.1"
   maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
   keystoreFile="/glide/bigdata/bdapi/keys/bdapi_keystore.jks"
   keystorePass="bdapi123" clientAuth="false" sslProtocol="TLSv1.2" 
   sslEnabledProtocols="TLSv1.2"/>

如果我允许 Tomcat 使用 TLS1.0,我仍然会看到 CONNECTED,但我也会看到证书信息。

(启用 TLS1.0 的输出)

openssl s_client -connect localhost:8443 -tls1
CONNECTED(00000003)
<snip snip>
<snip snip>
(certificate info)
verify error:num=21:unable to verify the first certificate
verify return:1
---
Certificate chain
<snip snip>
<snip snip>
(certificate info)
---
Server certificate
-----BEGIN CERTIFICATE-----
<snip snip>
<snip snip>
(public key)
-----END CERTIFICATE-----
<snip snip>
<snip snip>
(certificate info)
---
No client certificate CA names sent
Server Temp Key: ECDH, secp521r1, 521 bits
---
SSL handshake has read 2121 bytes and written 357 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES256-SHA
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
    Protocol  : TLSv1
    Cipher    : ECDHE-RSA-AES256-SHA
    Session-ID: 59C0448146B0A18DE52D99C630C896E12BA9861702AB2582C2AA0658E6458B04
    Session-ID-ctx: 
    Master-Key: <some random key>
    Key-Arg   : None
    Krb5 Principal: None
    PSK identity: None
    PSK identity hint: None
    Start Time: 1505772673
    Timeout   : 7200 (sec)
    Verify return code: 21 (unable to verify the first certificate)
---
read:errno=0

如何解释 openssl 的输出?我是否使用上面的配置成功禁用了 TLS1.0,或者因为它在两个输出中都显示“CONNECTED”,所以我没有禁用它,我将再次失败安全扫描?

4个回答

TL;TR:从客户端验证服务器不支持 TLS 1.0 绝非易事。如果您与 TLS 1.0 成功连接,则可以确定服务器支持 TLS 1.0。但是,如果此尝试失败,您无法确定服务器不支持 TLS 1.0。


正如您已经意识到您引用的链接中给出的信息至少部分错误。而且,它们是不完整的。检查服务器是否真的禁用了 TLS 1.0 并不是那么简单。要了解需要检查哪些内容才能真正确定,最好至少对 TLS-Handshake 的工作原理有一个基本的了解。请注意,我在这里所说的大部分内容也适用于 SSL,它主要是同一个协议系列的早期名称,现在称为 TLS。

最初,客户端需要创建到服务器的 TCP 连接。这与 TLS 本身无关。如果 TCP 连接成功,您将获得CONNECTED(00000003). 如果您没有获得此 CONNECTED,则服务器可能已关闭或无法从您的站点访问,例如因为防火墙阻止了访问。因此,没有得到 CONNECTED 并不能说明服务器支持 TLS 1.0 的能力

创建 TCP 连接后,TLS 部分开始。在最简单的情况下,客户端在 ClientHello 消息中的 TLS 握手开始时发送它可以使用的最佳 TLS 版本和它支持的密码。服务器回复它支持的最好的 SSL/TLS 协议,该协议等于或低于客户端提供的协议版本。服务器根据客户端提供的内容以及配置为服务器可接受的内容来选择通用密码。在您的特定情况下,客户端提供 TLS 1.0 作为最佳协议(由于-tls1选项)和默认密码集。如果服务器不支持 TLS 1.0 或更低版本,或者服务器不支持客户端提供的任何密码,则握手将失败。因为最后一部分即使服务器启用了 TLS 1.0,服务器也可能会因您的特定客户端而失败,因为服务器不喜欢客户端提供的密码

它变得更加复杂。今天,服务器在同一个 IP 地址上支持多个证书是很常见的。这是通过 在 TLS 握手开始时在 ClientHello 中包含使用SNI TLS 扩展的目标主机名来完成的。如果没有 SNI 扩展或扩展与任何配置的主机名不匹配,服务器通常会发送一些默认证书或中止握手。由于最后一部分,即使服务器启用了 TLS 1.0,服务器也可能会因您的特定客户端而失败,因为没有使用 SNI 扩展名或使用了错误的主机名openssl s_client默认情况下不会使用 SNI,因此您的尝试可能只是因为缺少 SNI 扩展而失败。您必须使用-servername 选项,当然您需要使用在服务器上正确配置的主机名和此选项。

到目前为止,我们只处理了健全的 TLS 堆栈和与服务器的直接连接。如果 TLS 堆栈损坏或中间有一些损坏的中间盒(如负载平衡器、防火墙等),即使服务器支持 TLS 1.0,它们也可能会意外或故意使握手失败。如果您的服务器前面有一些 SSL 终止(一些防火墙、负载平衡器或 CDN),您甚至不会测试服务器的属性,而是测试它前面的系统的属性。

换句话说:如果您成功地与服务器建立了 TLS 1.0 连接,则可以确定服务器或它前面的某些 SSL 终结器支持 TLS 1.0。如果 TLS 1.0 连接失败,并不意味着服务器不支持 TLS 1.0。

尽管这些工具不能直接回答您的具体问题,但它们可能会提供您正在寻找的结果。如果您有 Internet 连接,请尝试以下方法:

如果没有 Internet 连接,请尝试:

是的,该网站是错误的CONNECTED表示 TCP 连接成功,但没有说明 TLS(或希望不是 SSL)握手。如果你没有得到 CONNECTED 但有几行以connect: errno=$n(即使数字是 0!)结尾,这意味着我们甚至无法尝试握手,因此无论服务器支持什么方式都没有任何信息。

尽管您可以学习阅读错误消息和其他信息openssl,但关键指标是从New,最后一个输出块开头的行(在---之前的几行之后SSL-Session:);如果它显示一个真实的协议版本并加密握手成功,如果它(NONE)握手失败- 就像你的那样。

请注意,握手可能由于协议版本以外的原因而失败。如果对 1.0 的测试成功,您可以确定服务器确实支持 1.0,但如果测试失败,并不能肯定地证明服务器支持 1.0。您需要真正了解 TLS 才能区分它们。正如 Steffen 在我写这篇文章时发布的那样——但我认为我的第 2 段和第 4 段可能仍然有帮助。

FWIW 还指出,仅使用 SSLv2 的测试s_client -ssl2在 1.0.0 以上版本中无效,其中默认密码列表阻止 SSLv2 连接,即使在支持 SSLv2 的服务器上也是如此。但是,今天仍然担心真实(不是测试实验室或博物馆)服务器上的 SSLv2 的任何人都陷入了大麻烦。

此输出意味着我们已成功禁用 TLS 1.0:

CONNECTED(00000003)
140089425225616:error:1409442E:SSL routines:ssl3_read_bytes:tlsv1 alert protocol version:s3_pkt.c:1493:SSL alert number 70
140089425225616:error:1409E0E5:SSL routines:ssl3_write_bytes:ssl handshake failure:s3_pkt.c:659:

如果它没有被禁用,它将显示完整的证书详细信息。