HTTPSへのBEAST攻撃の要約

SSL/TLSで保護されたHTTPS通信を解読すると話題になった Thai Duong と Juliano Rizzo によるBEAST攻撃について調べたので自分の理解についてまとめておくことにする。

参考文献

攻撃対象はSSL 3.0/TLS 1.0のブロック暗号のCBCモードである。RC4を使用している場合はストリーム暗号なので影響を受けない。

結論から言えばHTTPSに対して広範囲に使える攻撃ではなさそうである。攻撃を成功させるにはWebSocketやJavaなどによってSSL/TLS上に生の通信を流す(最初のブロックを操作する)ことが必要であるが、WebSocketは対象のサーバが許可していなければ使えないし、Java脆弱性がなければ*1Same-origin Policyによって攻撃対象のサイトと攻撃者のサイトのIPアドレスが同じ場合などにしか攻撃できないようだ。許可なしに攻撃できる方法を思いついたので後で調べる。

脆弱性の詳細は以下に

IVを初期化しないことに対する既知の攻撃

SSL 3.0/TLS 1.0のCBCモードでは新しいレコードのIVを再生成せず、前のレコードの最後のブロックの暗号文を次のIVとして使い回す。これにより

  • 攻撃者がレコードの先頭ブロックとして任意のバイト列を暗号化・送信させることができる
  • 暗号文が盗聴可能

という条件下(選択平文攻撃)において、攻撃者は任意のブロックについて何らかの方法で予想した平文が正しいかを判定することが次の方法により可能であることが10年近く前から知られていた。

CBCモードは平文列M_iに対して暗号文列をC_i = E_k(M_i \oplus C_{i-1})で構成する(但しEを暗号化関数、kを暗号鍵として、i=1のときはC_1 = E_k(M_1 \oplus IV))。ここでM_iが知りたい部分、最後の暗号文がC_{n-1}だとして、C_{i-1}C_iC_{n-1}を盗聴により得たとする。そこで予想した平文をPとして、M_n=P \oplus C_{i-1} \oplus C_{n-1}を暗号化させると、C_n=E_k(P \oplus C_{i-1} \oplus C_{n-1} \oplus C_{n-1}) = E_k(P \oplus C_{i-1})となり、P=M_i \Leftrightarrow C_i=C_nより判定できる。

図にまとめると次のようになる。

しかし、この攻撃は

  • 攻撃者は攻撃対象の通信に任意の平文を混ぜることができなければならず
  • しかもブロック全体を一度に推測しなければならないからその組み合わせは2^{128}通りもある

という理由から困難であると考えられていた。

一方で、TLS 1.1では既にこの問題への対処としてレコードの先頭でIVを毎回再生成するように変更されている。レコードの先頭でのみ予測不可能であればいい理由は、この攻撃は攻撃者が操作可能な平文ブロックの直前のブロックの暗号文を知らなければ攻撃できないことによる。レコードの先頭以外のブロックは攻撃者が平文を操作する段階で知ることのできない、まだ生成されていない暗号文に依存しているためである。

Rizzo/Duong攻撃

RizzoとDuongによる今回の攻撃の要点は二つある。

  • 特定の条件下で、知りたい情報を1byteずつ確定して最終的に全体を知ることができることを示した
  • 実際にそのような攻撃がHTTPSに対して可能であることを示した

この攻撃では

  • 知りたい情報を何度でも送信させることができる
  • 知りたい情報の前に任意長の文字列を攻撃者が挿入できる

などの仮定を置くことで、次のように秘密の情報を先頭から1byteずつ確定することができる。

*を既知あるいは挿入した情報として、平文が ***************S となるように長さを調整する。すると未知の情報は最後のSだけであるから最悪でも256通り調べれば良い。そして、挿入した情報を1byte減らしてブロック内にもう1byte秘密の情報を入れて **************SE とする。Sは既に知っているからEを同じ要領で調べれば良い。これを繰り返すことで現実的な回数で秘密の情報を知ることができる。

HTTPにおいては、クロスサイトでリクエストを送信させることができ、攻撃者はそのPath部分を任意長に操作することが可能であるから、これによりCookieのデータの位置をずらしながら攻撃することが可能である。

しかし、これだけでは攻撃は成功せず、レコードの先頭ブロックを攻撃者が任意に設定可能な通信をブラウザに送信させる必要がある。通常のHTTPリクエストの範囲であればレコードの先頭ブロックを操作するのは困難であると思われるが、WebSocketやJavaなどを用いるとこのような通信をさせることが可能であるというデモンストレーションが行われたらしい*2

もっとも、前述のとおりいずれの方法にしても制約が多く、影響範囲は広くないと考えられているようだ。
WebSocketは通信を始める前に接続先のサーバから接続許可をもらわないと接続できないし、Java(Applet)のURLConnection*3はSame-origin policyによりドメインが同じ場合か、IPアドレスが同じ場合にしか接続が許可されないはずである、と。

*1:クロスサイトでのデモが行われたとすれば未知の脆弱性が使われた?

*2:この辺りの具体的な方法を理解していない

*3:デモンストレーションで使われたらしい