security:tls_renegotiation

TLS renegotiation

  • (従来の?) TLS では,サーバ・クライアントのどちらでも,<color red>いつでも</color>,再ネゴシエーションのリクエストを送ることが可能である
    • クライアントトリガだと “Client Hello” メッセージを送る.
    • サーバトリガだと “Hello Request” を送る.
  • 問題は renegotiation では暗号化はされているものの,セッションとして考えると,前のセッションと renegotiation 後のセッションが一続きのセッションであると確認する方法がなかった.
    • Renegotiating TLS のレポートでは,セッション回復 (session resumption) の話が出てくる.セッション回復 (session resumption) が SSL/TLS で定められているが,renegotiation 時に使うような実装はなかった (とのこと)
      • おそらく Session Resumption を使うと,前回の暗号の状態を引き継ぐような事を行うので,セッションとしての連続性が確保される事がいいたいのかと.ただし,再ネゴシエーションの場合はそもそもクライアント認証をする,とか暗号通信のパラメータを変更する必要があるシチュエーションなので,前回の再利用を目的とした Session Resumption とは両立しないんじゃないかと (Renegotiating TLS のレポートには “the two operations were designed for orthogonal purposes.” と書かれている)
   Client                        Attacker                        Server
   ------                        -------                         ------
   ----------- Handshake -----------> (Attacker hold)
                                     <----------- Handshake ---------->
                                     <======= Initial Traffic ========>
                                     (Renegotiation is triggerd)
   <--------------------------  Handshake ============================>
   <======================== Client Traffic ==========================>

(RFC5746の図を改変)

  1. Client は Server と TLS 通信を確立しようとするが Attacker が Hold する
  2. Attacker はサーバとハンドシェイクを行う
  3. Attacker は暗号通信を開始し,(例えば) http の一部のデータを送る.ここで http 的には中途半端な状態まで送出しておく (最後の行を X-ignore: で終わらせておくとか)
  4. Attacker は再ネゴシエーションを開始する
  5. Attacker は Hold していた Client からの Handshake を再開し,Client と Server に Handshake の内容を送る.この時,Attacker 〜 Server 間は 3 で使っていた暗号化された通信路を通る.
  6. Client と Server は暗号通信を開始する.この内容は Client 〜 Server 間でネゴシエーションされているので Attacker は内容を知ることはできない.(この攻撃が成り立つのが図のような MITM 攻撃のみである理由)
  7. Client は http のリクエストを Server に投げるが,先に Attacker が送出済みの X-ignore: ヘッダの後に連結されるので,Client が送出したリクエストの一行目は無視される.
    X-ignore: GET /path/
    Cookie: hogehoge
  • TLS のハンドシェイク時はサーバの計算量が多い (クライアントに比べて 15 倍以上?)
  • 何度もハンドシェイクを行わせると効果的に DoS が可能
  • <color red>従って,プロトコル自体に存在する計算量の多い点を突いているだけで,特別な工夫をしなくても DoS は成り立つし,それに対する対処法はない (サーバ側で処理量を上げるとか,普通の DoS 対策以外)</color>
  • CVE-2009-3555 対策 (RFC5746成立以前) 以前は,いつでもどこでも再ネゴシエーション可能だったので,コネクション張って,何度も再ネゴシエーションのリクエストを投げれば,サーバは何度でもネゴシエーションしようと計算する必要がある.
    • 普通に DoS するより TCP の 3-way ハンドシェイク分稼げる.→ これが THC-SSL-DoS
  • RFC5746 成立後は成立前程気軽には再ネゴシエーション不能になった.
    • THC-SSL-Dos ツールは動かない (多分)
    • <color blue>とはいえ,真面目に再ネゴシエーションすれば何度でも可能では?</color> → ここは RFC5746 をもう少し真面目に読む.
  • コネクションの状態として以下が追加
    • “secure_renegotiation” フラグ.このコネクションでセキュアな再ネゴシエーションが使用中かどうか
    • “client_verify_data” 直前のハンドシェイクでクライアントから送出された Finished に含まれる verify_data が入る.
    • “server_verify_data” 直前のハンドシェイクでサーバから送られた Finished メッセージに含まれる verify_data が入る.
  • 新たな TLS 拡張として “regegotiation_info” が追加.
    • 初期のハンドシェイクの場合,これは 00 が入る (拡張の実際の中身は ff 01 00 01 00: “ff01”=拡張タイプ,“0001”=拡張の長さ,“00”=1byte分0が入る)
    • 再ネゴシエーション時の ClientHello だと,ここに “client_verify_data” が入る.
    • 再ネゴシエーション時の ServerHello だと,ここに “server_verify_data” が入る.
  • SSLv3,TLS1.0,TLS1.1 では ClientHello で理解出来ない extension が来た時は無視することになってる.が,中には無視しないでハンドシェイクが失敗してしまうような実装がある.
    • そのようなサーバとの互換性を保つため,二次的なメカニズムを準備する.
      • “Signaling Cipher Suite Value (SCSV)” という “TLS_EMPTY_RENEGOTIATION_INFO_SCSV” という実際にはない Cipher Suite を定義する.
      • 空の “renegotiation_info” 拡張と同じ.SSLv3, TLS の実装なら,理解出来ない Cipher Suite は無視される.
  • 初期ハンドシェイクの時のクライアント
    • 空の “renegotiation_info” か TLS_EMPTY_RENEGOTIATION_INFO_SCSV のどちらかを ClientHello で送出.
    • ServerHello を受信した時 “renegotiation_info” があるかどうかチェック
      • ない場合はサーバがセキュアな再ネゴシエーションをサポートしてないので secure_renegotiation フラグを FALSE にする.
      • FALSE の場合は,クライアントはハンドシェイクを終わらせるかも?
      • 拡張が提示されてる場合は,secure_renegotiation フラグは TRUE となる.クライアントは “renegotiated_connection” フィールドが 0 であることを確認しなければならない.0 でない場合はハンドシェイクを中断しなければならない.
    • ハンドシェイク終了後は,クライアントは client_verify_data と server_verify_data の値を将来のために保存しておく必要がある.
  • Secure Renegotiation の時のクライアント (“secure_renegotiation” が TRUE の時)
    • クライアントは “renegotiation_info” 拡張を ClientHello に含まなければならない.この拡張には保存してある “client_verify_data” を使う.SCSV は含めてはならない.
    • “ServerHello” を受信した時,クライアントは “renegotiation_info” 拡張が含まれているかどうかチェックしなければならない.もし含まれていない場合,クライアントはハンドシェイクを中断しなければならない.
    • それから,クライアントは “renegotiated_connection” フィールドの前半分を保存してある client_verify_data と等しいかチェックし,後半分を保存してある server_verify_data と等しいかチェックしなければならない.等しくない場合,クライアントはハンドシェイクを中断しなければならない.
    • ハンドシェイクが完了したとき,クライアントは改めて新しい client_verify_data と server_verify_data を保存しておく必要がある.
  • 初期ハンドシェイク時のサーバ
    • ClientHello を受信したとき,サーバは TLS_EMPTY_RENEGOTIATION_INFO_SCSV が含まれているかどうかチェックしなければならない.もし含まれていたら,secure_renegotiation フラグを TRUE にする.
    • サーバは ClientHello に “renegotiation_info” 拡張が含まれているかどうかチェックしなければならない.もし拡張が含まれている場合,secure_renegotiation フラグを TRUE にセットする.サーバは “renegotiation_connection” フィールドの長さがゼロであるかチェックしなければならない.もし違っている場合は,ハンドシェイクを中断しなければならない.
    • もし TLS_EMPTY_RENEGOTIATION_INFO_SCSV も renegotiation_info も含まれていない場合,“secure_renegotiation” フラグを FALSE に設定する.この場合,ハンドシェイクを終了させるサーバがあるかもしれない.
    • secure_renegotiation フラグが TRUE にセットされている場合,サーバは空の “renegotiation_info” 拡張を ServerHello メッセージに含めなければならない.
    • ハンドシェイク終了後は,サーバは client_verify_data と server_verify_data の値を将来のために保存しておく必要がある.
  • この仕様を実装する TLS サーバはクライアントが示す未知の拡張を無視しなければならない.また,この TLS サーバは自分の実装する TLS のバージョン番号以上のバージョン番号を受け入れ,共通のバージョン番号のうちの最も高いバージョン番号のものでネゴシエーションしなければならない.(これは RFC5246 でかかれていることの念押し)
  • 注意すべきは,SCSV だけが含まれている ClientHello に対して “renegotiation_info” 拡張を送ることは,特に要求されない拡張を送るサーバ上では RFC5426 の Section 7.4.1.4 の禁止項目の例外であるということである.これは,クライアントが TLS_EMPTY_RENEGOTIATION_INFO_SCSV 経由で拡張を受け取りたいという意志を表明しているというのが理由である.TLS においては,他の全ての拡張は Section 7.4.1.4 に今後も従わなければなりません.

