HTTPS SSLv3のPOODLE脆弱性はなにが危ないのか(PaddingOracle攻撃の具体例)
前知識:典型的な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が追加される)
前提
- 太郎さんはいつも自社サーバー(example.com)にIDパスワードでログインして機密情報を確認しています。
- example.comはログイン後、cookieを太郎さんのブラウザに設定します。以降のリクエストはそのcookieがあれば太郎さんであると見なします。
- ここに太郎さんの会社の機密情報を狙う花子さんがいます。花子さんは太郎さんとexample.comの間に機器を設置し、太郎さんのパケットを盗聴または改ざんができます。ただし、https通信は暗号化されているので内容まではわかりません。
- 花子さんは太郎さんを誘導して自分のサイト(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は複数の原因が重なった結果とも言えます。
- 中間で通信を傍受し改ざんすれば古い方式(SSLv3)を選択出来てしまう事。(ダウングレード攻撃)
- 本来、改ざんを検知するはずのダイジェストがパディング領域には施されていないこと。
- サーバー(ここではexample.com)がパディングが正しいかどうかの判定器として使われてしまう事。(パディングオラクルマシーン)
- CBC暗号利用モードが直前ブロックの暗号文と対象ブロックの中間文を知るだけで平文が特定出来てしまう事。
どんなとき問題なのか
前提にもあるように、攻撃者は通信を傍受、改ざんできる必要があります。またマルウェアやサイトを使い被害者(ここでは太郎さん)のブラウザからリクエストを発行させることが必要です。
どんな危険があるのか
被害としては盗聴や不正ログインが挙げられます。
この問題の範囲では、例でいう太郎さんが出来る事を超える事(サーバーで任意コードを走らせる等)はできません。
参考資料
コメント
目次
- Amazon楽天Yahooの最安をその場で検索し欲しい物をメモ[Webバーコード価格比較] v1.3.0
- 今いる場所の過去の気象データを調べるWebアプリ[お天気タイムマシーン] v1.1.0
- GPSで近くの高速道路ICから100km以内の最遠出口ICを検索 [GPS高速100km地点IC探索] v1.0.0
- GPSで自分の近くの施設の公式ホームページを一覧 [GPSホームページ探索] v2.0.2
- 今走っている現在地の国道や県道をWikipediaで調べるアプリ [GPS道ペディア] v1.2.0
- 家や自動車のローン金利だけでもう一つ買える? 元利均等返済ローン金利シミュレーション計算機 [金利計算くん] v1.0.0
- GPSで自分の近くのWikipediaページを一覧 [GPS Wikipedia探索] v2.1.0
- GoogleEarthにGPXトラックをプロット表示[GoogleEarth GPXViewer] v1.2.0
- よく行く店を来店記録できるWebアプリ[ランチメモリー] v1.5.1
- よく行く施設やコース毎に積算カロリーをメモ [カロリー貯金箱] v1.0.0
- よく行く湯を来店記録[温泉メモリー] v1.0.0
- バーコードや手動入力で消費賞味期限をメモ[買い置き名人] v1.0.0
- GoogleMaps地図のクリックした場所の高度と住所を調べるWebアプリ[タップ高度君] v1.1.0
- 漫画喫茶で読み終わった巻数をメモ管理 [漫喫バーコードメモ] v1.0.0
- ×km先のゴールに向けて□秒差で○Km/hで走っている先の集団に追いつくには何km/h出せばいいのか[追いつき計算機]
- エブリィやアトレーなどの軽バンに乗用タイヤを履かせるには Javascriptタイヤ直径計算機 [タイヤサイズ計算機]
- ハイブリッドのエコカーに買い替えるのは本当に得? 自動車コスト計算機(update13/12/13)
- 最後に美容院に行った日を記録メモ [髪切りメモリー] v1.0.0
- 売上やカロリーや走行距離など日毎に積算し記録する[シンプル日々積算]v1.0.0
- マイナス思考の人は使用禁止。自分の残された時間を知り1秒1秒を大切に使う[寿命時計] v1.0.0
- 中古マンションの土地建物価格を簡易計算 [不動産マルチ計算機マンション版]
- 木造中古物件の建物価格や減価償却率を簡易計算 [不動産マルチ計算機 一戸建て版]
- Amazonや楽天などの通販サイトの価格表示を自分の労働時間で表示 時給換算君v1.1 (140602ChromeWebStore掲載)
- 見ているページの過去や昔の状態をタイムマシン検索する方法(WaybackMachineブックマークレット)
- ブラウザで好きなページのHTMLのtextareaをタブTABキー入力可能モードにするブックマークレット
- 現在のページのタイトルとURLをマークダウンMarkdown書式風のリンクリストにするブックマークレット
- Google Analyticsで自分除外用のCookie生成を簡単に行う方法(ブックマークレット)
- GitHubにJavaScriptファイルを置いて直接Scriptで読み込む方法(GitHub直リンク抽出ブックマークレット)
- 今見ているページのについてのTwitterつぶやき一覧を表示するブックマークレット(公式利用版)
- JavaScriptでブックマークレットbookmarkletなどを作る時に便利なスニペットSnippet集v1.0
- 自分の残された時間を知る寿命時計のbashシェルスクリプト版
- MacOS Xのターミナルから一発でWolframAlphaを開くスクリプト
- MacOS X Mountain Lion/Mavericksの通知をコマンドラインから出す方法
- クロスドメインXMLHttpRequestを実現するnode.js/expressプロキシ
- node.jsでブログにトラックバックを送信するモジュール
- CSSを使わずにHTMLのIMGタグのALT要素を画像に並べて表示する方法(+jQueryプラグイン)
- 指定したURLのGPXファイルのトラックログと高度グラフを表示するJQueryプラグイン
- iPhoneのSiri音声入力での記号入力方法をまとめてみた(2014/11/10更新)
- BitCoinの仕組みを紙とスタンプのごっこ遊びに例えてみる
- Javascript正規表現クックシート(よく使うサンプル集)2014/11/13更新
- Google ChromeでHTTP Headerを表示するには
- iPhone/iPad等iOSに自己署名オレオレCA証明書からサーバー/クライアント証明書を署名しインストールする
- Markdownクックシート(よく使うサンプル集)
- Garmin eTrexシリーズのGPSログをMacOSでUSB経由でダウンロードするには
- SVGクックシート(よく使うサンプル集)
- 定規とコンパスだけで足し引き掛け割りの四則演算をする(数学の思考パーツ集)
- しょうがくせい向けRSA暗号の仕組み
- ユークリッド互除法をつかいRSA暗号で秘密鍵と公開鍵のペアを求める方法
- しょうがくせい向けDiffie-Hellman(ディフィー・ヘルマン/DH)共通鍵交換方式のしくみ
- しょうがくせい向けハミング符号のしくみ
- MacOSXターミナルのシェルスクリプトからSafariやChromeのWebページのボタンを自動的に押す方法
- USBGPSドングルGT-730FとThree.jsを使った表示デモ
- クレジットカード課金の物乞いサイトを10分で作る〜Google In App Payments APIとJWTのサンプル
- ChromecastでHelloWorld!(任意のURLのMP4を再生)
- 明日が晴れならiPhoneに通知をする方法(IFTTTのかんたんチュートリアル)
- たった26行でiPhone用のQRコード/JANバーコードを読み取るHTML/JavaScriptWebアプリを書く
- GoogleログインボタンでHelloWorld!〜Google+SignInButtonのサンプル
- Titanium+node.js+APNS(ApplePushNotificationService)でHelloWorld!(たった43行でプッシュ通知を動作させるサンプル)
- Three.jsでHelloWorld〜18行で書けるiOS対応3Dプログラム
- Twitterのリストを削除できない・メンバー追加出来ない問題時の対処方法
- GoogleComputeEngineとAmazonEC2の最低料金比較(常時稼働の低スペックWebサーバーを想定)2014/3値下げ発表対応
- プログラミング言語ランキングを比較する
- GoogleのMobileBookmarkBubbleでバルーンが出なくなった時にリセットする方法
- 5を掛けたり5で割る計算が驚くほど簡単に暗算できる速算法「五算術」
- IngressのIntelMapでレゾネータの数を表示するIITCプラグイン(実験中)
- 手持ちの割引クーポンの使用期限をメモできるWebアプリ[クーポン管理君] v1.0.0
- Titanium iOSシミュレーターで言語が日本語にならない場合の対処方法
- ホワイトボードとタックメモだけで出来る デペンドToDoリスト(DTD)[iOS/Android版も開発中]