User Tools

Site Tools


ja:rule:inp:デフォルトで初期化される外部入力をバリデーションする

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Next revision
Previous revision
ja:rule:inp:デフォルトで初期化される外部入力をバリデーションする [2016/03/06 05:33] – created yohgakija:rule:inp:デフォルトで初期化される外部入力をバリデーションする [2017/07/02 02:58] (current) yohgaki
Line 6: Line 6:
   * $_POST - 変数名を含め、全て外部からの入力。デコード済み   * $_POST - 変数名を含め、全て外部からの入力。デコード済み
   * $_COOKIE - 変数名を含め、全て外部からの入力。デコード済み   * $_COOKIE - 変数名を含め、全て外部からの入力。デコード済み
-  * $_FILES - アップロードされたファイル以外に、ファイル名やファイルタイプも外部入力。+  * $_REQUEST - 変数名を含め、全て外部からの入力。デコード済み 
 +  * $_FILES - アップロードされたファイル以外に、ファイル名やファイルタイプも外部入力。デコード済み
   * $_ENV - 変数名を含め、全て外部からの入力。   * $_ENV - 変数名を含め、全て外部からの入力。
-  * $_REQUEST - 変数名を含め、全て外部からの入力。 
   * $_SERVER - 変数名はフィルタ処理される物が多いが外部入力、値は外部からの入力の物が多い。   * $_SERVER - 変数名はフィルタ処理される物が多いが外部入力、値は外部からの入力の物が多い。
  
Line 30: Line 30:
 また入力その物の真正性のバリデーションが必要となる場合も多い。例えば、データ操作をともなうURLへのリクエストが実際にユーザーが意図した操作であるかは、バリデーションを行わないとCSRF(クロスサイト・リクエスト・フォージェリ)攻撃が可能になる。 また入力その物の真正性のバリデーションが必要となる場合も多い。例えば、データ操作をともなうURLへのリクエストが実際にユーザーが意図した操作であるかは、バリデーションを行わないとCSRF(クロスサイト・リクエスト・フォージェリ)攻撃が可能になる。
  
-===== 非適合コード例 =====+このルールに非適合となるコード例は多岐に渡る。ここで紹介する非適合コード例は一部に過ぎない。 
 + 
 + 
 +===== 非適合コード例(Integer handling)===== 
 + 
 +前提条件:システムは正の整数IDを受け入れるシステムとする。
  
 $_GET/$_POST/$_COOKIE配列を直接利用すれば外部入力であることは明白だが、別の変数に代入すると外部入力であるかどうか不明確になる。 $_GET/$_POST/$_COOKIE配列を直接利用すれば外部入力であることは明白だが、別の変数に代入すると外部入力であるかどうか不明確になる。
  
 +<color #ed1c24>**非適合コード**</color>
 <code php> <code php>
 $id = $_GET['id']; $id = $_GET['id'];
Line 40: Line 46:
 キャストはバリデーションの代替とはならない。 キャストはバリデーションの代替とはならない。
  
 +<color #ed1c24>**非適合コード**</color>
 <code php> <code php>
 $id = (int)$_GET['id']; $id = (int)$_GET['id'];
Line 49: Line 56:
 ===== 適合コード例 (filter_input) ===== ===== 適合コード例 (filter_input) =====
  
 +<color #00a2e8>**適合コード**</color>
 <code php> <code php>
 $id = filter_input(INPUT_GET, 'id', FILTER_VALIDATE_INT, ['min_range'=>100, 'max_range'=>PHP_INT_MAX]); $id = filter_input(INPUT_GET, 'id', FILTER_VALIDATE_INT, ['min_range'=>100, 'max_range'=>PHP_INT_MAX]);
Line 56: Line 64:
 </code>  </code> 
  
 +filter_input/filter_varの整数型バリデーションフィルター(FILTER_VALIDATE_INT)はPHPの整数型の範囲内で整数値であることをバリデーションする。PHPの整数型は利用するOSにより符号付き32ビット整数か符号付き64ビット整数のどちらかになる点に注意が必要である。
  
