パディングオラクル攻撃のオラクルって何だっけという話。
本当は、ちゃんとした数学的な理論があるのですが、そういう正確さは脇へ置いて、分かりやすさを優先した説明を試みたいと思います。というわけで、以下の説明は間違っているかもしれませんが、そこは自己責任ということでひとつ。。。
#これがオラクルだ!
攻撃者は、攻撃の標的(例えば認証サーバ)が持っている秘密情報(例えばパスワード)を知りたいとします。攻撃者は何らかの「答案」を標的へと送信し、被害者の応答(例えばログオン成功・失敗)によって、さきほどの「答案」が「正解」だったか「不正解」だったかを知ることができます。
よくある構図ですよね。
このとき、標的サーバの実装は「答案が正解なら正解、答案が不正解なら不正解という応答だけを返し、それ以外の情報を渡さない」という対応に徹するのが基本です。この基本がきちんとできていれば、攻撃者は「オンライン総当たり攻撃」を仕掛けるしかありません。これならいいのです。オラクル攻撃は成立しません。
しかし、この標的が「正解か不正解かの1ビット情報だけでなく、攻撃者にヒントを与えるような何らかのデータを返してしまう」とか「本当は不正解なのに正解という誤った応答を返してしまう場合がある」ような実装だったらどうなるかということです。攻撃者は、このようなヒント情報をうまく利用すれば、「オンライン総当たり攻撃」よりもはるかに少ない手数で、正解に辿り着いてしまう可能性がありますね!
これがオラクル攻撃です。標的サーバが攻撃者に与えてしまうヒントのことを神託(オラクル)と呼びます。ヒントを与えてしまうサーバのことを預言者(オラクル)と呼ぶ場合もあるようです。
そんなわけで、オラクル攻撃は一般的に、オンライン総当たり攻撃ほどではありませんが、かなり大量のアクセスを伴います。
#POODLE
POODLEは、標的クライアントと標的サーバの間に介在して、クライアントからサーバへ送られる暗号通信の一部を改変する中間者攻撃の一種です。暗号通信の改変ですから、本来ならば受信したサーバ側で矛盾を検知してエラーを出さなければおかしいのですが、SSL3.0のCBCのパディングの仕様にあいまいな部分があり、その影響で、本来エラーを出すべきタイミングでエラーが出ない場合があるのです。それを探していくことで、256分の1の確率で、暗号文中の1文字を解読できてしまいます。1文字目を解読すれば、同じ手口で256分の1の確率で2文字目も解読できます。2文字目を解読すれば、同じ手口で256分の1の確率で3文字目。。。というわけで、オンライン総当たり攻撃よりはるかに少ない手数で暗号文の解読ができてしまいます。
この攻撃を実用的に行うには、標的クライアントから標的サーバへ、一定の条件を満たす(攻撃者にとって都合がいい)データを何度も繰り返し送信させ、さらに個々の通信を改ざんし、サーバの応答を観察しなければなりません。しかし、上手いことバレないようにやれば出来なくはないかも知れない程度には非現実的と言い切れない(汗)攻撃方法と言えます。
TLS1.0以降では、SSL3.0で未定義だったCBCのパディング部分の内容を厳密に定義するという対策が施されました。
#DROWN
これは、以下の__両方__の条件を満たす場合に成立する攻撃です。
- TLS鍵交換にRSAを使っている。
- そのTLSサーバと同じRSAキーペアを利用するSSL2.0サーバが、世界のどこかに存在する。
弊社のTLSサーバはSSL2.0を無効にしてあるから安全!と思っても、同じRSAキーペアを利用するSSL2.0サーバが__世界のどこか__にあれば、攻撃者はそれを暗号解読支援装置として利用してしまいます。したがってDROWN攻撃への対策は、該当するSSL2.0サーバを全部停止することです。また、別解として、TLSサーバでRSA鍵交換を止めてしまい、代わりにDHEやECDHEを使うという方法もあります。
攻撃手順としては、攻撃者はまずTLS通信をキャプチャし、そこに出てくるpre_master_secretの解読を試みます。このときにSSL2.0サーバを支援装置として使います。もっとも常に解読できるわけではなく、暗号文1,000件につき解読成功1件ぐらい出ればまあ上々とか、その程度です。pre_master_secretが手に入れば、あとはmaster_secret、key_block、暗号文本体と解読を進めていくのは容易なことです。
で、SSL2.0サーバをどうやって利用するかですが、SSL2.0ハンドシェイク中のCLIENT-MASTER-KEYメッセージ(SSL3.0以降のClientKeyExchangeに相当する)に含まれるENCRYPTED-KEY(SSL3.0以降のpre_master_secretに相当する)に細工し、手持ちの暗号化されたpre_master_secretに一種の改変を施して送信します。SSL2.0サーバはこれを自分のRSA秘密鍵で復号化し、PKCS#1v1.5のパディング形式に合っていれば合格、合っていなければ不合格と判定します。攻撃者はこれをヒントとして利用し、改変の中身を変えて不正なメッセージを何度も送信することで「正解」の範囲を少しずつ絞り込んで行きます(Bleichenbacher攻撃と呼ばれる)。これを繰り返して、最終的に「正解」に辿り着けば、見事pre_master_secret解読成功というわけです。
これに対するサーバ側の対抗策は、合格・不合格の判定結果をクライアントに教えないことです。しかし、SSL2.0では通常、鍵交換終了後の最初の暗号化メッセージは__サーバ側__から送出するCHALLENGEです。クライアントがこれを解読すれば、さっきの改変暗号文が合格だったか不合格だったか分かってしまいますので、結局、ご神託が攻撃者に届いてしまいます。
一方、SSL3.0以降では、鍵交換終了後最初の暗号化メッセージは__クライアント側__から送信するFinishedです。pre_master_secretの中身を知らない攻撃者はこのメッセージを正しく送信できませんので、サーバからご神託を引き出す段階まで辿り着くことはできません。あくまで、SSL2.0サーバの存在がDROWN攻撃成功の条件です。
以上!世の中まだまだどこに地雷が埋まっているか分かりません。幸運を祈る。
#リファレンス
##POODLE
This POODLE Bites: Exploiting The SSL 3.0 Fallback
https://www.openssl.org/~bodo/ssl-poodle.pdf
JVNDB-2014-004670
OpenSSL およびその他の製品で使用される SSL プロトコルにおける平文データを取得される脆弱性
http://jvndb.jvn.jp/ja/contents/2014/JVNDB-2014-004670.html
##DROWN
The DROWN Attack
https://drownattack.com/
JVNDB-2016-001554
SSLv2 の暗号通信を解読可能な脆弱性 (DROWN 攻撃)
http://jvndb.jvn.jp/ja/contents/2016/JVNDB-2016-001554.html