====== 入力文字エンコーディングをバリデーションする ====== PHPの文字列型は文字エンコーディング情報を持たないバイナリ型である。APIや外部システムが入力文字エンコーディングのバリデーションを行っている場合も多いが、文字エンコーディングを利用したインジェクション攻撃のリスクを無くす為に入力文字エンコーディングはバリデーションしなければならない。 外部からの文字列型データの文字エンコーディングは全て正しい文字エンコーディングであることをバリデーションしなければならない。 ===== 非適合コード例 ===== Your name is . filter_var関数のFILTER_DEFAULTのみでは$nameは$_GET['name']の値となる。FILTER_FLAG_STRIP_LOWでASCII値の32以下の文字が削除される。$nameはASCII値の32以下の文字を含まない文字列となるが、文字エンコーディングはバリデーションされない。 htmlspecialchars関数は文字エンコーディングをinternal_encoding設定(default_charsetのみ設定されている場合はdefault_charset)の文字エンコーディングでバリデーションするが、PHP 5.4 と PHP 5.5 のデフォルト値は、 UTF-8 で、それより前のバージョンの PHP のデフォルト値は ISO-8859-1 でした。 ===== 適合コード例 ===== 100) { throw new Exception('Too long string'); } // 文字エンコーディングチェック if (mb_check_encoding($_GET['name']) === FALSE) { throw new Exception('Invalid encoding'); } $name = filter_var($_GET['name'], FILTER_DEFAULT, [FILTER_FLAG_STRIP_LOW]); // 不要な文字を含む場合のバリデーション if (strlen($name) !== strlen($_GET['name'])) { throw new Exception('Contains invalid chars'); } ?> Your name is . PHP 5.6以降の場合、ini_set('default_charset', 'UTF-8')で全ての文字エンコーディングのデフォルト値がUTF-8になる。mb_check_encoding($_GET['name'])でUTF-8エンコーディングであることが確認される。 filterモジュールには文字列バリデーションオプションがない。サニタイズフィルターを適用後、文字列の長さの変化でバリデーションすることが可能である。 ===== 例外 ===== $_GET/$_POST/$_COOKIEなどブラウザからの変数は正しい文字エンコーディングであることが保証されない。しかし、データベースなどの場合、保存時に文字エンコーディングがバリデーションされる物もある。この場合、入力文字エンコーディングのバリデーションを省略しても構わない。 ===== リスク評価 ===== 文字エンコーディングを利用したインジェクション攻撃が可能となるケースはプログラム内のどこにあるのか判別しづらい。ライブラリや外部システムなどの入れ替えで文字エンコーディング脆弱になる場合もある。 ^ Rule ^ Severity ^ Likelihood ^ Remediation Cost ^ Priority ^ Level ^ | IDS05-J | medium | likely | medium | P4 | L3 | ===== 関連ガイドライン ===== ===== 参考文献 =====