要約

  • 従来のTLS再ネゴシエーションは既存の暗号化チャネル内で新しい握手を行ったが、二つの握手を暗号学的に結び付けていなかった。
  • RFC 5746は直前のFinishedメッセージの証拠を次の握手に持ち込ませ、TLS 1.3は再ネゴシエーション自体を廃止した。

一つの接続に現れた二人の送信者

攻撃者はまずサーバーとの正規のTLS接続を作り、任意のアプリケーション前置データを送る。それは未完成のHTTP要求や、後続バイトによって意味が完成する命令でもよい。次に攻撃者は、被害者が始めた新しいTLS握手を、その既に暗号化されたサーバー側接続へ通す。

被害者には実サーバーとの初回握手に見える。一方、サーバーには攻撃者の接続上の再ネゴシエーションに見える。新しい握手が完了しても、攻撃者は被害者の後続通信を読めない。壊れたのは機密性そのものではなく帰属である。サーバーは攻撃者の前置データと被害者の認証済みデータを一つのアプリケーション・ストリームとして扱い、同じ主体の操作だと判断し得る。

RFC 5746の時系列図が示したのは、トランスポートの連続、暗号化の連続、アプリケーションのtranscriptの連続が別物だということだった。同じTCP接続が開いている事実は、認証状態が変わった前後のバイトを同じ作者に帰属させる根拠にはならない。

過去の握手を証拠として保存する

修正では接続ごとに、安全な再ネゴシエーションを使うかというフラグと、直前の握手でクライアントとサーバーがFinishedメッセージに送った二つの verify_data を保存する。これらは双方が以前の握手内容を確認した証拠である。

RFC 5746が定義した renegotiation_info 拡張の型は 0xff01 である。初回握手では結合フィールドを空にし、過去を装わずに対応能力だけを知らせる。再ネゴシエーションのClientHelloには保存済みのクライアント verify_data を入れ、ServerHelloにはクライアントとサーバーの値を連結して入れる。どちらかが拡張の欠落や不一致を見つければ、握手を中止しなければならない。

攻撃者は被害者の握手を転送できても、その握手に攻撃者側接続の過去の証拠を正しく持たせることはできない。安全性は「古い鍵の内側で実行された」ことではなく、「どの過去を継ぐかを認証して示した」ことから生まれる。

互換性を抱えた修正

当時の一部実装は、未知のClientHello拡張を無視すべきところで接続を失敗させた。RFC 5746はそこで TLS_EMPTY_RENEGOTIATION_INFO_SCSV も定義した。暗号スイート一覧に置かれるが本物の暗号スイートではなく、選択もできない。古いサーバーが受け入れやすい形で、空の初期 renegotiation_info と同じ意思を伝える信号だった。

それでも、応答しないサーバーが危険な再ネゴシエーションを許すのか、再ネゴシエーションを全面的に拒否して安全なのかを、クライアントはTLSだけでは判別できなかった。確実性を求めれば接続を切り、互換性を求めれば証明のない相手を残す。この移行は、証拠の欠如をどう扱うかを運用者の明示的な選択にした。

TLS 1.3は修理ではなく削除を選んだ

RFC 8446はTLS 1.3で再ネゴシエーションを禁止する。不適切な時点のClientHelloは接続終了の対象になる。KeyUpdateとハンドシェイク後認証は残るが、目的を分けた個別機構であり、旧来の汎用的な再ネゴシエーションを復活させるものではない。

RFC 9325はTLS 1.2について、クライアントとサーバーの双方に renegotiation_info の実装を求め、サーバーが確認しなければクライアントは接続を終了すべきだとする。RFC群は実被害件数や現在の利用数を示してはいない。しかし欠陥、修正、廃止の経路は明確である。鍵や認証主体が変わる遷移では、何を継承するのかを暗号学的に証明しなければならない。開いたままのソケットはその証明ではない。

出典