My Photo

« PostgreSQLでMySQLのgroup_concat関数のようなことをする | Main | jQueryで非同期な処理が終わるのを待つにはDeferredを使う »

August 25, 2013

入力処理とセキュリティ

入力値の検証とセキュリティ

入力値の検証の目的はセキュリティ対策ではないが、以下のようにセキュリティのために役立つ場合もある。

  • SQLインジェクション対策が漏れていたが、英数字のみ許可していたので実害には至らない。
  • バイナリセーフではない関数を使っているが、入力段階で制御文字をチェックしているので実害には至らない。
  • 表示処理の関数で文字エンコーディングの指定を怠っているが、入力段階で不正な文字エンコーディングをチェックしているので実害には至らない。

バイナリセーフ

バイナリセーフとは入力値がどんなバイト列であっても正しく扱えることを意味する。典型的な例としてはヌルバイト(PHPでは\0と表記)が現れても正しく処理できることを指す。
ヌルバイトが特別な理由は、CおよびUNIX、WindowsのAPIでヌルバイトを文字列の終端とみなす取り決めがあるからである。このためPHPやその他の言語ではヌルバイトを正しく扱えない関数がある。このような関数をバイナリセーフではない関数と言う。

ヌルバイトを使った攻撃手法はヌルバイト攻撃と呼ばれる。ヌルバイト攻撃は他の脆弱性対策を回避するために使用される。
ヌルバイト攻撃との組み合わせが多い脆弱性はXSS脆弱性、ディレクトリトラバーサル脆弱性がある。

下記のPHPのコードはereg()を用いて変数$pが数字のみからなることを検証している。
ereg()はバイナリセーフではない。

<?php
$p = $_GET['p'];
if (ereg('^[0-9]+$', $p) === FALSE) {
	die('整数値を入力してください。');
}
echo $p;
?>

これに以下のURLでアクセスする。

http://example.jp/42/42-002.php?p=1%00<script>alert('XSS');</script>

結果はブラウザ上でjavascriptが実行されダイアログ上に「XSS」と表示される。これはヌルバイト攻撃+XSS脆弱性である。
URL中の「%00」はヌルバイトであり、ereg()はヌルバイトで文字列が終わっているとみなすためヌルバイトより後ろを無視し、検証が回避された。

ヌルバイト攻撃に対する根本対策はバイナリセーフの関数のみを用いてアプリケーションを開発することである。しかし、言語の関数リファレンスには関数がバイナリセーフかどうか記述がない場合が多く、現時的には困難である。
そのため、アプリケーションの入り口でバイナリセーフの関数を用いてヌルバイトをチェックするのが現実的な対応である。

入力値の検証基準はアプリケーション要件

入力値の検証の基準はアプリケーション要件である。
よって「すべての文字を許可する」という場合もある。しかし、そのような場合でも以下のチェックは行うべきである。

  • 制御文字のチェック
  • 文字数のチェック

PHPの正規表現ライブラリ

PHPの正規表現関数にはereg、preg、mb_eregの3系統がある。
eregは前述のとおりバイナリセーフではないので、開発ではpreg、mb_regを使用する。
pregはエンコードがUTF-8の場合のみ日本語を扱える。mb_eregは様々なエンコーディングが利用できる。

下記は英数字1~5文字チェックをpreg_match()で実装したコードである。
データの先頭と末尾はそれぞれ'\A'と'\z'で示す。代わりに'^'と'$'を使う場合もあるが'^'と'$'は行の先頭と末尾を表すので、'^'と'$'を使うと改行文字がチェックを通過してしまう。

<?php
$p = isset($_GET['p']) ? $_GET['p'] : '';
if (preg_match('/\A[a-z0-9]{1,5}\z/ui', $p) == 0) {
	die('1文字以上5文字以下の英数字を入力してください');
}
?>

文字種の制限がなし1~30文字の場合は、preg_match()の部分は以下のようになる。

preg_match('/\A[[:^cntrl:]]{1,30}\z/u', $p)

また、textarea要素からの入力値で改行、タブを許容し他の制御文字は禁止する場合は以下のようになる。

preg_match('/\A[\r\n\t[:^cntrl:]]{1,30}\z/u', $p)

「[:cntrl:]」は制御文字を表すPOSIX文字クラスで、「[:^cntrl:]」はその否定、つまり制御文字以外である。

参考文献:体系的に学ぶWebアプリケーションの作り方 4.2 入力処理とセキュリティ

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

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

Amazonで詳しく見る
by G-Tools

参考ページ:
Ruby 1.9.3 リファレンスマニュアル 正規表現
正規表現の文字クラスまとめ - 名もないテクノ手

« PostgreSQLでMySQLのgroup_concat関数のようなことをする | Main | jQueryで非同期な処理が終わるのを待つにはDeferredを使う »

プログラミング、技術情報」カテゴリの記事

PHP」カテゴリの記事

セキュリティ」カテゴリの記事

Comments

The comments to this entry are closed.

TrackBack


Listed below are links to weblogs that reference 入力処理とセキュリティ:

« PostgreSQLでMySQLのgroup_concat関数のようなことをする | Main | jQueryで非同期な処理が終わるのを待つにはDeferredを使う »

June 2021
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