2009年秋に、SSL/TLSプロトコルの問題が見つかりました。 IETF TLS Working Groupによってプロトコルの修正が開発され、JDKの現行バージョンにはこの修正が含まれています。 このセクションでは、このプロトコル修正を含まない以前の実装との通信時における相互運用性の問題を含め、状況をさらに詳しく説明します。
この脆弱性により、選択されたプレーン・テキストを接頭辞としてTLS接続に注入できるというMan-In-The-Middle (MITM)攻撃を許していました。 この脆弱性は、クライアントとサーバーがセッションのネゴシエーションに成功した後、傍受されたネットワーク通信を攻撃者が復号化または変更することを許すものではありません。
詳細は、CVE-2009-3555 (に投稿されたMitre's 「一般的な脆弱性およびエクスポージャ・リスト」、2009)を参照してください。
この問題の修正は、2つのフェーズに分けて扱われています。
フェーズ1: プロトコル修正が開発されるまで、SSL/TLSの再ネゴシエーションをデフォルトで無効化する中間修正が、「March 30, 2010 Java SE and Java for Business Critical Patch Update」から利用できるようになりました。
フェーズ2: IETFによって、再ネゴシエーション・プロトコルの問題を扱うRFC 5746が発表されました。 次の表に、RFC 5746を実装してセキュアな再ネゴシエーションをサポートする修正を含むJDKおよびJREリリースを示します。
JDKファミリ | 脆弱性のあるリリース | フェーズ1の修正(再ネゴシエーションの無効化) | フェーズ2の修正(RFC 5746) |
---|---|---|---|
JDKおよびJRE 6 | Update 18以前 | 更新19-21 | Update 22 |
JDKおよびJRE 5.0 | Update 23以前 | 更新24-25 | Update 26 |
JDKおよびJRE 1.4.2 | Update 25以前 | 更新26-27 | Update 28 |
ノート: 再ネゴシエーションを必要としないアプリケーションはフェーズ2のデフォルト構成に影響を受けません。 ただし、再ネゴシエーションを必要とするアプリケーション(最初は匿名のクライアント・ブラウズを許可するが、後でSSL/TLS認証済のクライアントを要求するWebサーバーなど)は:
SunJSSE実装は、RFC 5746に準拠したピアへの接続について、再ネゴシエーションをデフォルトで再び有効にします。 つまり、セキュアに再ネゴシエーションを行うためには、クライアントとサーバーが両方ともRFC 5746をサポートする必要があります。 まだアップグレードされていないピアとの接続について、SunJSSEではある程度の相互運用性モードが提供されていますが、ユーザーがクライアントとサーバーの両方の実装をできるだけ早く更新することを強く推奨します。
フェーズ2修正により、SunJSSEは現在3つの再ネゴシエーション相互運用性モードを用意しています。 どのモードもRFC 5746のセキュアな再ネゴシエーションを完全にサポートしていますが、アップグレードされていないピアと通信する場合、次のような意味合いが加わります。
厳密モード: クライアントとサーバーの両方がRFC 5746にアップグレードされていること、および適切なRFC 5746メッセージを送信することが求められます。 そうでない場合、初期の(または後続の)ハンドシェークが失敗して接続が切断されます。
相互運用モード(デフォルト): 正しいRFC 5746メッセージの使用はオプションですが、適切なメッセージが使用されない場合はレガシーの(元のSSL/TLS仕様の)再ネゴシエーションが無効になります。 最初のレガシー接続は許可されますが、レガシーの再ネゴシエーションは無効化されます。 これはセキュリティと相互運用性の最適な組み合わせであるため、デフォルト設定です。
セキュアでないモード: レガシーの再ネゴシエーションを完全に許可します。 レガシーのピアとの相互運用性がもっとも高いですが、本来のMITM攻撃に対して脆弱です。
3つのモード区分は、アップグレードされていないピアとの接続にのみ影響します。 すべてのクライアントおよびサーバーで厳密モード(完全なRFC 5746モード)を使用することが望ましいのですが、配備されているすべてのSSL/TLS実装がRFC 5746をサポートするようになるまである程度時間がかかるため、今のところは相互運用モードがデフォルトになっています。
次の表には、クライアントおよび/またはサーバーがRFC 5746をサポートするように更新されるかどうかのさまざまな場合のモードに関する相互運用性情報が含まれています。
Client | Server | モード |
---|---|---|
更新しました | 更新しました |
すべてのモードで再ネゴシエーションがセキュリティ保護されます。 |
レガシー 脚注1 | 更新しました |
|
更新しました | レガシー 脚注1 | |
レガシー 脚注1 | レガシー 脚注1 | 既存のSSL/TLS動作を行い、MITM攻撃に対して脆弱です。 |
脚注1 「レガシー」とは元のSSL/TLS仕様を意味します(つまり、RFC 5746でない)。
脚注2 SunJSSEフェーズ1実装は、明示的に再有効化されないかぎり再ネゴシエーションを拒否します。 再ネゴシエーションが再有効化された場合、それらは正しいRFC 5746メッセージを送信しないため、RFC 5746に準拠したピアによって「レガシー」として扱われます。
脚注3 SSL/TLSでは、再ネゴシエーションをいずれの側からでも開始できます。 フェーズ1修正のように、アップグレードされていないピアと相互運用モードで通信しているアプリケーションが(SSLSocket.startHandshake()
またはSSLEngine.beginHandshake()
を使用して)再ネゴシエーションを開始しようとすると、アプリケーションはSSLHandshakeException
(IOException
)を受け取り、接続は停止されます(handshake_failure
)。 まだアップグレードされていないピアから再ネゴシエーション要求を受け取ったアプリケーションは、現在の接続のタイプに応じて応答します。
no_renegotiation(100)
タイプの警告メッセージがピアに送信され、接続は開いたままになります。 古いバージョンのSunJSSEは、no_renegotiation
アラートを受け取ると接続を停止します。 SSLHandshakeException
を受け取り、接続は閉じられます(handshake_failure
)。 no_renegotiation
アラートはSSLv3仕様に定義されていません。 モードを設定するために、次のシステム・プロパティを使用します。
sun.security.ssl.allowUnsafeRenegotiation
(フェーズ1で導入)は、レガシー(安全でない)再ネゴシエーションを許可するかどうかを制御します。sun.security.ssl.allowLegacyHelloMessages
(フェーズ2で導入)は、適切なRFC 5746メッセージを必要とすることなくピアがハンドシェーク・プロセスを実行することを許可します。モード | allowLegacyHelloMessages |
allowUnsafeRenegotiation |
---|---|---|
厳格 | false | false |
相互運用(デフォルト) | true | false |
安全でない | true | true |
注意: セキュアでないSSL/TLS再ネゴシエーションは、脆弱性が再確立されるため、再有効化しないでください。
システム・プロパティを設定することによって特定のモードを構成する方法については、「java.lang.Systemプロパティの設定方法」を参照してください。
すべてのピアは、できるだけ早くRFC 5746準拠の実装に更新する必要があります。 このRFC 5746修正を適用しても、再ネゴシエーションが必要な場合は、アップグレードされていないピアとの通信に影響が生じます。 推奨されるいくつかの方法を次に示します。
ピアを再構築して再ネゴシエーションを要求しないようにする。
再ネゴシエーションは通常、Webサーバーが最初は匿名のクライアント・ブラウズを許可するが、後でSSL/TLS認証済クライアントを要求する場合や、Webサーバーが最初は弱い暗号化方式群を許可するが、後で強い暗号化方式群を必要とする場合に、Webサーバーによって使用されます。 代替策は、最初のネゴシエーション中にクライアント認証および強い暗号化方式群を必要とすることです。 これを行うには、2つの選択肢があります。
アプリケーションに、あるポイントに到達して、再ネゴシエーションが必要になるまでの「ブラウズ・モード」がある場合、「ブラウズ・モード」を削除し、すべての初期接続を強化するようにサーバーを再構築できます。
サーバーを2つのエンティティに分割して、1つのエンティティ上でブラウズ・モードを実行し、2つ目のエンティティをよりセキュアなモードで使用します。 ネゴシエーション・ポイントに到達したら、関連情報をサーバー間で転送します。
これらのどちらのオプションも、ある程度の作業が必要ですが、元のセキュリティ上の欠陥が再度発生することはありません。
システム・プロパティを使用して、再ネゴシエーション相互運用性モードを「セキュアでない」に設定します。
情報と警告については、「フェーズ2修正の説明」を参照してください。
RFC 5746では2つの新しいデータ構造が定義されており、上級ユーザーのために、ここで説明します。
これらのいずれも、実装がRFC 5746に準拠していることと、セキュアな再ネゴシエーションが実行できることを通知するために使用できます。 関連する技術的な議論については、2009年11月から2010年2月までのIETFの電子メールによる議論を参照してください。
RFC 5746により、クライアントは最初のClientHello
でSCSVまたはRIを送信できます。 相互運用性を最大限に高めるため、SunJSSEはデフォルトでSCSVを使用しますが、これは、いくつかのTLSサーバー/SSLサーバーが不明な拡張機能を正しく処理できないためです。 有効化された暗号化方式群(SSLSocket.setEnabledCipherSuites()
またはSSLEngine.setEnabledCipherSuites()
)にSCSVが存在することによって、最初のClientHello
内でSCSVを送信するか、あるいはRIをかわりに送信すべきかどうかが判別されます。
SSLv2はSSL/TLS拡張機能をサポートしません。 SSLv2Hello
プロトコルが有効化された場合、SCSVが最初のClientHello
内で送信されます。
前述のとおり、フェーズ1修正は、RFC 5746に準拠した修正が開発されるまでの間、再ネゴシエーションをデフォルトで無効にするためのものでした。 再ネゴシエーションは、sun.security.ssl.allowUnsafeRenegotiation
システム・プロパティを設定することによって再び有効化できました。 フェーズ2修正では同じsun.security.ssl.allowUnsafeRenegotiation
システム・プロパティを使用するだけでなく、それにRFC 5746メッセージを使用させる必要もあります。
すべてのアプリケーションを、できるだけ早くフェーズ2 RFC 5746修正にアップグレードする必要があります。
次の場合、SSL/TLS再ネゴシエーションでサーバー証明書を変更することは、安全でないことがあります。
2つの証明書は、次の場合に、同じアイデンティティを表すと見なせます。
JDK 8u25以降では、SSL/TLS再ネゴシエーションでの安全でないサーバー証明書の変更は、デフォルトでできません。 新しいシステム・プロパティjdk.tls.allowUnsafeServerCertChange
を使用して、SSL/TLS再ネゴシエーションにおける安全でないサーバー証明書の変更を制限するかどうかを定義できます。
このシステム・プロパティのデフォルト値はfalse
です。
注意: どうしても必要でないかぎり、このシステム・プロパティを"true"
に設定しないでください。安全でないサーバー証明書変更の脆弱性が再び確立される可能性があります。