-===== 適合コード例 =====+===== 適合コード例 (is_numeric/is_int and range check)=====
  
 +<color #00a2e8>**適合コード**</color>
 <code php> <code php>
 if (!is_numeric($_GET['id']) || $_GET['id'] < 100 || is_int($_GET['id']*1) { if (!is_numeric($_GET['id']) || $_GET['id'] < 100 || is_int($_GET['id']*1) {
Line 65: Line 75:
 </code> </code>
  
 +このコードfilter_var()/filter_input()は整数型で表現可能な範囲外の値にはfalseを返す。"$GET['id']*1"は$GET['id']の値が整数型で表現できない場合に浮動小数点型に変換されることを用いてオーバーフローを検出している。PHPの整数型は利用するOSにより符号付き32ビット整数か符号付き64ビット整数のどちらかになる点に注意が必要である。
 +
 +
 +===== 非適合コード例(Text handling)=====
 +
 +前提条件: $_GET['name']は名前を保存したデータとする。文字エンコーディングはUTF-8とする。エラーイベントはデフォルトエラーハンドラで例外に変更され、デフォルト例外ハンドラが定義されているものとする。
 +
 +テーブル定義:
 +<code sql>
 +CREATE TABLE mytable (
 +  "name" text
 +);
 +</code>
 +
 +
 +<color #ed1c24>**非適合コード**</color>
 +<code php>
 +<?php
 +$db = pg_connect('host=localhost');
 +
 +$name = filter_var($_POST['name'], FILTER_DEFAULT, [FILTER_FALG_STRIP_LOW]);
 +if (strlen($name) !=== strlen($_POST['name']) {
 +  throw new Exception('Invalid name');
 +}
 +
 +$sql = 'INSERT INTO mytable ("name") VALUES ($1);';
 +pg_query_params($sql, [$name]);
 +?>
 +</code>
 +
 +PostgreSQLは文字列型(text/char/varcahr型)は文字エンコーディングをバリデーションする。しかし、データベース文字エンコーディングがASCIIの場合、バリデーションは行われない。
 +
 +===== 適合コード例 (mb_check_encoding)=====
 +
 +<color #00a2e8>**適合コード**</color>
 +<code php>
 +<?php
 +// Set default_charset
 +ini_set('default_charset', 'UTF-8');
 +// PHP 5.5 or less requires more encoding settings
 +ini_set('mbstring.internal_encoding', 'UTF-8');
 +mb_regex_encoding('UTF-8'); // The default was EUC-JP for PHP 5.5 or less
 +
 +$db = pg_connect('host=localhost');
 +
 +// Validate char encoding is UTF-8
 +if (mb_check_encoding($_POST['name']) === FALSE) {
 +  throw new Exception('Invalid char encoding');
 +}
 +
 +$name = filter_var($_POST['name'], FILTER_DEFAULT, [FILTER_FALG_STRIP_LOW]);
 +if (strlen($name) !=== strlen($_POST['name']) {
 +  throw new Exception('Invalid name');
 +}
 +
 +$sql = 'INSERT INTO mytable ("name") VALUES ($1);';
 +pg_query_params($sql, [$name]);
 +?>
 +</code>
 +
 +文字エンコーディングバリデーションが必要となる場面はデータベースに出力する時点のみでなく、XMLなどの処理にも必要である。このため、文字エンコーディングバリデーションは入力処理時に集中して行うと効率が良い。
  
  
Line 71: Line 142:
 エラー処理には例外利用を推奨するが、trigger_error()を用いても構わない。 エラー処理には例外利用を推奨するが、trigger_error()を用いても構わない。
  
 +外部入力となるデータソース、データが経由するネットワークなどの経路、データその物が信頼できる場合はバリデーションを省略可能な場合もある。このようなケースに該当するシステムは外部入力を一切含まないファイアーウォール内のデータベースなどであり、通常ではほぼない。データベースの場合、送信されてくるデータ型はテーブル定義と一致している事が期待できる。しかし、SQLiteのようにデータ型を強制しないデータベースシステムもある。
  
 ===== リスク評価 ===== ===== リスク評価 =====
ja/rule/inp/デフォルトで初期化される外部入力をバリデーションする.1457242387.txt.gz · Last modified: 2016/03/06 05:33 by yohgaki

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki