McAfee Avert Labs Blog
「Click-fraud, captchas & session-fixation puzzles」より
September 24, 2007 Posted by Vinay Mahadik

 筆者はパズルが大好きだ。ここでは,筆者が自らの「Webサイト」上で遭遇,解決した,セキュリティに関するパズルを取り上げる。

クリック詐欺の阻止

 問題の内容は次の通りだ。Web 2.0的な投票制Webサイトに,ユーザーの投稿したコンテンツが掲載されている。投稿者はサイト訪問者にコンテンツを評価してもらうと,ランキング上位に躍り出る。ここで,このWebサイトがログインを強制せず,未登録ユーザーがログインすることなくコンテンツを評価できる場合,サイトはクリック詐欺に対して無防備な状態となり,コンテンツ投稿者が自分のコンテンツを高く評価し続ける可能性がある。一方,評価時のログインを強制した場合,投稿者以外,すなわちこのWebサイトをたまたま訪れたような訪問者は,何らかの「インセンティブ」がない限り赤の他人のコンテンツを評価するためだけの登録は望まないだろう。

 そこで,クリック詐欺を阻止しつつ,未登録の訪問者がコンテンツを評価できるようにするにはどうすればよいだろうか?

 ヒントは,過去のブログ記事「Flashの危うさと,著作権のあるコンテンツの配信」(英文)にある。

 筆者はこの過去記事で,これを「脳死アイデア」と呼んだが,今回の匿名ユーザーのシナリオもこれに完全に当てはまる。Flashでは,ローカルのPIE-SOLオブジェクト・クッキーを利用して訪問者の識別(ID)情報を保存する。主なWebブラウザでは「すべてのプライバシー情報」を消すよう操作しても,これらのID情報は削除できない。そのため,ハード・ディスク上にあるID情報を手動で探し出して削除する必要がある。例えばアクション・スクリプトは以下のようになる。

var site_so:SharedObject = SharedObject.getLocal("cf");

if ( site_so.data.u == undefined ) { // 初回訪問時
var dt = new Date();
site_so.data.u = dt.getTime(); // (例えば)時刻情報を用いて,一意なユーザーID(uuid)を生成
site_so.flush(); // SOLクッキーをハード・ディスクに保存
}

var cf = new LoadVars();
cf.u = site_so.data.u;
cf.sendAndLoad("images/cf",cf,"GET"); // 「GET images/cf?u=…」要求を通じてuuidを送信

 上記スクリプトにより,訪問者が使っているパソコンのハード・ディスクには,初回訪問時に“cf”SOLファイルが密かに作成される。時刻情報(あるいは任意の情報)を用いた一意なuuidを訪問者に割り当て,これをWebサイト上のユーザーIDとして使う。WebサイトのURLは“images/cf?u=…” GET要求と一つにつながっているように見え,その他のWeb要求にまぎれて容易にカモフラージュされる。Flashオブジェクトそのものは引き続き非表示となる(あるいは1ピクセル角サイズなどに設定される)ため,Webページ上には表示されない。

 これで処理は完了だ。同じユーザーによるクリック操作をWebサイトで認識できるようになった。ユーザーがWebブラウザを閉じても,Webブラウザの履歴情報を削除しても,それどころか別のWebブラウザを使ってもユーザーの識別が可能だ。素晴らしい!

以下に追加情報をメモしておく。

・最近では,このようなユーザーIDクッキーは銀行で利用されるようになっている。ユーザーに対して,利用している銀行が本物であることを証明するためだ(例:米バンク・オブ・アメリカの「サイトキー」)。これは,ユーザーが前回選択した画像イメージを利用するもので,今回のアイデアはフィッシング対策として用いられている

・Pandora.comなどのオンライン・ラジオは,ユーザーが特定のセッションでスキップしたトラック数を保存する目的でユーザーIDクッキーを用いている。こうしたライセンスにより,未登録ユーザーが任意の数のトラックをスキップするのを阻止する。このケースでは,今回のアイデアはデジタル著作権管理(DRM)として用いられている