(理解の過程のメモなので読む必要なし)

Client certificate authentication

クライアント認証機能を設定できる HTTPS サーバは一般的にディレクトリ毎の設定が可能である.これは,クライアントからのリクエストを受けとるまでは,クライアントが有効な証明書を提出するということを断言できず,サーバが持つ認証ルールでフィルタすることもできない.

クライアント認証が必要である事が分かったリクエストについては,HTTPS サーバはクライアントからクライアント証明書を受け取り,確認を行うために,その時点で TLS チャンネルの再ネゴシエーションを行わなければならない.サーバで有効な証明書が見つかれば,サーバはその時点でリクエストを処理するように強制できる.

不幸なことに,HTTP には新たに認証されたチャンネルないでリクエストを再送信するようにクライアントに求めるための具体的なレスポンスコードが欠如しているため,サーバはオリジナルのリクエストにさかのぼって認証 (authentication) を適用する必要がある.暗号的にはギャップが存在しないにも関わらず(新しい鍵のネゴシエーションは古い鍵の保護の下で行われる),サーバとクライアントの認証の連続性は失われる.(<color gray>ここで言っている「認証 (autentication)」が何の認証なのかがイマイチわからない.例えば HTTP 的にやりとりされている何らかの認証情報 (Cookie でやりとりされているアプリのセッションの情報とか) の事か?</color>)

セッションの回復 (resumption) (<color gray>← SSL/TLS プロトコル上での resumption を指す.Hello メッセージで session_id を指定する</color>) がない限り,最初のクライアントのコネクションから再ネゴシエートしたセッションへ繰り越される重要な暗号の状態は存在しない.テストした HTTPs サーバやクライアントで,再ネゴシエーションの間にセッションの回復の指示が観察できたものはなかった (プロトコルのオプショナル機能なのでそれほど必要とされていない).事実,再ネゴシエーションは新しい暗号化コンテキストを始めるためにデザインされているのに対して,回復 (resumption) は純粋に前の暗号化コンテキストを resume するための最適化のためにデザインされている.その意味では,これらの二つの操作は直行する目的のためにデザインされている.

  • security/tls_renegotiation.txt
  • 最終更新: 2013/04/12 07:44
  • by tenforward