This is an old revision of the document!
Table of Contents
デフォルトで初期化される外部入力をバリデーションする
PHPは多くの外部からの入力を自動的に初期化し、スーパーグローバル配列として利用可能にしている。外部からの入力であることは明らかな物もあるが、そうでない物もある。
- $_GET - 変数名を含め、全て外部からの入力。デコード済み
- $_POST - 変数名を含め、全て外部からの入力。デコード済み
- $_COOKIE - 変数名を含め、全て外部からの入力。デコード済み
- $_REQUEST - 変数名を含め、全て外部からの入力。デコード済み
- $_FILES - アップロードされたファイル以外に、ファイル名やファイルタイプも外部入力。デコード済み
- $_ENV - 変数名を含め、全て外部からの入力。
- $_SERVER - 変数名はフィルタ処理される物が多いが外部入力、値は外部からの入力の物が多い。
スーパーグローバル変数以外の外部入力が変数として初期化される物は以下である
- $argv, $argc - $argcはシステムが初期化したパラメータ数。$argvの内容は外部入力。
- $php_errormsg - 直前のエラーのエラーメッセージ。エラーメッセージ内に外部入力が含まれる可能性がある。
- $http_response_header - PHPストリームでURLを処理した場合に初期化される配列。全て外部入力。
- $HTTP_RAW_POST_DATA - POSTメソッドデータ。デコード処理が行われていない外部入力。(PHP 7.0で廃止。代わりにphp://inputストリームを利用)
外部入力のデータは全てバリデーションを行うべきあり、バリデーションを省略できるのはデータ元となるシステム、データを経由するネットワークなどの経路およびデータその物が信頼できる場合に限る。例えば、信頼できるデータベースサーバーとネットワークであっても、データベースに保存されているデータが信頼できない物(第三者が情報を保存/編集できる物)である場合はそのデータを信頼することはできない点に注意する。
Webアプリケーションで取り扱うデータは基本的にすべて文字列である点に留意してバリデーションを行う。バリデーションは全ての外部入力に対して行い、ロジックは以下のチェックを行わなければならない
- データの大きさ(最小サイズ、最大サイズ)
- 形式の確認 (整数のみ、半角英字のみ、などをホワイトリスト方式で確認)
- 値の範囲(整数/浮動小数点の場合、最小値と最大値)
- パラメータの数
また入力その物の真正性のバリデーションが必要となる場合も多い。例えば、データ操作をともなうURLへのリクエストが実際にユーザーが意図した操作であるかは、バリデーションを行わないとCSRF(クロスサイト・リクエスト・フォージェリ)攻撃が可能になる。
非適合コード例
$_GET/$_POST/$_COOKIE配列を直接利用すれば外部入力であることは明白だが、別の変数に代入すると外部入力であるかどうか不明確になる。
$id = $_GET['id'];
キャストはバリデーションの代替とはならない。
$id = (int)$_GET['id'];
キャストでは$idの範囲は正の整数のみであるにも関わらず負の数が設定される、文字列などが0に初期化される、など不正な入力を受け入れる。
適合コード例 (filter_input)
$id = filter_input(INPUT_GET, 'id', FILTER_VALIDATE_INT, ['min_range'=>100, 'max_range'=>PHP_INT_MAX]); if (!is_numeric($id)) { throw new Exception('Invalid ID') ; }
適合コード例
if (!is_numeric($_GET['id']) || $_GET['id'] < 100 || is_int($_GET['id']*1) { throw new Exception('Invalid ID') ; }
このコードfilter_var()/filter_input()は整数型で表現可能な範囲外の値にはfalseを返す。“$GET['id']*1”は$GET['id']の値が整数型で表現できない場合に浮動小数点型に変換されることを用いてオーバーフローを検出している。
例外
エラー処理には例外利用を推奨するが、trigger_error()を用いても構わない。
外部入力となるデータソース、データが経由するネットワークなどの経路、データその物が信頼できる場合はバリデーションを省略可能な場合もある。このようなケースに該当するシステムは外部入力を一切含まないファイアーウォール内のデータベースなどであり、通常ではほぼない。データベースの場合、送信されてくるデータ型はテーブル定義と一致している事が期待できる。しかし、SQLiteのようにデータ型を強制しないデータベースシステムもある。
リスク評価
外部入力のバリデーションを行わなかったり不備があった場合、任意コード実行、情報の漏洩、サービス不能など生む結果となる場合がある。
| Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
|---|---|---|---|---|---|
| High | likely | medium | P15 | L3 |
関連ガイドライン
- ISO27000
