HTTPS SSL3.0のPOODLE脆弱性の仕組み(PaddingOracle攻撃の具体例)

(c)Wikipedia

前知識:典型的なhttpsのネゴシエーション

方向 メッセージ 主な内容 暗号化
Client->Server ClientHello 使用可能な暗号方式 なし
Client<-Server ServerHello 使用する暗号方式 なし
Client<-Server ServerCertificate サーバー証明書 なし
Client<-Server ServerHelloDone なし
Client->Server ClientKeyExchange 共通鍵 あり
Client->Server ChangeCipherSpec なし
Client->Server Finish あり
Client<-Server ChangeCipherSpec なし
Client<-Server Finish あり

典型的なhttps(tls)のネゴシエーションです。暗号方式はクライアントから提案するClientHelloの範囲内でサーバーが選択します。

この段階では暗号化されていないことに注意してください。悪意のある攻撃者がもし通信を傍受、改ざんできたら、わざとClientHelloに古い暗号方式を指定する事ができます(ダウングレード攻撃)

前知識:CBC利用モード

共通鍵を使ったブロック暗号には暗号利用モードという概念があります。これはブロック毎にしか暗号化出来ないため、元の平文がある程度特徴があった場合(0フィルが続くなど)に解読されるのを防ぐ方法です。

その一種であるCBC利用モードは、一つ前の暗号化されたブロックを対象ブロックにxorすることを繰り返すモードです。 一つ前のブロックがない場合は初期ベクタ(IV)という双方で取り決めた適当な値を利用します。

(平文1 xor IV) ->ブロック暗号化 -> 暗号文1
(平文2 xor 暗号文1) -> ブロック暗号化 -> 暗号文2
・
・



前知識:パディング

 ブロック暗号はブロックサイズが固定です。例えば16バイトブロックの場合は元の平文が16バイトである必要があります。

通信文の最後で16バイト未満の場合はどうするのでしょう。答えは16バイトになるようにパディングと呼ばれるバイトを追加します。

pkcs#7パディングではこの追加バイトとして埋めるべきバイト数の数を使います。

例:(8バイトパディング)

元のバイト列:12 34 56 78(4バイト足りない)
パディング後のバイト列:12 34 36 78 04 04 04 04

平文がブロックサイズ丁度の場合は、まるまる1ブロックパディングが追加されます。(上の例では08 08 08 08 08 08 08 08が追加される)

前提

  1. 太郎さんはいつも自社サーバー(example.com)にIDパスワードでログインして機密情報を確認しています。
  2. example.comはログイン後、cookieを太郎さんのブラウザに設定します。以降のリクエストはそのcookieがあれば太郎さんであると見なします。
  3. ここに太郎さんの会社の機密情報を狙う花子さんがいます。花子さんは太郎さんとexample.comの間に機器を設置し、太郎さんのパケットを盗聴または改ざんができます。ただし、https通信は暗号化されているので内容まではわかりません。
  4. 花子さんは太郎さんを誘導して自分のサイト(evil.com)にアクセスさせます。

攻撃

1.evil.comのJavaScriptは太郎さんのブラウザにexample.comへのリクエストを発行させます。この時の暗号化前の送信内容は以下のような内容です。パスとボディは花子さんの自由です。

POST /パス Cookie: name=value...\r\n\r\nボディ ダイジェスト パディング

2.「value」が花子さんの知りたい情報ですが、暗号化されているので当然、見る事はできません。

3.この時、中間に機器を設置している花子さんは、(暗号化されていない)httpsのネゴシエーションを改ざんして双方に古いSSLv3を選択させます(Downgrade攻撃)

4.暗号はブロック単位で施されています。花子さんは自分がコントロールできるパスとボディの長さを調整します。

5 調整はちょうどパディングがブロックサイズ一杯になるように、しかも知りたいvalueがそのブロック(valueブロックとします)の終端になるように行います。

...[valueブロック-1][valueブロック]...[ダイジェストブロック][パディングブロック]

6.この状態で発行された暗号化されたパケットをキャプチャ、valueブロックをパディングブロックにコピーしてexample.comに送ります。

...[valueブロック-1][valueブロック]...[ダイジェストブロック][valueブロック(コピー)]

7.ここでexample.comは当然、エラーを返します。ただしそのエラーは「バディング違反」です。PKCS#7パディングに準拠していないというエラーです。

8.花子さんは(1)から(7)までを複数回繰り返します。すると「パディング違反」にならない事があります。

9.パディング違反にならない場合、それは復号された最後の1バイトが一つ前のブロック(ダイジェストを含むブロック)の最後の1バイトとxorして1、つまり正常なパディングと認識されたということです(前述CBCモード参照)。確率は1/256。けっして大きい数ではありません。

(復号器にかけたあとのvalueブロックの最後 xor 一つ前のブロックの最後)->01

10.その復号されたバイトがなにかはすぐにわかります。一つ前のブロックの最後のバイトにxorしたら1になる数は1つしか無いからです。

11.このブロックはvalueブロックをコピーしたものでもある事を思い出してください。そしてこの最後のバイトはvalueブロックの一つ前のブロックの最後のバイトとvalueブロックの暗号化前の平文の最後のバイトをxorしたものです。

(valueブロック-1のブロックの最後 xor valueブロックの最後の平文)->(10)で求めたバイト

12.valueブロックの一つ前のブロック最後のバイトとxorして(10)で求めたバイトになる数は1つしかありません。これこそがvalueブロックの最後のバイト「e」です。平文が求まりました。

13.花子さんはパスとボディを自由に操作できます。パスを1バイト増やしボディを1バイト減らせばvalueブロックが1バイトずれます。そこで(12)までの手順を行えばvalue一つ前の文字「u」の平文が得られます。

POST /パス Cookie: name=valu[e]...\r\n\r\nボディ ダイジェスト パディング
↓
POST /パス+1バイト Cookie: name=val[u]e...\r\n\r\nボディ-1バイト ダイジェスト パディング

14.これを繰り返せば花子さんは太郎さんのvalueのすべてを入手する事ができてしまいます。

なにが問題なのか

POODLEは複数の原因が重なった結果とも言えます。

どんなとき問題なのか

前提にもあるように、攻撃者は通信を傍受、改ざんできる必要があります。またマルウェアやサイトを使い被害者(ここでは太郎さん)のブラウザからリクエストを発行させることが必要です。

どんな危険があるのか

被害としては盗聴や不正ログインが挙げられます。

この問題の範囲では、例で言うと太郎さんが出来る事を超える事(サーバーで任意コードを走らせる等)はできません。

参考資料

この記事を見た人がよく読んでいる記事

カナシスコム > 節約テクノロジ > HTTPS SSL3.0のPOODLE脆弱性の仕組み(PaddingOracle攻撃の具体例)