Java 似乎接受任何 CN 的证书

Java seems to accept certificate with ANY CN

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

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

检查了它
-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),也在远程机器上做了同样的事情。

好的,我想我找到了答案。检查这个 link:

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

上面link中提到的

和link:

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

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

编辑:另见:

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

具体看这部分:

Cipher Suite Choice and Remote Entity Verification The SSL/TLS protocols define a specific series of steps to ensure a protected connection. However, the choice of cipher suite directly affects the type of security that the connection enjoys. For example, if an anonymous cipher suite is selected, then the application has no way to verify the remote peer's identity. If a suite with no encryption is selected, then the privacy of the data cannot be protected. Additionally, the SSL/TLS protocols do not specify that the credentials received must match those that peer might be expected to send. If the connection were somehow redirected to a rogue peer, but the rogue's credentials were acceptable based on the current trust material, then the connection would be considered valid.

When using raw SSLSocket and SSLEngine classes, you should always check the peer's credentials before sending any data. The SSLSocket and SSLEngine classes do not automatically verify that the host name in a URL matches the host name in the peer's credentials. An application could be exploited with URL spoofing if the host name is not verified.

Protocols such as HTTPS (HTTP Over TLS) do require host name verification. Applications can use HostnameVerifier to override the default HTTPS host name rules. See HttpsURLConnection for more information.

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

So in fact my question is: how to force hostname verification?

参见this answer