・上記オブジェクト・スクリプトは,クリック詐欺の検出/阻止が目的である。米グーグルは,Flashベースの「AdWords」広告サービスを間もなく開始すると発表した。グーグルがクリック詐欺を防止目的で最初の防御層に上記アイデアを試みても,驚くに当たらない(関連記事:Google,リッチ・メディア対応インタラクティブ広告「Gadget ads」を試験運用

reCAPTCHAの優れたアイデア

 ヒューマン・コンピュテーションは,画像認識などコンピュータでは非常にコストのかかる処理,あるいは不可能な処理を人間にアウトソーシングするものだ。ESPゲーム/Google Image Labelerでは,Webサイト訪問者に課題/回答形式のパズルを解いてもらう形で,このアイデアを利用している。基本的にこのゲームはコンピュータが解釈できない画像を課題として提示し,複数のWebサイト訪問者に答えてもらう。仮に「ある程度多くの訪問者が画像を『赤いバラ』と識別したら,この画像はほぼ間違いなく赤いバラである」という仕組みになっている。

 このESPゲームの作者は「reCAPTCHA」でも全く同じアイデアを利用し,まさに最適な応用例とした。CAPTCHAをベースとするreCAPTCHAでは,OCRでの解読に失敗した文字(古い本のかすれたテキストや低品質のスキャンから調達したもの)を抽出し,Webサイト訪問者に提示する。ここで提示するのは二つの文字画像で,一つは高い確率でこれと思われる文字にマッピングされており,もう一つは学習モード(複数のユーザーに提示し,これらのユーザーがすべて同じ文字として解釈するかどうか見極める)となっている。さらに訪問者には,どちらの文字が学習モードなのか知らせない。このCAPTCHAを解きたければ,reCAPTCHAで両方の文字を同じ様に解かなければならない(関連記事:カーネギーメロン大学,画像認証を書籍デジタル化に活用するサービス「reCAPTCHA」)。

 (Webサイトでの)アンチ・スパム対処用ヒューマン・コンピュテーションは,基本的には不確実性に対応する。このプロセスは,書籍をデジタル化して保存するのにも役立つ。非常に効率的だ。

「Session Fixation(セッションの固定化)」でFlashのアップロード問題を解決する

 HTML POSTメソッドによるファイル・アップロードは,実際にアップロードされるまでWebサイト側にはファイルの名前やサイズが分からないので,非常に悩ましい問題である。こうした問題があるため,アップロードするファイルの名前やサイズに制限があっても(例:*.mp3のファイルのみ,あるいはファイル・サイズが50Mバイト未満など),ユーザーにこの条件を知らせられるタイミングは,(おそらく長時間かかるであろう)アップロードの終了後しかない。

 現在Flashは,FileReferenceクラスを提供することでこの問題を解決している。Flashオブジェクトは,ユーザーが選択したアップロード・ファイルについて,名前やサイズなどの情報を含むようになった。この情報を利用して,クライアントがアップロード用に参照/選択するファイルを制限することができる。ここまでは問題ない。問題なのは,このFileReferenceを使うアップロード処理がWebブラウザによって異なる点だ。米マイクロソフトのInternet Explorerでは,アップロード要求は親セッションと同じセッションIDクッキーで送信される。したがって,この場合はうまく処理される。ただし,FirefoxなどのWebブラウザの場合,アップロード要求で新しいセッションが使用される。そのため,サーバー上のアップロード・ハンドラが認証済みセッションのアップロード処理であるかどうかを確認すると,当然のことながらアップロードは失敗する。このFlashオブジェクトはステータス・コード302(転送)となり,ログイン・ページに戻る。おそらく大半のユーザーはこのエラーを無視し,あきらめざるを得ないだろう。

 上記のシナリオでは,典型的なセッション固定による「ぜい弱性」を回避策として用いることができる。セッション固定によるセキュリティ上の問題は,新しいセッション開始用としてクライアント側から提供されるセッションIDクッキーを,サイト側が受け入れたときに発生する。サイト側がクライアント側に対して,このセッションIDをもとに既存セッションの接続のみを許可した場合でも,さらに複雑なシナリオにおいては,セッションの固定化が悪用される可能性がある。これは例えば,攻撃者がWebサイトとの既存のセッションを維持し,電子メールまたはWebを通じてクライアントにセッション固定リンクを送信し,さらにこのWebサイトが(1)クライアントからのセッションIDクッキーを受け入れ,(2)たとえ特権昇格(例えば,クライアントによるサイトへのログイン)が行われても該当セッションに対するセッションIDの再生成に失敗する場合だ。(2)の場合,攻撃者はWebサイトとのセッションを維持し,その後このセッションを利用して被害者にログインを仕向け,セッションIDを共有することで被害者のログイン済みセッションを引き継ぐ。

 最後は,Flashのアップロード問題をまさに克服するため使用できるものだ。面白そうなFlashムービー内に実装されたupload()メソッドを含む親ページで,FlashVarsメソッド(またはその他のメソッド)を通じて,セッションIDクッキーの値を同ムービーに読み込む。アップロードするFlashムービーはファイルのアップロード要求で使用されるURLに,このパラメータを追加する。Webサイトで受信するアップロード・ハンドラは,以下のような処理を行うことになる(PHPの場合)。

// ログインがまだの場合は確認しない
// GET要求にPHPSESSID上書き値を提供するURLパラメータが含まれているかどうか確認
// 含まれていない場合,新しいセッションでログインするかどうかのみ確認
// 含まれている場合,この新セッションを以前のセッションとマージ
// 以前のセッションでログインしたかどうか確認

if ( isset($_GET['sid']) )
{
session_id((string)$_GET['sid']); // 固定化。'sid'パラメータの上書き値を使用
session_start();
}

if ( !Is_User_Logged_In() )
{
header("Location: /login");
exit();
}

 このように処理することで,Flashのファイル・アップロード要求のPHPSESSIDセッション・ハンドラを受け入れ,同ハンドラを使って新しいセッションとログイン時の最初のセッションをマージする。これにより,このアップロードはFirefoxでも同様に処理される。

 アップロード・ハンドラ・ページのぜい弱性はどうだろうか。攻撃者が唯一行えるのは,攻撃者のアカウントでコンテンツをアップロードするよう被害者を仕向けることである(被害者が攻撃者の役目を担う)。ログイン・ページでセッションIDが再生成される限り,攻撃者は例えアップロード時でも被害者の役割を担うことはできない。

 あるものに対する安全かつ優れたユース・ケースは,それ自身がぜい弱性となることが多い。

 考え方としては,過去のブログ記事「防御のための技術が攻撃へと身を転じるとき,またその逆もしかり」で取り上げたシナリオと類似する。


Copyrights (C) 2007 McAfee, Inc. All rights reserved.

本記事の内容執筆時点のものであり,含まれている情報やリンクの正確性,完全性,妥当性について保証するものではありません。
◆この記事は,マカフィーの許可を得て,米国のセキュリティ・ラボであるMcAfee Avert Labsの研究員が執筆するブログMcAfee Avert Labs Blogの記事を抜粋して日本語化したものです。
オリジナルの記事は,「The end of Downloader-AAP?」「Click-fraud, captchas & session-fixation puzzles」でお読みいただけます。