映射 SSL/TLS 密码套件及其 OpenSSL 等效项

Posted

技术标签:

【中文标题】映射 SSL/TLS 密码套件及其 OpenSSL 等效项【英文标题】:Map SSL/TLS cipher suites and their OpenSSL equivalents 【发布时间】:2016-04-06 22:27:28 【问题描述】:

我正在尝试检查哪些密码套件可以与服务器握手。我在帖子末尾使用脚本,代表他调用 OpenSSL,输出是套件名称的 OpenSSL 等效项。例如:

$./ciphers.sh ***.com:443
***.com:443,SSL2(),SSL3(),TLS1(ECDHE-RSA-AES256-SHA:AES256-SHA:ECDHE-RSA-AES128-SHA:AES128-SHA),TLS1.1(ECDHE-RSA-AES256-SHA:AES256-SHA:ECDHE-RSA-AES128-SHA:AES128-SHA),TLS1.2(ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:AES256-SHA256:AES256-SHA:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:AES128-SHA256:AES128-SHA)

我不知道如何将它们与 SSL/TLS 密码套件名称进行映射。我需要的是密码名称列表,例如

TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA 
TLS_DHE_RSA_WITH_AES_128_CBC_SHA   
TLS_RSA_WITH_AES_128_CBC_SHA       
TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
SSL_RSA_WITH_3DES_EDE_CBC_SHA 

但我就是想不通...感谢您的帮助和时间!

#!/usr/bin/env bash
ciphers2=$(openssl ciphers -ssl2 'ALL:eNULL' | sed -e 's/:/ /g')
ciphers3=$(openssl ciphers -ssl3 'ALL:eNULL' | sed -e 's/:/ /g')
cipherst1=$(openssl ciphers -tls1 'ALL:eNULL' | sed -e 's/:/ /g')
cipherst11=$(openssl ciphers -tls1.1 'ALL:eNULL' | sed -e 's/:/ /g')
cipherst12=$(openssl ciphers -tls1.2 'ALL:eNULL' | sed -e 's/:/ /g')

SSL2="SSL2("
for cipher in $ciphers2[@]
do
result=$(echo -n | openssl s_client -ssl2 -cipher "$cipher" -connect $1 2>&1)
if [[ "$result" =~ "Cipher is $cipher" ]] ; then
  SSL2="$SSL2$cipher:"
fi
done
SSL2=$(echo "$SSL2)" | sed -e 's/:)/)/g')

SSL3="SSL3("
for cipher in $ciphers3[@]
do
result=$(echo -n | openssl s_client -ssl3 -cipher "$cipher" -connect $1 2>&1)
if [[ "$result" =~ "Cipher is $cipher" ]] ; then
  SSL3="$SSL3$cipher:"
fi
done
SSL3=$(echo "$SSL3)" | sed -e 's/:)/)/g')
TLS1="TLS1("
for cipher in $cipherst1[@]
do
result=$(echo -n | openssl s_client -tls1 -cipher "$cipher" -connect $1 2>&1)
if [[ "$result" =~ "Cipher is $cipher" ]] ; then
  TLS1="$TLS1$cipher:"
fi
done
TLS1=$(echo "$TLS1)" | sed -e 's/:)/)/g')

TLS11="TLS1.1("
for cipher in $cipherst11[@]
do
result=$(echo -n | openssl s_client -tls1_1 -cipher "$cipher" -connect $1 2>&1)
if [[ "$result" =~ "Cipher is $cipher" ]] ; then
  TLS11="$TLS11$cipher:"
fi
done
TLS11=$(echo "$TLS11)" | sed -e 's/:)/)/g')

TLS12="TLS1.2("
for cipher in $cipherst12[@]
do
result=$(echo -n | openssl s_client -tls1_2 -cipher "$cipher" -connect $1 2>&1)
if [[ "$result" =~ "Cipher is $cipher" ]] ; then
  TLS12="$TLS12$cipher:"
fi
done
TLS12=$(echo "$TLS12)" | sed -e 's/:)/)/g')

echo "$1,$SSL2,$SSL3,$TLS1,$TLS11,$TLS12";

【问题讨论】:

你得到什么输出?您可能还希望根据每个调用使用-no_ssl2-no_tls1_1 禁用每个opensslinvocation 中未使用的所有协议。并尝试为每次调用发出一些调试数据,例如有问题的密码。 您运行的是哪个版本的 OpenSSL?对于 OpenSSL 1.0.2.f,我不认为 openssl ciphers 具有除 -ssl2-ssl3-tls1 选项之外的任何选项。没有为ciphers 列出-tls1.1-tls1.2 选项。 openssl 和 RFC 密码名称之间的转换可以在 testssl.sh/openssl-rfc.mappping.html 找到。 @AndrewHenle 在s_client 中指定单个协议,如-tls1 已经禁用所有其他协议; -no_ 选项仅在您想保留默认的“自动协商”功能(现在严重错误命名的 SSLv23_method)但对其进行部分限制时才需要。 @dave_thompson_085 但是限制“自动协商”功能似乎正是需要的,因为可以为多个 SSL/TLS 版本实现任意密码套件,但发布的脚本看起来正在测试是否服务器在特定 SSL/TLS 级别上支持正在测试的密码套件。 【参考方案1】:

