CodeIgniterで会員サイトの訂正

keiji様より、『Form validationのルールで htmlspecialchars してしまうと、保存するデータがおかしくなりませんか?』とのご指摘がありましたので、検証してみました。

会員登録のお名前を『7&i』と入力してみました。

登録確認画面でも、『7&i』と表示しています。

会員登録チェックのページでは、普通に表示していましたので、大丈夫かなと思ったのですが、登録されたデータベースを確認してみたら、『7&i』となっていました。

『form_validation.php』でXSSフィルタリングの検証もできたら、楽かなと考えましたが、浅はかでした。やはり出力時にエスケープする必要がありそうです。

そこで、横着者の私は、kenji様のコードをお借りして、ヘルパを作成しようと思いました。『application/helpers』フォルダに『xssfilter_helper.php』ファイル名で、下記のコードを入力、作成しました。

<?php
//変数のエスケープ処理
function h($var)
{
	if (is_array($var))
	{
		return array_map('h', $var);
	}
	else
	{
		return htmlspecialchars($var, ENT_QUOTES, config_item('charset'));
	}
}

//URIのエスケープ処理
function allow_url($str)
{
	if (preg_match('/\Ahttp(s?):/', $str) OR
		preg_match('#\A/#', $str))
	{
		return h($str);
	}
	else
	{
		$backtrace = debug_backtrace();
		$view = $backtrace[0]['file'];
		$line = $backtrace[0]['line'];

		log_message('error',
				'allow_url() got unallowable string: "' . $str . '" in ' . $view .
				' on line ' . $line);
		return 'Error';
	}
//イベントハンドラ内の文字列リテラル
// 文字列をすべて \uXXXX 形式に変換
function unicode_escape($matches)
{
	$u16 = mb_convert_encoding($matches[0], 'UTF-16');
	return preg_replace('/[0-9a-f]{4}/', '\u$0', bin2hex($u16));
}

// 英数字とマイナス、ピリオド以外を \uXXXX 形式でエスケープ
function escape_js_str($str)
{
	return preg_replace_callback('/[^-\.0-9a-zA-Z]+/u',
					'unicode_escape', $str);
}
//style要素内で数字だけを許可するヘルパー
function allow_num($str)
{
	$CI =& get_instance();
	$CI->load->library('form_validation');

	if ($CI->form_validation->numeric($str))
	{
		return $str;
	}
	else {
		$backtrace = debug_backtrace();
		$view = $backtrace[0]['file'];
		$line = $backtrace[0]['line'];

		log_message('error',
				'allow_num() got unallowable string: "' . $str . '" in ' . $view .
				' on line ' . $line);
		return 'Error';
	}
}
//style要素内でアルファベットと数字、アンダースコア(_)、ダッシュ(-)を許可するヘルパー
function allow_alnum($str)
{
	$CI =& get_instance();
	$CI->load->library('form_validation');

	if ($CI->form_validation->alpha_dash($str))
	{
		return $str;
	}
	else {
		$backtrace = debug_backtrace();
		$view = $backtrace[0]['file'];
		$line = $backtrace[0]['line'];

		log_message('error',
				'allow_alnum() got unallowable string: "' . $str . '" in ' . $view .
				' on line ' . $line);
		return 'Error';
	}
}
}

それでは、『application/config』フォルダの『form_validation.php』のmembers検証グループを次のように変更します。全てのhtmlspecialcharsを外しました。

	'members'=>array(
		array(
			'field'  => 'name',
			'labbel' => 'お名前',
			'rules'  => 'required'
		),
		array(
			'field'  => 'email',
			'labbel' => 'メールアドレス',
			'rules'  => 'required|valid_email'
		),
		array(
			'field'  => 'passw',
			'label'  => 'パスワード',
			'rules'  => 'required|min_length[4]|md5'
		),
		array(
			'field'  => 'picture',
			'label'  => '写真',
			'rules'  => ''
		)
	)

次に、コントローラmembersのコンストラクタに先程作成したヘルパーを追加します。

$this->load->helper(array(‘form’,’url’,’xssfilter’));

作成したヘルパーは『xssfilter_helper.php』なのに、何故、ヘルパーの指定は、『xssfilter_helper』では、なくて、『xssfilter』なのでしょう。これは、ヘルパーの仕様で、ヘルパの物理ファイル名の末尾には『_helper』というサフィックスがついていますが、呼び込むときは、サフィックスは不要だということです。

次に、ビューファイル『entry_check.php』のecho文にフィルタをかけてエスケープします。フィルタをかけると言っても『h()』で囲うだけですが、『echo $name』を『echo h($name)』に変更します。同様に他のecho文もフィルタをかけて下さい。

本日は以上でした。

 

WinRoadお奨め書籍

たしか、kenji様もご推奨だと思いましたので、早速購入しました。セキュリティ本は、ほとんどが中級以上の人が対象ですので、読んでいても意味不明な箇所が多いのですが、この本は、初心者でもある程度の流れみたいなものはつかめると思います。

Webアプリケーションには、どういう罠が潜んでいて、どういう対処が必要か事細かに書かれていますので、Webサイト、ましてや会員サイト等を作りたいと考えている人は、是非一読下さい。できれば、手元に置いて、セキュリティチェックの糧にして下さい。

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

posted with amazlet at 11.08.26
徳丸 浩
ソフトバンククリエイティブ
売り上げランキング: 675

このエントリーを含むはてなブックマーク Buzzurlにブックマーク livedoorクリップ Yahoo!ブックマークに登録

トラックバック&コメント

この投稿のトラックバックURL:

コメントをどうぞ

このページの先頭へ