NWセキュリティ

【図解】Padding Oracle Attack (AES-CBC, PKCS#7) の仕組み

Padding Oracle Attack とは

Padding Oracle Attack とは、CBC モード暗号化データの復号結果の「Padding 値が想定外」であるときにそのことがエラーにより攻撃者にて把握できてしまい、その結果、現実的な計算量で暗号化/復号を破られてしまう攻撃です。

この攻撃が成立する場合、共通鍵を持っていない人であっても、暗号化データを復号することもできるし、平文を適切な形に暗号化するといった改竄も行うことができます。

AES-CBC + PKCS#7 Padding による暗号化処理の概要

例えば 28 bytes の平文 {username:nesuke,admin:true} を暗号化する場合、AES のブロックサイズである 16 bytes 毎にブロックを区切ります。そして最後のブロックについては Padding を埋めます。

Padding を埋める方式はいくつかありますが、そのうち一般的なのは PKCS#7 Padding です。この方式ではブロックの不足 bytes 数を示す byte で埋めるといったものです。

AES-CBC で暗号化する場合、Initial Vector (IV) と呼ばれる乱数が先頭に付きます。これは同じ input に対し毎回同じ output とすると共通鍵の推測などセキュリティ上問題になるため、毎回異なる乱数をセットすることで毎回異なる文脈を作り、共通鍵推測のリスクを大きく下げるためのものです。

Padding Oracle Encryption Attack

さっそく攻撃の仕組みを解説していきます。まずは任意の平文を適切な形に暗号化する改竄の攻撃方法です。

シナリオとしては Web サーバから cookie で AES-CBC 暗号化され、base64encode されたデータを cookie で受領し、その内容を改竄し Web サーバへアクセスを試みる、といったものです。

Web サーバ側では PKCS#7 Padding に関するエラーのみ 500 エラーで返ってくる状態であり、それ以外は 200 の正常応答か、500 以外のエラーが返されます。

この攻撃では復号処理における AES 共通鍵で処理した後の値 = Intermediary を計算することにより、共通鍵無しで適切な暗号化データを構築することができます。

攻撃ステップの概要としては以下の通りです。

  • C2 (任意固定値) に対する Intermediary を探索
    1. 探索用の C'1 (C1 とは別) の末尾 byte を 0~255 の範囲で変え、Padding エラーが出ない byte を探索し、見つかった byte と 0x01 の xor を取る ⇒ Intermediary の末尾 byte が算出 (下図)
    2. 1 で見つかった byte を 0x01 と 0x02 で xor (0x01 をキャンセル、0x02 を反映) し、C'1 の最後から 2 番目の byte を 0~255 で変え、Padding エラーが出ない byte を探索し、その byte と 0x02 の xor を取る ⇒ Intermediary の最後から 2 番目の byte が算出
    3. ・・・
    4. C'1 の末尾から 1~15 番目の byte を 0x0f と 0x10 で xor し、先頭 byte を 0~255 で変え、Padding エラーが出ない byte を探索し、その byte と 0x10 の xor を取る ⇒ Intermediary の先頭 byte が算出
  • 本来の P2 と Intermediary の xor を取り C1 を算出
  • 同様に C1 に対する Intermediary を探索 (C'0, C1 を繋げて送信) ⇒ P1 と xor を取り C0 を算出

C2 からドミノ倒しで C0 を算出し、しわ寄せは C0 で吸収するので、C2 は任意の値で固定して OK です。

Padding Oracle Decryption Attack

今度は暗号化データを復号する攻撃パターンです。

前回 Encryption Attack のときより想定しにくいシナリオではありますが、cookie のときと同じ共通鍵で AES-CBC 暗号化されたデータファイルをダウンロードし、復号する、というケースです。

環境は前回と同じで、cookie に任意の暗号化されたデータを送信し Padding エラーの有無を確認できる状態です。

このパターンでも同じように Intermediary の計算が肝になります。

攻撃ステップの概要としては以下の通りです。

  • C1 に対する Intermediary を探索 (探索用の C'0 と無加工の C1 を繋げて送信)
    1. C'0 の末尾 byte を 0~255 の範囲で変え、Padding エラーが出ない byte を探索し、見つかった byte と 0x01 の xor を取る ⇒ Intermediary の末尾 byte が算出 (下図)
    2. 1 で見つかった byte を 0x01 と 0x02 で xor (0x01 をキャンセル、0x02 を反映) し、C'0 の最後から 2 番目の byte を 0~255 で変え、Padding エラーが出ない byte を探索し、その byte と 0x02 の xor を取る ⇒ Intermediary の最後から 2 番目の byte が算出
    3. ・・・
    4. C'0 の末尾から 1~15 番目の byte を 0x0f と 0x10 で xor し、先頭 byte を 0~255 で変え、Padding エラーが出ない byte を探索し、その byte と 0x10 の xor を取る ⇒ Intermediary の先頭 byte が算出
  • 本来の C0 と Intermediary の xor を取り P1 を算出
  • 同様に C2 に対する Intermediary を探索 ⇒ C1 と xor を取り P2 を算出

コメント

タイトルとURLをコピーしました