blog

DeNAのエンジニアが考えていることや、担当しているサービスについて情報発信しています

2014.10.23 技術記事

SSL v3.0の脆弱性「POODLE」ってかわいい名前だけど何??

by ReiSugano

#security

このブログは「mobage developers blog」2014.10.23の記事を転載させていただきました。

こんにちは。セキュリティ技術グループのはるぷです。

10月上旬にHTTPSなどで利用されているSSLv3の脆弱性が報告され、中間者攻撃(通信経路上で通信に介入してパケットの取得、改ざん等を行う攻撃。Man In The Middle Attackとも呼ばれる)によって、暗号化されている通信の内容を復号することの可能性が示唆されました。

この攻撃方法はPOODLE (Padding Oracle On Downgraded Legacy Encryption)と呼ばれ、暗号方式のダウングレード攻撃を利用して、Padding方式に問題があるSSLv3を暗号通信に利用させ、パケットを通信経路で改ざん、観測することで平文の内容を特定することができるといわれています。

今回は、この攻撃方法が具体的にどういったものであるのかを紹介したいと思います。

中間者攻撃(Man In The Middle Attack)

POODLEの技術詳細の前に中間者攻撃について解説します。中間者攻撃とは、下図のように、他人のネットワーク上での通信に対して、通信経路上に介入して通信の書き換えなどを行う攻撃になります。

図. 中間者攻撃の概要

これは、POODLEに限らず一般的に利用される攻撃手法ですが、例えばhttpsの場合、一般的な中間者攻撃の方法では、サーバ側で証明書が正しく管理されていればクライアント側では下記のようなエラーとなり、中間者攻撃を検知・ブロックすることが可能になります。

図. 中間者攻撃が発生した際のブラウザでのブロック例

このケースでは、通信経路の中間に入っている攻撃者が、クライアントに対してWebサーバの振りをして暗号通信を行いWebサーバ宛の通信を取得しようとしたため、クライアント側のブラウザに検知される仕組みになっています。

POODLEの場合も、通信経路の中間に入って攻撃をするのですが、暗号を直接的に復号することは行わず、クライアントから送信された暗号文自体を細工してサーバに送りサーバ側での処理結果を確認するという手法を用います。※「Downgraded Legacy Encryption」については暗号通信前の平文の通信を改ざんして実現することになりますが、簡単のためにここでは割愛します。

Padding Oracle

POODLEでは、SSLv3の暗号で利用されるPadding(後述)の特徴を利用し、Paddingではない別の箇所の暗号文の解読を実施します。SSLv3で利用される暗号はCBC方式のブロック暗号を選択することができ、その場合は、一定のサイズのブロックごとに暗号化・復号を行います。図にすると下図のような仕組みになっています。

図. CBC方式のブロック暗号の復号処理

ブロックごとに処理を行うため、平文の最後がブロック長に比べて中途半端な長さになることが当然発生してしまうのですが、このはみ出た部分をダミーの文字を入れてブロックサイズの倍数に揃う様に調整します。この調整のために平文の最後に付与される文字をPaddingといいます。SSLv3では、平文の一番最後のbyteにPaddingの長さが入るようになっており、復号した際に後ろからPaddingの長さ分の文字も無視することでPaddingを削除した元の平文を取得することが可能です。

この時に、一番最後のバイトはPadding長として規定されているため、平文が丁度ブロックサイズの倍数であっても、Padding長情報のbyte分がはみ出てしまうため、その場合は、最後のブロックはダミーの文字とPadding長のみの実質データが入っていないようなブロックになります。

図. 最後のブロックがPaddingのみになった際の復号例

POODLEでは、このPaddingのみで構成されているブロックを悪用して他のブロックの平文の推測を行います。SSLv3のPadding方式では、ダミーの文字部分は無視され、Padding長のみ正しいことが要求されます。従って、Paddingのみで構成されているブロックの暗号文が改ざんされても、復号を行った結果の最後のbyteが正しいPadding長のbyteと一致した場合、正しい暗号文として扱われます。

つまり、おおよそ1/256の確率(1byteが偶然一致する確率)で、暗号文が復号された結果の最後のbyteがPadding長と同じになるということが判別可能になります。この判別結果を利用することで、後述の手法により任意の暗号ブロックの最後のbyteの復号結果を検証することが可能になります。

