要約

  • TLS 1.2 は既存接続の中で新しいハンドシェイクを行えたが、それがどの履歴を継ぐのかを証明しなかった。
  • RFC 5746 は直前のクライアントとサーバーの verify_data を保存し、再ネゴシエーション時に照合させた。

正しい二つのハンドシェイクが作る偽の会話

攻撃者はまずサーバーとの正規の TLS 接続を確立し、自分で選んだアプリケーションデータを送る。次に、被害者のハンドシェイクをその保護済み接続に通す。被害者には初回ハンドシェイクに見えるが、サーバーには攻撃者の接続上の再ネゴシエーションに見える可能性がある。

攻撃者はその後の暗号化トラフィックを読めない。しかし、先に届けたプレフィックスは残る。サーバーは攻撃者のバイト列と、被害者が後から送る認証済みデータを一つのアプリケーション対話として扱えてしまう。HTTPS のアプリケーションが状態境界を分けなければ、攻撃者の入力が被害者の資格情報や Cookie と結び付くことがある。

暗号が破られたのでも、証明書が偽造されたのでもない。どちらのハンドシェイクにも正しい Finished メッセージがあり得た。欠けていたのは、二つのハンドシェイクの間の継続性を示す証拠だった。

直前の Finished を接続状態にする

RFC 5746 は secure_renegotiation フラグを導入し、接続ごとに直前のハンドシェイクのクライアントおよびサーバーの verify_data を保存した。それらは、再利用可能なセッションキャッシュだけの情報ではなく、現在の接続に属する。

型 0xff01 の renegotiation_info 拡張が履歴を次の交渉へ運ぶ。初回ハンドシェイクでは renegotiated_connection は空である。再ネゴシエーションでは、クライアントが保存した client_verify_data を送り、サーバーが自分の値と照合して、クライアント値とサーバー値の連結を返す。クライアントもそれを確認する。必須拡張の欠落や不一致は、致命的な失敗としてハンドシェイクを中止させる。

つまり、ハンドシェイクが完了しただけでは十分でない。それは、この接続の正確な履歴に続く次のハンドシェイクでなければならない。

暗号スイートではなかった互換性信号

古い実装には未知の拡張を含む ClientHello を拒否するものがあった。そこで RFC 5746 は TLS_EMPTY_RENEGOTIATION_INFO_SCSV(0x00,0xFF)を定義し、暗号スイート一覧に置いた。未知のスイートは無視することになっていたため、拡張パーサーに依存せず能力を示せた。

SCSV は交渉される暗号スイートではなく、後続の再ネゴシエーションを束縛する値でもない。初回ハンドシェイクでの互換性信号である。サーバーが安全な再ネゴシエーションを確認しない場合、クライアントは相互運用性と分断攻撃への防御を同時には最大化できない。TLS だけでは、そのサーバーが再ネゴシエーションを全面的に拒否して安全なのか、修復を実装していないのかを区別できないためである。

修復から廃止へ

TLS 1.3 は再ネゴシエーションを禁止する。TLS 1.3 接続で後から届く ClientHello は予期しないメッセージとして扱われる。旧版で確立した接続が再ネゴシエーション中に TLS 1.3 の ClientHello を受け取っても、従来のプロトコル版を維持しなければならず、TLS 1.3 へ昇格できない。KeyUpdate とハンドシェイク後認証は別の機構であり、再ネゴシエーションとは呼べない。

TLS 1.2 について、RFC 9325 はクライアントとサーバーの双方に renegotiation_info の実装を求め、サーバーが拡張を確認しなければクライアントに接続終了を求める。RFC 5746 は複数ハンドシェイクに関する全問題を解決したわけではない。関連する triple-handshake には RFC 9325 が拡張マスターシークレットを別途求める。歴史的な核心は、時間的連続性をアプリケーションの思い込みから認証済みプロトコル属性へ変えたことにある。

出典