My Photo

« August 2013 | Main | October 2013 »

September 30, 2013

SQLインジェクション その1

発生箇所 SQL呼び出しをしている箇所
影響の種類
  • 情報漏洩:DB内のすべての情報が外部から盗まれる。
  • データ改ざん:DBの内容が書き換えられる。
  • 認証の回避:IDとパスワードを用いずにログインされる。
  • プログラムの実行:DBサーバ上のプログラムの実行
  • ファイルの参照・更新:DBサーバ上のファイルの読み出し・書き込み

エラーメッセージ経由の情報漏洩

以下はDB(PostgreSQL)内の蔵書を著者名を検索条件として検索するスクリプト(抜粋、一部省略)である。SQL脆弱性がある。

<?php
header('Content-Type: text/html; charset=UTF-8);
$author = $_GET['author'];
$con = pg_connect(<接続文字列>);
$sqlstm = "SELECT id, title, author, publisher date, price FROM books WHERE author ='{$author}' ORDER BY id";
$rs = pg_query($con, $sqlstm);
?>
// HTML省略
<?php
$maxrows = pg_num_rows($s);
for ($i = 0; $i < $maxrows; $i++) {
	$row = pg_fetch_row($rs, $i);
	// 画面への出力:省略
}
pg_close($con);
// 以下省略

このスクリプトを
「author='+AND+CAST((SELECT+id||':'||pwd+FROM+users+OFFSET+0+LIMIT+1)+AS+integer)>1--」
というクエリストリングを指定して実行する。
すると以下のようなユーザIDとパスワードを含むエラーメッセージが表示されてしまう。

Warning: pg_query() [function.pg-query]: Query failed: ERROR: 型integerの入力構文が無効です: "yamada:pass1" in /var/www/44/44-001.php on line 7

原因は、実行されるSQLが以下であることが原因である(見やすいように適宜改行を入れてある)。

SELECT id, title, author, publisher date, price
FROM books
WHERE author ='' AND CAST((SELECT id||':'||pwd
                           FROM users
                           OFFSET 0 LIMIT 1) AS integer)
                     >1
--' ORDER BY id
スクリプト側ではパラメータは著者名を想定しているが、この例では想定外の文字列が入力されている。
そしてその入力によって作られたSQL文の中で、WHERE句内の副問い合わせ
CAST((SELECT id||':'||pwd FROM users OFFSET 0 LIMIT 1) AS integer)>1

の部分が問題となる。
CAST()の中のSELECT文の結果はユーザIDとパスワードの文字列であり、それをCASTで整数に型変換しようとしてエラーになる。
そのためにユーザIDとパスワードを含んだエラーメッセージが表示される。

参考文献:体系的に学ぶWebアプリケーションの作り方 4.4.1 SQLインジェクション

体系的に学ぶ 安全なWebアプリケーションの作り方 脆弱性が生まれる原理と対策の実践体系的に学ぶ 安全なWebアプリケーションの作り方 脆弱性が生まれる原理と対策の実践
徳丸 浩

ソフトバンククリエイティブ 2011-03-03
売り上げランキング : 4070

Amazonで詳しく見る
by G-Tools

September 29, 2013

エラーメッセージからの情報漏洩

エラーメッセージからの情報漏洩は以下の2種類がある。

  • エラーメッセージに攻撃者にとって有益なアプリケーションの内部情報が含まれる。
  • 意図的な攻撃としてエラーメッセージに秘密情報(個人情報など)を表示させられる。

このような問題があるため、アプリケーションでエラーが発生した場合、画面に表示するのは「しばらくお待ちください」的なものにとどめ、エラーの詳細はエラーログに出力するようにする。

参考文献:体系的に学ぶWebアプリケーションの作り方 4.3.3 エラーメッセージからの情報漏洩

体系的に学ぶ 安全なWebアプリケーションの作り方 脆弱性が生まれる原理と対策の実践体系的に学ぶ 安全なWebアプリケーションの作り方 脆弱性が生まれる原理と対策の実践
徳丸 浩

ソフトバンククリエイティブ 2011-03-03
売り上げランキング : 4070

Amazonで詳しく見る
by G-Tools

PHPメモ034:ファイルを日本語ファイル名でダウンロードさせる

ファイルを日本語のファイル名でダウンロードさせたい場合にどうすればいいか調べた。
ググって調べると色々情報があったので、それらを参考にして自分は以下のような実装をした。

$server_file_name = 'japanese.pdf';
$download_file_name = '日本語.pdf';
$user_agent = $_SERVER['HTTP_USER_AGENT'];

$path = DOWNLOAD_FILE_DIR . $server_file_name;
header('Content-type: application/pdf');

if (preg_match("/MSIE/i",$user_agent) === 1) {	// IE
	$download_file_name = rawurlencode($download_file_name);
	$filename = "filename=\"{$download_file_name}\"";
} else if (preg_match("/chrome/i",$user_agent) !== 1
	       && preg_match("/safari/i",$user_agent) === 1) {	// Safari
	$filename = "filename=\"{$download_file_name}\"";
} else {
	$download_file_name = rawurlencode($download_file_name);
	$filename = "filename*=utf-8'ja'{$download_file_name}";
}

header("Content-Disposition: attachment; {$filename}");
header('Cache-Control: public');
header('Pragma: public');
readfile($path);

下記PC用ブラウザで確認した。スマホ、タブレットでは未確認。
IEが8と古いのは確認したPCのOSがXPだったので^^;
Macのfirefox、WindowsのSafariでは確認していない。

  • IE 8.0.6001.18702
  • firefox 24.0
  • chrome 29.0.1547.76m
  • Safari(Mac) 5.1.10

IE、Safari、その他で分けている。
IEではファイル名をURLエンコードしている。
その他(FireFox、Chrome)では文字コードを指定してファイル名をURLエンコードする。
SafariではUTF-8のファイル名をそのまま使っている。Safariであることの確認はUser-Agentに "Chrome" が含まれていないことかつ "Saferi" が含まれていること。ChromeのUser-Agentには "Safari" が含まれているらしい。

参考サイト:
ファイルダウンロード時のファイル名が文字化けする対処法 - [PHP + PHP] ぺんたん info
Webから日本語ファイル名でダウンロード - みちのぶのねぐら A面
userAgent一覧/ユーザーエージェント一覧

September 27, 2013

PHPメモ033:Smarty3の変数

Smarty3では以下の例のような変数を変数名に使ったり(可変変数)、計算式や関数をバッククウォートで囲って計算結果や関数の返り値を変数の値に使うことができる。
#Smarty2ではできない。

phpコード

<?php
require_once("Smarty-3.1.14/libs/Smarty.class.php");

$smarty = new Smarty();
$smarty->template_dir = "../templates/";
$smarty->compile_dir = "../templates_c/";


$smarty->assign('n1', '747');
$smarty->assign('n2', '777');

$smarty->assign('b_747', 'Jumbo Jet');
$smarty->assign('b_787', 'Dreamliner');

$smarty->assign('a', '5');
$smarty->assign('b', '7');


$array1 = array('春', '夏', '秋', '冬');
$smarty->assign('array1', $array1);

$smarty->display('variable.tpl');
?>

テンプレート

{$b_{$n1}}<br />  {* 可変変数 *}
{$n3 = "`$n2+10`"}{* 計算結果を利用 *}
{$b_{$n3}}<br />  {* 可変変数 *}
{$tmp1 = "季節は`$array1[2]`です。"}{* 配列の値を利用 *}
{$tmp1}<br />
{$tmp2 = "5×7=`$a*$b`"}{* 計算結果を利用 *}
{$tmp2}<br />
{$ts = "time={time()}"}    {* 関数の戻り値を利用 *}
{$ts}<br />

出力

Jumbo Jet<br />
Dreamliner<br />
季節は秋です。<br />
5×7=35<br />
time=1380205156

WindowsのPHPにSmarty3をインストール

家のWindows7のPCにはSmarty2はインストールしてあったが会社ではSmarty3を使っているのでバージョンアップを試みた。
バージョンアップというか、Smartyは単なるクラスの集合なのでSmarty2とは別にインストールする。Smarty2とSmarty3が両方インストールされていてもかまわない。たぶん。

インストールの方法は

  • php.ini の include_path に含まれるフォルダの配下の好きなところにダウンロードしたSmartyのzipファイルを展開する。
以上。

使い方は以下のようにSmarty3のクラスを読み込んで使用する。
Smarty3の場所が "<インクルードパスに含まれるフォルダ>/Smarty-3.1.14" の場合。

require_once("Smarty-3.1.14/libs/Smarty.class.php");

$smarty = new Smarty();
// 以下に必要なコード

参考サイト:
Smarty3 設定 | 私的雑録

September 19, 2013

クロスサイト・スクリプティング(XSS)その4

DOM based XSS

DOM based XSSはJavaScriptによるクライアント側での表示処理に存在するXSS脆弱性である。サーバ側で生成されたHTMLには攻撃者の注入したJavaScriptが現れないのでこのように呼ばれる。

次のスクリプトはクエリストリングname=に指定した値をJavaScriptにより表示する。

こんにちは
<script type="text/javascript">
document.URL.match(/name=([^&]*)/);
document.write(unescape(RegExp.$1));
</script>
さん

「name=<script>alert(document.cookie)</script>」
というクエリストリングを指定してスクリプトを実行すると、JavaScriptが実行されてしまう。

対策としては、JavaScriptの標準関数にはHTMLエスケープの機能は用意されていないので、jQueryを使用して文字列を表示する方法が考えられる。
text()は引数をエスケープして要素内にセットする。

こんにちは<span id="name"></span>さん
<script tyep="text/javascript">
if (document.URL.match(/name\=([^&]*)/)) {
	var name = unescape(RegExp.$1);
	$('#name').text(name);
}
</script>

HTMLタグやCSSの入力を許す場合の処理

SNSなどでHTMLタグやCSSの入力を許可したい場合、script要素やイベントハンドラによって悪意のあるJavaScriptが注入される可能性がある。
対策として入力されたHTMLを構文解析して表示してよい要素のみを抽出する方法がある。HTMLを構文解析するライブラリを使用することが望ましい。PHPで利用できるライブラリにはHTML Purifierなどがある。

参考文献:体系的に学ぶWebアプリケーションの作り方 4.3.2 クロスサイトスクリプティング(発展編)

体系的に学ぶ 安全なWebアプリケーションの作り方 脆弱性が生まれる原理と対策の実践体系的に学ぶ 安全なWebアプリケーションの作り方 脆弱性が生まれる原理と対策の実践
徳丸 浩

ソフトバンククリエイティブ 2011-03-03
売り上げランキング : 4070

Amazonで詳しく見る
by G-Tools

September 17, 2013

クロスサイト・スクリプティング(XSS)その3

JavaScriptの動的生成

最近のWebアプリケーションではJavaScriptの一部をサーバ側で動的に生成する例が多く見られるようになった。典型的なのはJavaScriptの文字列リテラルを生成する場合である。

イベントハンドラのXSS

次のスクリプトはonloadイベントで呼び出される関数の引数を生成している。

<head><script>
function init (a) { /* 処理 */ }
</script></head>
<body onload="init('<?php echo htmlspecialchars($_GET['name'], ENT_QUOTES) ?>'">
</body>

htmlspecialchars()でエスケープしているので問題ないように思えるが、実際にはXSS脆弱性がある。
「name=');alert(document.cookie)//」
というクエリストリングを指定してスクリプトを実行すると、HTMLは以下のようになる。

<body onload="init('&#039;);alert(document.cookie)//')">

属性値は文字参照が解釈されるので、以下のJavaScriptが実行される。
#クエリストリングの末尾のスラッシュ2つは余計な"')"をコメントアウトしている。

init('');alert(document.cookie)//')

脆弱性の原因はJavaScriptの文字列リテラレルのエスケープがされていなかったことである。そのため、入力パラメータ中のシングルクウォートがデータとしての文字ではなくJavaScriptの文字列終端に使われ、alert()の挿入を許す結果となった。

対策は後述。

JavaScriptの文字列リテラルのエスケープとして最低限必要な文字列は下表。

文字 エスケープ後
\ \\
' \'
" \"
改行 \n

script要素のXSS

script要素内でJavaScriptの一部を動的に生成する場合、script要素内ではタグや文字列参照を解釈しないのでHTMLエスケープは不要で、JavaScript文字列リテラルのエスケープを行う。しかし、それだけでは脆弱性が残る。
以下のスクリプトは脆弱性がある。

<script>
$('#name').text('<?php echo escape_js($_GET['name']); ?>');
</script>

escape_js()はJavaScript文字列リテラルをエスケープする関数とする。
「</script><script>alert(document.cookie)//」
というクエリストリングを指定してスクリプトを実行すると、script要素は以下のようになる。

<script>
$('#name').text('</script><script>alert(document.cookie)//');
</sciprt>

"</script>"でscript要素が一旦終端して、次の"<script>"で始まるscript要素でalert()が実行される。

JavaScriptの文字列リテラルの動的生成の対策

  1. JavaScriptの文字列リテラルとしてエスケープする。
  2. イベントハンドラ中の場合は1の結果をHTMLエスケープする
  3. スクリプト要素内の場合は1の結果に"</"という文字列が出現しないようにする。

JavaScriptのエスケープルールは複雑なため対処漏れが生じやすく、基本的にJavaScriptの動的生成は避けるべきである。
しかし、やむを得なず行う場合の対策として以下の2つがある。

  • Unicodeエスケープ
    英数字以外をすべてをエスケープする。UnicodeコードポイントU+XXXXの文字を\uXXXXで表す。
    実際には英数字以外にもマイナスとピリオドもエスケープしなくてセキュリティ上は問題ない。
  • script要素の外部でパラメータ定義してJavaScriptから参照する方法
    type属性がhiddeのinput要素などの値を動的に生成して、それをJavaScriptから参照する。
    この方法であればJavaScriptの動的生成をせずに済む。

参考文献:体系的に学ぶWebアプリケーションの作り方 4.3.2 クロスサイトスクリプティング(発展編)

体系的に学ぶ 安全なWebアプリケーションの作り方 脆弱性が生まれる原理と対策の実践体系的に学ぶ 安全なWebアプリケーションの作り方 脆弱性が生まれる原理と対策の実践
徳丸 浩

ソフトバンククリエイティブ 2011-03-03
売り上げランキング : 4070

Amazonで詳しく見る
by G-Tools

September 16, 2013

クロスサイト・スクリプティング(XSS)その2

href属性などURLを保持する属性値、イベントハンドラのスクリプト、script要素内のXSS脆弱性はHTMLエスケープする以外に特別な対応が必要となる。
対象の場所ごとのXSS脆弱性に対するHTMLエスケープの概要をまとめた表が以下になる。

場所 説明 対応
要素内容
(通常のテキスト)
タグと文字参照が解釈される。
「<」で終端。
「<」と「&」を文字参照に変換。
属性値 文字参照が解釈される。
引用符で終端。
属性値を「"」で囲み、
「<」と「"」と「&」を文字参照に変換。
属性値
(URL)
同上 URLの形式を検査してから
属性値としてエスケープ
イベントハンドラ 同上 JavaScriptとしてエスケープしてから
属性値としてエスケープ。
script要素内の
文字列リテラル
タグも文字参照も解釈されない。
「</」により終端。
JavaScriptとしてのエスケープおよび
「</」が出現しないよう考慮。

URLである属性値

a要素のhref属性やimg要素、frame要素、iframe要素のsrc属性などはURLを属性値としてとる。このURLが外部から変更できる場合、URLとして
「javascript:<JavaScript式>」
という形式(JavaScriptスキーム)でJavaScriptを起動できる。
たとえば次のスクリプトを考える。

<a href="<? php echo htmlspecialchars($_GET['url']); ?>">ブックマーク</a>

このスクリプトを
「url=javascript:alert(document.cookie)」
というクエリストリングを指定して実行すると以下のHTMLが生成され、JavaScriptが実行される。

<a href="javascript:alert(document.cookie)">ブックマーク</a>

JavaScriptスキームによるXSSはHTMLのエスケープ漏れが原因ではなく、対策も異なる。
書式チェックとして、以下のURLのみを許容するようにチェックする。

  • http:またはhttps:で始まる絶対URL
  • スラッシュで始まる相対URL(絶対パス参照)

また、リンク先として任意のURLを指定できる場合、罠サイトに誘導される可能性がある。よって外部ドメインのURLである場合に次のいずれかの対策をするとよい。

  • エラーとする。
  • 外部ドメインへのリンクであることを利用者に注意喚起するためのクッションページを表示する。

参考文献:体系的に学ぶWebアプリケーションの作り方 4.3.2 クロスサイトスクリプティング(発展編)

体系的に学ぶ 安全なWebアプリケーションの作り方 脆弱性が生まれる原理と対策の実践体系的に学ぶ 安全なWebアプリケーションの作り方 脆弱性が生まれる原理と対策の実践
徳丸 浩

ソフトバンククリエイティブ 2011-03-03
売り上げランキング : 4070

Amazonで詳しく見る
by G-Tools

September 08, 2013

クロスサイト・スクリプティング(XSS)

発生箇所 Webアプリケーション上でHTML、JavaScriptを生成している箇所
影響の種類 Webサイト利用者のブラウザJavaScriptの実行
  • 攻撃者の用意したスクリプトの実行によりクッキー値が盗まれる。
  • 攻撃者の用意したスクリプトの実行によりサイト利用者の権限でWebアプリケーションの機能が悪用される。
偽情報の表示
  • 偽の入力フォームが表示され、フィッシングにより個人情報が盗まれる。

受動的攻撃によりクッキー値を盗む

脆弱なサイトの正規利用者を罠サイトに誘導して以下のようにクッキー値を盗みだす攻撃が考えられる。

  1. 罠サイトのiframe内で脆弱なサイトを表示される。
  2. 脆弱なサイトはXSS脆弱性により、クッキー値をクエリ文字列に付けて情報収集ページに遷移する。
  3. 情報収集ページは受け取ったクッキー値をメールなどで攻撃者に送信する。

画面の書き換え

form要素のある画面でXSS脆弱性を使って画面を書き換え、元のformを隠して偽のformを表示することによって情報を盗むことが考えられる。

反射型XSSと持続型XSS

攻撃用のJavaScriptがどこにあるかによってXSS攻撃を分類すると以下に分けられる。

反射型XSS
  • 攻撃用JavaScriptが攻撃対象サイトとは別のサイトにある(罠サイトやメールのURL)。
  • 多くの場合、入力値をそのまま表示するページ(例えば入力値の確認用のページ)で発生する。
持続型XSS
  • WebメールやSNSに攻撃用JavaScriptを仕込むタイプ。
  • 攻撃側のメリットとして、罠サイトに利用者を誘導する手間がかからない、また注意深い利用者でも被害にかう可能性が高いことがある。

対策

対策として以下がある。

必須対策

  • HTMLの要素内容をエスケープする。
  • HTMLの要素の属性値をエスケープしてダブルクウォートで囲む。
  • HTMLレスポンスに文字エンコーディングを明示する。

エスケープにはPHPではhtmlspecialchars()を使用する。
htmlspecialchars()はデフォルトでは<、>、&、"をエスケープする。

予防的対策

  • 入力値を検証する。
  • クッキーにHttpOnly属性を付与する。
  • TRACEメソッドを無効化する。

TRACEメソッドの無効化はクロスサイト・トレーシング(XST)攻撃への対策(参考ページを参照)。

参考文献:体系的に学ぶWebアプリケーションの作り方 4.3.1 クロスサイトスクリプティング(基本編)

体系的に学ぶ 安全なWebアプリケーションの作り方 脆弱性が生まれる原理と対策の実践体系的に学ぶ 安全なWebアプリケーションの作り方 脆弱性が生まれる原理と対策の実践
徳丸 浩

ソフトバンククリエイティブ 2011-03-03
売り上げランキング : 4070

Amazonで詳しく見る
by G-Tools

参考ページ:
実はそんなに怖くないTRACEメソッド | 徳丸浩の日記
TRACEメソッドって怖いんです - カイワレの大冒険

September 01, 2013

jQueryで非同期な処理が終わるのを待つにはDeferredを使う

非同期な処理が終わるのを待って何かしたい場合、jQuery.Deferredというものを使うとできる。参考サイト2の説明がわかりやすい。
Deferred.promise()でPromiseオブジェクトを取得する。そしてDeferred.resolove()とするとPromise.done()でバインドした関数が、Deferred.reject()するとPromise.fail()した関数が実行される。Promise.then()は引数を複数取ってresolve時とreject時に実行される関数を一度にバインドできる。

deferred.resolve([args])
Deferredオブジェクトをresolved状態に移行し、指定した引数を
doneCallbacksコールバック関数に渡し、それを実行する。

deferred.reject([args])
Deferredオブジェクトをrejected状態に移行し、指定した引数を
failCallbacksコールバック関数に渡し、それを実行する。

deferred.then(doneFilter[, failFilter ][, progressFilter])
Deferredオブジェクトの各状態において呼び出すコールバック関数を登録する。

deferred.done(doneCallbacks[, doneCallbacks])
Deferredオブジェクトがresolved状態に移行したときに呼び出すコールバック関数を
登録する。

deferred.fail(failCallbacks[, failCallbacks ])
Deferredオブジェクトがrejected状態に移行したときに呼び出すコールバック関数を
登録する。

jQueryのAjax用メソッド(ajax(),post(),get())が返すjqXHRオブジェクトがDeferredインタフェースかPromiseインタフェースを実装しているらしい。どちらを実装してるのかよくわからないが、参考サイト3に

「Promiseは、ユーザがDeferredの状態の変更を防ぐための、Deferredのメソッドのサブセット(then,done,fail等)を提供する」

とあったので、あまり深く考えずにAjax関数の返り値に対してthen()などのメソッドでコールバック関数をバインドすると覚えておく。

追記:Deferred と Promise についてはちゃんと理解した(つもり)後に別記事を書いた。

処理が終わるのを待つなら同期処理のような気もする。使いどころがイマイチわからないが、例えば以下の例のようなことができる。
1つ目はHTML+Javascript、2つ目はサーバ側のphpのコード。

<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja">
<head>
<title>jQuery Deferred test</title>
<script type="text/javascript" src="./js/jquery-1.8.2.min.js"></script>
<script type="text/javascript">
$(function() {
	// イベントハンドラをバインド
	$("#btn01").on("click", function() {
		funcA();
	});
	
	// funcAを実行して、終わったら "[initital]" を書き加える
	funcA().done(function() {
		$("#displayArea").append("[initial]");
	});
});

// funcBを呼んでその戻り値を返すだけ。
function funcA() {
	return funcB();
}

// Ajax。レスポンスデータをdisplayAreaにセットする
function funcB() {
	var url = document.form.action;
	var data = {"mode": "time"};
	var $p = $.post(url, data, function(jdata) {
		$("#displayArea").text(jdata);
	},"json");
	return $p;
}
</script>
</head>
<body>
<form name="form" action="http://localhost/php/ajax.php" method="post">
<input type="button" id="btn01" name="btn01" value="btn01" />
<div id="displayArea" style="min-width: 100%; min-height: 100px; border: solid 2px"></div>
</form>
</body>
</html>
<?
header('Content-type: application/json');

$mode = $_REQUEST['mode'];
if ($mode === 'time') {
	print json_encode(strftime('%c'));
} else {
	print json_encode('success');
}
?>

この例では、最初の表示の時はAjaxでサーバから日時の文字列をJSON形式で取得し、その日時文字列をdiv要素のテキストとしてセットし、さらにdone()でバインドした関数(div要素のテキストに "[initial]" を追加する)を実行する。よって、画面には

<日付> <時間>[initial]

と表示される。
一方、ボタンを押した時は、サーバから時間を取得しdiv要素にセットするまでは同じだが、初期表示の時に実行されたdone()でバインドされた関数は実行されないので

<日付> <時間>

と日時だけ表示される。
resolove()は明示的に呼ばなくていい。post()が指定したコールバック関数が終了した後にresoveしているんだろう。

注意:
Deferredとは関係ないが、最初、クライアント側でpostの引数のコールバック関数が呼ばれず、原因がしばらくわからずに困った。
サーバ側のプログラムがjson_encode()を使わず文字列をそのまま返していたのを、json_encode()を使うようにしたら思ったように動作するようになった。クライアント側で受け取るデータを "json" と指定しているので、サーバ側のアプリもちゃんとJSON形式でデータを返すべきだった。
また、header()も呼んでいなかったので呼ぶようにした。なくても動くが、一応決まりとして呼んでおくべきだろう。

参考サイト:
1.Qrefy - jQuery日本語リファレンス
2.爆速でわかるjQuery.Deferred超入門 - Yahoo! JAPAN Tech Blog
3.Types | jQuery API Documentation

« August 2013 | Main | October 2013 »

April 2017
Sun Mon Tue Wed Thu Fri Sat
            1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30            
無料ブログはココログ

日本blog村

  • にほんブログ村 IT技術ブログへ
  • にほんブログ村 アニメブログへ
  • にほんブログ村 サッカーブログ アルビレックス新潟へ

好きな音楽家

メモ

XI-Prof