Java似乎接受任何CN的证书

时间:2017-09-07 20:47:09

标签: java ssl certificate spring-jms

此问题与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),在远程计算机上也是如此。

2 个答案:

答案 0 :(得分:1)

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

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

和上面链接中提到的链接:

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

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

编辑:另见:

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。

答案 1 :(得分:1)

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

  

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

请参阅this answer