我有一个场景,一些旧客户端只能支持 MD5 和 SHA1 签名。显然,这些通常被认为已弃用,但我仍然需要支持它们。升级这些客户端不是可以完成的事情(固件更新不再发布,理想情况下我想砍掉所有这些设备,但这也不可行)。
假设我仍然可以获得 MD5 或 SHA1 签名的证书。
是否可以在任何 (https) 服务器上根据客户端在首次连接时发送的 ClientHello 块中包含的传入 TLS 版本提供不同的证书?
我相信应该可以通过编写一个小型“代理”来读取从客户端传入的前几个字节,然后将连接拼接到在最坏情况下为不同请求提供服务的备用端口,但如果可能的话我更愿意如果现有的 Web 服务器确实支持此类功能,请避免这种情况。
旁白:据我所知,SSL/TLS 协议确实包含针对降级攻击的保护,因此,如果服务器支持 1.2 并且客户端也支持 1.2,那么如果发生降级到 1.0,则连接应该终止(如果发生主动人入攻击) -中间攻击)。我相信这应该至少尽可能地降低提供 MD5 或 SHA1 签名证书的风险,同时仍然支持旧的 SSL/TLS 版本。
答案1
Nginx 及其 lua 扩展和 ssl 部分可以根据握手的开始以及客户端发送的内容选择要公开的证书,ClientHello
但可能不是您所需要的(支持的算法列表)。
完整的文档位于https://github.com/openresty/lua-resty-core/blob/master/lib/ngx/ssl.md和https://github.com/openresty/lua-nginx-module/#ssl_certificate_by_lua_block
它指出:
它对于根据每个请求设置 SSL 证书链和相应的私钥特别有用。
...
人们还可以利用来自客户端的 SSL 握手请求做一些有趣的事情,例如选择性地拒绝使用 SSLv3 协议甚至更低版本的旧 SSL 客户端。
您可以通过函数raw_client_addr
和轻松访问客户端或服务器 IP(对于多宿主 IP) raw_server_addr
,以及客户端通过读取 SNI 部分尝试访问的主机名server_name
。根据文档,我看不到访问客户端 ClientHello 的其他部分,但是如果您可以根据 IP 来区分客户端,或者如果您有两个单独的服务器名称,则您可能可以找到上述解决方案一个人可能会与特定的证书绑定在一起。
阅读https://github.com/openresty/lua-nginx-module/blob/master/src/ngx_http_lua_ssl_certby.c我没有看到访问客户端发送的密码套件列表的特定方法。然而,这段代码从 openssl 库获取所有底层“SSL”信息,因此我怀疑您想要的在技术上是可能的,但只需要编码。
现在还有两点:
1) “假设我仍然可以获得 MD5 或 SHA1 签名的证书。”
这可能很难。至少来自默认操作下的公共已知 CA。 CAB 论坛要求(https://cabforum.org/wp-content/uploads/CA-Browser-Forum-BR-1.6.3.pdf)第 38 页有此内容:
用户证书
摘要算法:SHA1*、SHA-256、SHA-384 或 SHA-512
* 根据第 7.1.3 节中定义的标准,SHA-1 可以与 RSA 密钥一起使用。
进而:
7.1.3.算法对象标识符
自 2016 年 1 月 1 日起,CA 不得使用 SHA-1 哈希算法颁发任何新的订户证书或从属 CA 证书。
2)“据我了解,SSL/TLS 协议确实包含针对降级攻击的保护,因此,如果服务器支持 1.2 并且客户端也支持 1.2,那么如果发生降级到 1.0,则连接应该终止(在主动手动操作的情况下)中间攻击)。”
是的,但前提是使用扩展TLS_FALLBACK_SCSV
,并且可能禁止在现有会话期间客户端重新协商。看https://crypto.stackexchange.com/questions/19673/how-does-tls-fallback-scsv-help#19674进行解释,但引用其核心部分:
本质上,TLS_FALLBACK_SCSV 允许客户端在降级连接尝试中以不会触发服务器错误的方式发送隐藏版本号。
维基百科页面位于https://en.wikipedia.org/wiki/Transport_Layer_Security还详细讨论了有关降级攻击的事情。
顺便说一句,这在 TLS 1.3 中得到了改进,引用了 4.1.3。来自 RFC8446 的服务器问候:
TLS 1.3 在服务器的随机值中嵌入了降级保护机制。协商 TLS 1.2 或更低版本以
响应 ClientHello 的 TLS 1.3 服务器必须
在其 ServerHello 中专门设置其随机值的最后 8 个字节。
和
对于所有握手模式,完成的 MAC(以及签名(如果存在))可防止降级攻击。此外,
如第 4.1.3 节所述,在随机数中使用某些字节
可以检测降级到以前的 TLS 版本。
有关 TLS 1.3 和降级的更多详细信息,请参阅[BBFGKZ16]。
答案2
我有一个非常相似的问题。 我不相信您会找到能够满足您要求的服务器。 我也认为你应该停止寻找一个:
您不应依赖 MD5 或 SHA1 证书来保护任何连接。这些证书被认为容易受到攻击,因为存在有人可以伪造这些证书的风险。所有客户端现在都应该拒绝旧的 MD5 和 SHA1 证书。
您应该避免任何客户端通过不安全的连接与您的服务器进行通信。如果任何客户端或服务器无法升级,那么您应该将它们放入自己的安全沙箱中。
如何解决问题
和您一样,我也支持无法升级的旧软件。无论安全建议是什么,我们都必须利用我们现有的资源。
我建议隧道。它作为独立服务器运行,转发它收到的所有连接:首先对它们进行加密或解密。
要使用它,您最好将其安装在旧主机上。在旧软件上禁用 SSL 并将其配置为以未加密方式连接到 stunnel,而不是使用(不安全)加密连接到您的服务器:
[ "Sandbox" ] [ Wherever ]
[[ old box ]] [[ Wherever ]]
[[[ old Client ] ---->[ stunnel client ]]] ---->[[[ actual server ]]]
如果无法将其安装在同一个盒子上,则将其安装在新盒子上安全地连接到旧主机。这可能只是插入同一交换机的树莓派:
[ Securely on the same LAN ("Sandbox") ] [ Wherever ]
[[ old box ] [ new box ]] [[ Wherever ]]
[[[ old Client ]] ---->[[ stunnel client ]]] ---->[[[ actual server ]]]
如果旧软件拒绝未加密连接,那么您可以再次使用 stunnel,充当提供旧 MD5 或 SHA1 证书的服务器。同样,两者应该物理连接,因为您应该考虑与旧证书的连接,就像它未加密一样:
[ Securely on the same LAN ("Sandbox") ] [ Wherever ]
[[ old box ] [ new box ]] [[ Wherever ]]
[[[ old Client ]] ---->[[ stunnel server ]---->[ stunnel client ]]] ---->[[[ actual server ]]]