什么意思是"javax.net.ssl.SSLHandshakeException:服务器证书更改在重新协商期间受到限制"以及如何防止它?

Mic*_*ael 41 ssl tomcat java-7

我们使用Oracle jdk 1.7.0_71和Tomcat 7.0.55.不幸的是,我们在服务器之间的SSL连接期间开始出现以下异常:

javax.net.ssl.SSLHandshakeException: server certificate change is restrictedduring renegotiation
Run Code Online (Sandbox Code Playgroud)

这是什么意思?怎么预防呢?

Tomcat重启后异常消失.

完整堆栈:

Caused by: javax.net.ssl.SSLHandshakeException: server certificate change is restrictedduring renegotiation
        at sun.security.ssl.Alerts.getSSLException(Alerts.java:192) ~[?:1.7.0_71]
        at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1884) ~[?:1.7.0_71]
        at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:276) ~[?:1.7.0_71]
        at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:266) ~[?:1.7.0_71]
        at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1402) ~[?:1.7.0_71]
        at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:209) ~[?:1.7.0_71]
        at sun.security.ssl.Handshaker.processLoop(Handshaker.java:878) ~[?:1.7.0_71]
        at sun.security.ssl.Handshaker.process_record(Handshaker.java:814) ~[?:1.7.0_71]
        at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1016) ~[?:1.7.0_71]
        at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1312) ~[?:1.7.0_71]
        at sun.security.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:702) ~[?:1.7.0_71]
        at sun.security.ssl.AppOutputStream.write(AppOutputStream.java:122) ~[?:1.7.0_71]
        at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:82) ~[?:1.7.0_71]
        at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:140) ~[?:1.7.0_71]
        at org.apache.commons.httpclient.methods.EntityEnclosingMethod.writeRequestBody(EntityEnclosingMethod.java:506) ~[commons-httpclient-3.1.jar:?]
        at org.apache.commons.httpclient.HttpMethodBase.writeRequest(HttpMethodBase.java:2114) ~[commons-httpclient-3.1.jar:?]
        at org.apache.commons.httpclient.HttpMethodBase.execute(HttpMethodBase.java:1096) ~[commons-httpclient-3.1.jar:?]
        at org.apache.commons.httpclient.HttpMethodDirector.executeWithRetry(HttpMethodDirector.java:398) ~[commons-httpclient-3.1.jar:?]
        at org.apache.commons.httpclient.HttpMethodDirector.executeMethod(HttpMethodDirector.java:171) ~[commons-httpclient-3.1.jar:?]
        at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:397) ~[commons-httpclient-3.1.jar:?]
        at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:323) ~[commons-httpclient-3.1.jar:?]
        at org.springframework.remoting.httpinvoker.CommonsHttpInvokerRequestExecutor.executePostMethod(CommonsHttpInvokerRequestExecutor.java:205) ~[spring-web-3.2.9.RELEASE.jar:3.2.9.RELEASE]
        at org.springframework.remoting.httpinvoker.CommonsHttpInvokerRequestExecutor.doExecuteRequest(CommonsHttpInvokerRequestExecutor.java:140) ~[spring-web-3.2.9.RELEASE.jar:3.2.9.RELEASE]
        at org.springframework.remoting.httpinvoker.AbstractHttpInvokerRequestExecutor.executeRequest(AbstractHttpInvokerRequestExecutor.java:136) ~[spring-web-3.2.9.RELEASE.jar:3.2.9.RELEASE]
        at org.springframework.remoting.httpinvoker.HttpInvokerClientInterceptor.executeRequest(HttpInvokerClientInterceptor.java:192) ~[spring-web-3.2.9.RELEASE.jar:3.2.9.RELEASE]
        at org.springframework.remoting.httpinvoker.HttpInvokerClientInterceptor.executeRequest(HttpInvokerClientInterceptor.java:174) ~[spring-web-3.2.9.RELEASE.jar:3.2.9.RELEASE]
        at org.springframework.remoting.httpinvoker.HttpInvokerClientInterceptor.invoke(HttpInvokerClientInterceptor.java:142) ~[spring-web-3.2.9.RELEASE.jar:3.2.9.RELEASE]
        ... 160 more