まず、クライアントからの同じ通信内の他の暗号ブロックをPaddingのブロックにブロックごと上書きしてサーバに送信することで、該当のブロックの復号結果を観測します。

図. クライアントの暗号文を暗号文のまま変更を実施

通常であれば、サーバ側は正しくない暗号文が送られてくる状態となるため、復号に失敗する(コネクションが切断されるなど)ことが考えられます。復号結果のPadding長に相当する最後のbyte部分が偶然正しいものになった場合、サーバ側には復号結果が正しく見えるため復号に成功することとなります。

CBC方式のブロック暗号では、クライアントが送信するデータがまったく同じでも、毎回暗号文が変化する仕組みになっているため、復号したい暗号文のブロックもPaddingのブロックも毎回異なるbyte列になります。そこで、攻撃者はクライアントに同じデータを送信させて、同様の手法を繰り返し行うことで偶然復号結果のPadding長に相当する最後のbyte部分が一致するケースが出てきます。

復号に成功したことが分かった後は、下図のような手順で平文が入手可能になります。
1. (A)暗号文の最終byteと(B)既知のパディング長をXORする
2. 復号処理直後の最終byte(C)が求まるので、コピー元の暗号文の復号結果の(D)とみなす
3. (D)と(E)暗号文の最終byteをXORする
4. (F)の1byteの平文を取得

図. Padding-Oracle Attackの復号手順

このように、平文を1byte判別できた後は、求めたい平文の該当byteをブロックの最終byteになるように位置をコントロールします。

ここで、どのように求めたい平文の位置をコントロールするのか(Paddingのみのブロックを作ることにおいても同様ですが)という問題が出てきますが、HTTPのプロトコルであればこの条件を満たすことが可能です。HTTPのリクエストは大雑把には下記のようになっています(簡単のために一部ヘッダ等を省略しています)。

POST /index.html HTTP/1.1
Host: dena.com
Cookie: xxxx=xxxx

a=b&c=d

攻撃者が知りたい情報をCookieとすると、クライアントに強制的にリクエストを発行させることができれば、path (/index.htmlの部分)とbody (a=b&c=dの部分)の長さを増減することでCookieの出現位置をコントロールすることができます。例えば、1文字後ろにしたい場合、pathを「/index.htmlx」、bodyを「a=b&c=」のようにそれぞれ1byteずつ変更します。1byte解読する度に位置をずらし繰り返しクライアントにリクエストを送信させることで最終的にCookie全体を取得することが可能になります。逆に、この条件を満たしていない情報(例えばユーザが入力したID/Passwordなど)はPOODLEを利用して取得することは困難となります。

実際に例えば32文字のCookieの値を取得することを考えると、おおよそ8,000回程度のリクエストをクライアントから繰り返し送らせる必要があります。結構回数多いですね。Webでの攻撃として8,000回程度の試行を他のユーザに実行させるのは比較的大掛かりですが、暗号を解読するのにこの程度の試行回数で収まるのは画期的であるといえます。


では、このようにPaddingを推測できてしまわないようにするにはどのようになっていればいいのでしょうか?今回のように脆弱であると言われていないPadding方式では、Padding長以外のPadding部分も正しいものか検証するようになっています。例えば、Padding長以外は「0」で埋めるであったり、Padding部分を全てPadding長で埋めるであったり、あらかじめ決めた値か意味のあるものになっています。この場合に同様の攻撃を行おうとした場合、全てのbyteが偶然一致する必要があり、ブロックサイズが128bit(16byte)だと256^-16の確率となるため、現実的に解読ができる試行回数ではなくなります。

このように、「暗号が解読可能」という場合でも全ての条件で解読ができるわけではなく、特定の条件が必要になることがあります。実際にこの攻撃ができてしまわないかを上記の攻撃シナリオで再現することは非常に困難を極めると考えられます。その為、重要な情報を扱うサーバでは、SSLv3を利用しない設定にするなどの対策を行うことが望ましいと考えられます。

また、暗号ロジックの部分のみを検証してみたいという場合は、ISO10126が似た仕様となっているため、C#などで再現することで下記のように部分的に復号が成功することを確認できます。

図. ISO10126のPadding方式を利用した暗号の解読実施例


ちなみに、POODLEの絵はPower Pointによって制作されています。

最後まで読んでいただき、ありがとうございます!
この記事をシェアしていただける方はこちらからお願いします。

recruit

DeNAでは、失敗を恐れず常に挑戦し続けるエンジニアを募集しています。