名称映射:OpenSSL 使用自己的一组密码套件名称,这些名称与大多数其他实现和文档使用的 RFC 中的名称相关但不相同。请参阅您系统上ciphers 的手册页(如果类 Unix,并且 bash 主要在类 Unix 系统上,尽管它可以移植到其他系统)大约一半的标题“CIPHER SUITE NAMES”下。在某些系统上,您可能需要指定类似man 1ssl ciphers 的部分。或在线(更新)https://www.openssl.org/docs/manmaster/man1/openssl-ciphers.html(如有必要,请使用右侧的链接获取特定版本)。

要手动将 RFC 名称转换为 OpenSSL:丢弃(前导)TLSSSL 和(嵌入)WITH,并将所有 _ 更改为 -;其中密钥交换是纯 RSA(不是 [EC]DH[E]-RSA)完全丢弃它;在某些情况下,将DHE 交换为EDH(仅限旧版本)并始终将DH_anon 交换为ADHECDH_anonAECDH;在 大多数 情况下将 3DES_EDE_CBC 更改为 DES-CBC3;将EXPORT 缩短为EXP 并将其移至开头;如果不需要消除歧义,在某些情况下删除位长度和 CBC

请注意,匿名套件从未包含在提供或接受的默认列表中;从 2015 年 3 月的 1.0.0r 1.0.1m 和 1.0.2a 开始,导出套件从默认值中删除,并从 2016 年 3 月的 1.0.1s 和 1.0.2g 开始,完全删除并从默认值中删除了单 DES; 3DES RC4 SEED IDEA Camellia 和 DSS 身份验证(又名 DSA)在 1.1.0 中不是默认设置; SSL2 协议自 1.0.0 起默认禁用,并在 2016-08 发布的 1.1.0 中完全删除; SSL3 在 1.1.0 中默认编译出来,但可以重新添加(尽管你不应该使用它,也不应该在较低版本上使用它,因为它被 POODLE 破坏了,除了 RC4 还有其他缺陷)。

可用性: 密码套件在低于 1.1.0 的 OpenSSL 中分为三类:用于 SSL2 的密码套件; SSL3 及以上版本;以及那些用于 TLS1.2 的。 SSL2 使用不同的代码方案,因此 SSL2 套件不能用于较新的协议,反之亦然。为了迂腐,TLS1.0 放弃了 Fortezza 套件(OpenSSL 无论如何都没有实现)并且 TLS1.1 放弃了导出套件,但 OpenSSL 仍然允许它们,除非如上所述。另一方面,TLS1.2 添加了新格式 (AEAD) 和新 PRF/KDF 方案,以及一堆仅适用于 TLS1.2 的新密码套件;它还保留了 TLS1.1 中的所有内容,除了单 DES 和 IDEA,OpenSSL 仍然允许除上述之外的所有内容。

低于 1.1.0 的 ciphers 上的 -ssl2 -ssl3 -tls1 选项仅限制您使用与该格式兼容的套件,并且所有 SSL3-up 和 TLS1.2 套件都与 -ssl3 兼容和-tls1;再次查看手册页。正如@Andrew 所指出的,-tls1.1-tls1.2 低于 1.1.0(编辑)没有选项,它添加了选项 -tls1_1-tls1_2(下划线不是点),它们实际上仍然相同,并且还添加了一个选项-stdname 显示标准 (RFC) 名称,避免映射问题 - 但使行很长,恕我直言,难以阅读。

PS:如果您的目标只是匹配或通过一些愚蠢地枚举密码的审计扫描,那么这种方法可以工作。如果您希望确定有关服务器的安全性 的有用信息,这主要是在浪费时间。服务器完全不执行 SSL2 或 SSL3(使用任何密码套件)并支持 一些 体面的密码套件并且不应用错误的偏好(此扫描未测试)就足够了;除了确切支持哪些密码套件之外,对安全性的影响远不及使用良好的身份验证密钥和证书链以及可能的装订(这没有测试)之类的事情;使用几乎不可能测试的良好的短暂参数和随机性,这不会尝试;支持 5746 和回退等功能,并且没有像 Heartbleed 和 CCS 这样未经测试的错误;避免或减轻未测试且通常可能无法测试的压缩问题,并使用记录拆分作为针对实际上不可测试的 BEAST 的最佳实践;以及 SSL/TLS 级别以上的各种问题。

更新:以上是在 2018 年 TLS1.3 发布之前编写的,由 OpenSSL 1.1.1 实现。 TLS1.3 使用一组全新的密码套件,仅指定完全不再使用 HMAC 的 AEAD 对称加密(GCM、CCM 或 ChaCha+Poly)和 KDF 哈希(KDF 已被大幅更改并且不再称为PRF); 1.3 密码套件像以前的版本那样指定密钥交换和服务器身份验证。 (这些现在由协议的其他部分处理。有关详细信息,请参阅 RFC 8446。)对于 1.3 套件,OpenSSL 使用标准名称,以及一个单独的新 API;命令行 ciphers 涵盖 1.0-1.2 和 1.3 API。如上所述,自 1.1.0 起,SSL2 已被完全删除,包括其所有独特的密码套件。

【讨论】:

以上是关于映射 SSL/TLS 密码套件及其 OpenSSL 等效项的主要内容,如果未能解决你的问题,请参考以下文章

使用 openssl 生成证书

WindowsServer 2016 修复SSL/TLS协议信息泄露(CVE-2016-2183)

密码学初级教程(四)SSL/TLS-为了更安全的通信

关于SSL/TLS协议信息泄露漏洞(CVE-2016- 2183)解决方案

使用 TLS 协议在客户端和服务器之间进行通信的密码套件 [重复]

使用OpenSSL创建CA和申请证书