Run Code Online (Sandbox Code Playgroud)

Yve*_*tin 48

客户端层代码中的此错误消息是最近Java更新中"SSL V3.0 Poodle漏洞 - CVE-2014-3566"之后的代码强化的结果.这是一个错误 - 如果你不能立即更新你的JRE,这里有解决办法:

第一个选项是在建立HTTPS连接时强制使用TLS协议:

如果您可以将HttpClient更新为比4.3.6更新的版本,则默认情况下将禁用SSLv3,并且您的代码不应再报告此类异常.

如果您无法升级HttpClient版本,则必须使用此答案的代码将协议限制为TLS:https://stackoverflow.com/a/26439487/737790

对于Java 7运行时的其他http访问,必须设置以下系统属性

-Dhttps.protocols="TLSv1"
Run Code Online (Sandbox Code Playgroud)

完整的详细信息可以在这里找到:Java http客户端和POODLE


第二个选项是放宽客户端检查以仍允许使用以下属性进行重新协商:

-Djdk.tls.allowUnsafeServerCertChange=true 
-Dsun.security.ssl.allowUnsafeRenegotiation=true
Run Code Online (Sandbox Code Playgroud)


第三个选项是根据Burp论坛中的这篇文章 "改进"您的服务器证书,以包括您的集群成员的所有IP地址作为主题备用名称


第四个选项是在添加此证书/重新协商检查之前降级Java版本,因此在7u41之前(待确认)

更新此错误行为现已在JDK更新7u85和8u60中得到修复.Pada找到了JDK-8072385的参考资料.

  • 据我所知,造成这个问题的代码是:http://hg.openjdk.java.net/jdk7u/jdk7u/jdk/rev/eabde5c42157现在好像他们修复了它:https:// bugs.openjdk.java.net/browse/JDK-8072385因此修复程序将包括在:7u85和8u60 (5认同)
  • 我现在正在使用 `https.protocols="TLSv1"` 运行 Java 8u60,但已部署的产品仍然面临此错误。肯定还没有修好。 (2认同)

Mer*_* Z. 5

在以下条件下,以下代码片段在企业环境中为我们工作;

  • 无缝(运行时)证书更新是一项关键要求
  • 更新应用程序中使用的HTTPClient成本太高
  • 将https协议限制为"TLSv1"没有效果
  • 该应用程序是一个JNLP服务的Java客户端,不允许"allowUnsafeServerCertChange"和"allowUnsafeRenegotiation"通过JNLP参数传递给客户端应用程序(我猜JWS由于安全原因阻止它们)
  • 在应用程序的引导期间通过System.setProperty()调用设置"allowUnsafeServerCertChange"和"allowUnsafeRenegotiation"没有效果.

    if (e.getCause() instanceof SSLHandshakeException) {
        logger.debug("server https certificate has been altered");
        try {
            Class<?> c = Class.forName("sun.security.ssl.ClientHandshaker");
            Field allowUnsafeServerCertChangeField = c.getDeclaredField("allowUnsafeServerCertChange");
            allowUnsafeServerCertChangeField.setAccessible(true);
            Field modifiersField = Field.class.getDeclaredField("modifiers");
            modifiersField.setAccessible(true);
            modifiersField.setInt(allowUnsafeServerCertChangeField, allowUnsafeServerCertChangeField.getModifiers() & ~Modifier.FINAL);
            allowUnsafeServerCertChangeField.set(null, true);
            logger.debug("client has been updated in order to support SSL certificate change (re-negotiation) on runtime.");
        }
        catch (Exception ex) {
            logger.debug("client cannot be updated to support SSL certificate change (re-negotiation) on runtime. Please restart the application.", ex);
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)

请注意,这应该被视为黑客(引入漏洞),应该在受信任的环境中使用.在走这条道路之前,应该尝试Yves答案中的所有选项.