【问题标题】:Java seems to accept certificate with ANY CN [duplicate]Java似乎接受任何CN的证书[重复]
【发布时间】:2017-09-07 20:47:08
【问题描述】:

此问题与question pointed to 不重复。在提到的问题中没有任何关于 TLS 自身不执行主机名验证的事实。

我有 Java 中的 ActiveMQ 实例和客户端。客户端使用带有工厂 org.apache.activemq.ActiveMQSslConnectionFactory 的 JMSTemplate (org.springframework.jms.core.JmsTemplate)。我创建了自签名证书并使用它们信任存储和密钥库。两个程序都读取信任库和密钥库,我通过运行两个程序来检查它

-Djavax.net.debug=all

现在我的问题是客户端似乎完全忽略了服务器主机名验证。客户端使用 URL 连接到 ActiveMQ:

ssl://localhost:61616?jms.useCompression=true

现在,我尝试检查如果我更改 ActiveMQ 证书上的 CN 是否一切都会按预期失败,但结果并不顺利。我将 CN 改为例如:

CN=google.com

或到:

CN=some.random.xxx333aaa.net.pp

但所有这些值似乎都适用于 Java。另请注意,没有 SAN(即 subjectAltNames)。还有什么我试图用这样的证书连接到 ActiveMQ 但安装在不同的机器上,看起来一切正常。这不是我想要的。

另外:我终于卸载了所有 Java 版本并安装了 1.8.0_144,只使用 JDK 安装程序,在两个地方都安装了 jce_policy-8(它同时安装了 JRE 和 JDK),在远程机器上也做了同样的事情。

【问题讨论】:

  • 您说客户端和服务器正在使用包含服务器证书的相同信任库。客户端将接受证书,因为它是“受信任的”,甚至是过期的,或者 CN 与服务器名称不对应。尝试仅从客户端信任库中删除它,然后连接将失败。这不是问题
  • @pedrofb 等等,你是不是想告诉我,仅仅因为我相信一些 CA,java 接受任何由该 CA 签名的证书,无论主机名是否有效?它不会与 PKI 似乎提供的功能完全相反吗?
  • @ElliottFrisch 谢谢,但它没有回答我的问题——我只想知道为什么默认情况下 Java 似乎不验证主机名。我认为应该这样做,因为否则人们不会寻找禁用此检查的方法。那么为什么它在我的情况下不起作用?我不知道,这就是我问的原因。
  • @pedrofb 我有一个主公钥/私钥对+证书,用于签署代理(ActiveMQ)的证书(带有私钥)和客户端(我的基于Spring的Java程序)的证书(也带有私钥) )。所以他们两个的信任库都包含主证书,他们各自的密钥库在证书中包含他们的公钥,并且都有他们的私钥。我使用 OpenSSL 创建了所有这些,将所有内容打包到 PKCS12 存储中,并将 PKCS12 导入 JKS。我认为这可以防止您提出的情况。但我想我找到了答案,请查看我的回复。

标签: java ssl certificate spring-jms


【解决方案1】:

如果您检查 RFC 2246 (TLS) 和 RFC 2818 (HTTPS),您会发现主机名验证是 HTTPS 的一部分,而不是 TLS 的一部分。在 TLS 中,执行授权步骤完全取决于应用程序。

所以事实上我的问题是:如何强制主机名验证?

this answer

【讨论】:

  • 这基本上是我在一小时前的回答中写的。为什么你把这个问题标记为重复?您指出的问题是否在默认情况下不执行主机名验证的任何地方提到?我在问题、答案和 cmets 中找不到任何关于它的内容。
  • 这个答案比你的答案有了相当大的改进,它引用了 RFC,而不是教程和错误报告。 此答案 提供了 TLS 不执行主机名验证的信息以及规范性参考。该链接回答了我在引用之前仔细引用了您所写内容的问题,并且没有其他目的被引用。
  • 好的,已接受答案。当然,您确实意识到 RFC 形式的文字墙基本上不是答案,因为通读整个内容并理解其后果需要几天甚至几周的工作?
  • 垃圾。 “主机名验证是 HTTPS 的一部分,而不是 TLS 的一部分”。这就是答案。我意识到我已经回答了这个问题。两个问题。带引文。对“主机名验证”的文本搜索在 RFC 2246 和 RFC 2818 中没有任何结果。我没有发布任何文字墙,也没有仅仅列出 RFC 编号。
  • “有引用” - 抱歉,但指向 RFC 不是引用。但是,是的,你回答了,我接受了,毫无疑问。
【解决方案2】:

好的,我想我找到了答案。检查此链接:

https://issues.apache.org/jira/browse/AMQ-5443

以及上面链接中提到的链接:

https://tersesystems.com/2014/03/23/fixing-hostname-verification/

似乎针对我认为的 TLS 不执行主机名验证。这绝对是惊人的,但似乎情况确实如此。如果没有人会提供更好的答案,我会接受我自己的答案。

编辑:另见:

https://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html

具体看这部分:

密码套件选择和远程实体验证 SSL/TLS 协议定义了一系列特定的步骤来确保受保护的连接。但是,密码套件的选择直接影响连接所享有的安全类型。例如,如果选择了匿名密码套件,则应用程序无法验证远程对等方的身份。如果选择了没有加密的套件,则无法保护数据的隐私。此外,SSL/TLS 协议未指定接收到的凭据必须与对等方可能发送的凭据相匹配。如果连接以某种方式被重定向到恶意对等方,但根据当前的信任材料,恶意用户的凭据是可接受的,则该连接将被视为有效。

使用原始 SSLSocket 和 SSLEngine 类时,您应该始终在发送任何数据之前检查对等方的凭据。 SSLSocket 和 SSLEngine 类不会自动验证 URL 中的主机名是否与对等方凭据中的主机名匹配。如果未验证主机名,则可能会通过 URL 欺骗来利用应用程序。

HTTPS(HTTP Over TLS)等协议确实需要主机名验证。应用程序可以使用 HostnameVerifier 覆盖默认的 HTTPS 主机名规则。有关详细信息,请参阅 HttpsURLConnection。

【讨论】:

  • 您对 docs.oracle 的链接的降价已损坏。此外,您应该知道(正如 EJP 所暗示的那样)检查 Subject.CN 的 TLS 已经过时了。 对于网络 CABforum.org 多年来一直要求所有证书都具有 SubjectAltName (SAN) 扩展,所有主要浏览器和 HttpsURLConnection 使用 SAN 代替 Subject 如果存在,最近的 Chrome 忽略 主题和需要 SAN。 RFC 6125 也鼓励其他(基于名称的)协议这样做,尽管没有人为他们如此有力地推动它。
  • 谢谢,这就是我正在寻找的那种评论/答案。
猜你喜欢
  • 2019-09-24
  • 2011-12-17
  • 1970-01-01
  • 2012-02-21
  • 1970-01-01
  • 1970-01-01
  • 2012-09-24
  • 2014-06-01
  • 1970-01-01
相关资源
最近更新 更多