web-dev-qa-db-ja.com

「javax.net.ssl.SSLHandshakeException:再ネゴシエーション中にサーバー証明書の変更が制限される」とはどういう意味ですか?

Oracle jdk 1.7.0_71およびTomcat 7.0.55を使用します。残念ながら、サーバー間のSSL接続中に次の例外が発生し始めました。

javax.net.ssl.SSLHandshakeException: server certificate change is restrictedduring renegotiation

その意味?それを防ぐ方法は?

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
41
Michael

クライアントレイヤーコードのこのエラーメッセージは、最近のJavaアップデート。 JREをすぐに更新できない場合の回避策:

最初のオプションは、HTTPS接続を確立するときにTLSプロトコルを強制することです:

HttpClientを4.3.6よりも新しいバージョンに更新できる場合、SSLv3はデフォルトで無効になり、コードはそのような例外を報告しなくなります。

HttpClientのバージョンをアップグレードできない場合は、この回答のコードを使用して、プロトコルをTLSに制限する必要があります。 https://stackoverflow.com/a/26439487/73779

Java 7ランタイムからの他のhttpアクセスの場合、次のシステムプロパティを設定する必要があります

-Dhttps.protocols="TLSv1"

詳細については、こちらをご覧ください。 Java HTTPクライアントとPOODLE


2番目のオプションは、クライアントチェックを緩和して、次のプロパティとの再ネゴシエーションを許可することです。

-Djdk.tls.allowUnsafeServerCertChange=true 
-Dsun.security.ssl.allowUnsafeRenegotiation=true


3番目のオプションは、サーバー証明書を「改善」して、クラスターメンバーのすべてのIPアドレスをサブジェクトの別名として- Burpフォーラムのこの投稿


4番目のオプションは、この証明書/再ネゴシエーションのチェックが追加される前にJavaバージョンをダウングレードすることです、したがって7u41の前(確認予定)

アップデートこのバグのある動作は、JDKアップデート7u85および8u60で修正されました。 JDK-8072385 参照を見つけたことに対するPadaの功績。

48
Yves Martin

次のコードは、次の条件のエンタープライズ環境で機能しました。

  • シームレスな(実行時)証明書の更新は重要な要件です
  • アプリケーションで使用されるHTTPClientを更新するにはコストがかかりすぎます
  • httpsプロトコルを「TLSv1」に制限しても効果はありません
  • アプリケーションはJNLPで提供されますJavaクライアントであり、 "allowUnsafeServerCertChange"と "allowUnsafeRenegotiation"のいずれもJNLP引数を介してクライアントアプリケーションに渡すことはできません(JWSがそれらをブロックしていると推測しますセキュリティ上の理由から)
  • アプリケーションのbootstrap=の間に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);
        }
    }
    

注意してくださいこれはハッキング(脆弱性の導入)と見なされ、信頼できる環境で使用される必要があります。この道を進む前に、Yvesの答えにあるすべてのオプションを試してください。

5
Mert Z.

これは、間違ったIPアドレスを指す1つ以上の負荷分散ターゲットを持つhaproxyなど、接続の構成が誤っているために発生する可能性があるため、要求のXパーセントが異なる証明書を取得します。

2
nbryant

サーバー側が証明書を更新したため、この問題が発生しました。この前に、私たちのクライアントはうまく機能していました。プログラムを再起動するだけで、通常の状態に戻りました。

1
Charlie

この問題が発生し、クライアントがロードバランサーの背後にある別の証明書でサービスを呼び出していることが判明しました。

0
John